MQ : Émulateur add-ins universel
Posté le 28/05/2025 20:22
Parmi les
projets de 2025 il y a tout un plan pour préserver les contenus du site, notamment les vieux programmes. La base de programmes de Planète Casio n'est pas beaucoup maintenue et on ne traque pas vraiment ce qui est encore jouable ou pas.
Les projets d'émulateurs c'est pas nouveau, c.f.
*,
*,
* et j'en oublie. Initialement je pensais repartir d'un existant, mais finalement j'en ai commencé un from scratch en voyant le cahier des charges :
- Il faut pouvoir émuler à la fois les Graph mono et les Prizm et à la fois les SH3 et les SH4 ;
- Il faut que ça puisse tourner sur le site donc compiler vers WebAssembly et optimiser raisonnablement (téléphones etc. ont pas des perfs de dingue) ;
- Il faut émuler pas mal de trucs matériels, donc assez bas-niveau, pour bien couvrir les add-ins et potentiellement l'appli PRGM pour émuler les programmes Basic ;
- Et si on fait tout ça ce serait criminel de pas s'en servir pour développer/debugger, ce pour quoi une GUI plus grosse que juste l'écran est nécessaire (et/ou gdb).
Les détails techniques, pour ceux que ça intéresse, c'est : pur C, tourne sur
Azur par facilité (GUI en OpenGL avec
ImGui + compile pour Linux et WebAssembly), le décodeur est un arbre de
switch généré automatiquement et la mémoire est hiérarchique par blocs de 1 Mo, 4 ko, et 1 octet.
L'état actuel (Mai 2025) c'est : on peut faire tourner quelques add-ins sur CG, y'a des syscalls mais peu, y'a une partie du matériel émulé pour faire tourner gint ; en gros si vous prenez un add-in aléatoire ça va probablement pas marcher, mais pas loin.
Voici le dépôt et au passage à quoi ressemble l'interface : y'a tous les trucs techniques nécessaires pour debugger.
» Dépôt Git Lephenixnoir/mq «

J'ai pas encore de build pour le web sur lequel vous pouvez cliquer et tester tout de suite, mais vous pouvez compiler depuis le dépôt.
Voilà plus de nouvelles bientôt j'espère.
Fichier joint
Citer : Posté le 28/05/2025 20:24 | #
Notez que je suis intéressé par des informations de performance donc si quelqu'un a un add-in de benchmark sous la main (CalcLoverHK avait un Dhrystone je crois ?) ou un truc graphique qui fait des choses intéressantes sans intervention humaine ce serait utile.
Citer : Posté le 28/05/2025 20:36 | #
Joli boulot. C'est clair qu'un bel outil comme ça pourrait vraiment nous aider à garder l'histoire des addins sur Casio.
Pour le Benchmarking, je sais pas si tu as tout pour faire tourner, mais il y a BenchFX que j'ai release avec les sources il y a pas si longtemps.
C'est là que ça se passe : https://git.planet-casio.com/Slyvtt/BenchFX
Je croyais que j'avais fait un fil pour en parler mais en fait non : https://www.planet-casio.com/Fr/programmes/programme4539-1-benchfx-slyvtt-utilitaires-graphisme.html
C'est une reprise de mon addin de démo qui est prévu pour tourner en boucle et stocker les infos de frame rate à la fin, ça crache un fichier avec les data module par module. Il faut RAM étendue et FS par contre.
Comme les sources sont dispos, tu peux faire mumuse avec.
Hâte de tester.
Citer : Posté le 29/05/2025 09:24 | #
Oh lala mais il faut pas sortir des projets comme ça, je vais passer toutes mes nuits sur Planet Casio
Citer : Posté le 30/05/2025 01:25 | #
Très joli projet, je suis impressionné par l'état d'avancement de cette "v1", hâte de suivre son évolution !
Et pourquoi pas y contribuer si l'enfer des interruptions est déjà fonctionnel
Citer : Posté le 30/05/2025 13:25 | #
Content de voir que ça vous intéresse !
Pour le Benchmarking, je sais pas si tu as tout pour faire tourner, mais il y a BenchFX que j'ai release avec les sources il y a pas si longtemps.
Aaah mais oui c'est vrai. Ma mémoire est vraiment mauvaise ces derniers temps. C'est bien pratique parce que je pense que c'est un meilleur benchmark pour les jeux.
Je me demande, comment l'emulateur fait pour savoir quelle calculatrice il doit émuler, il ne regarde que l'extension de fichier ou alors il y a un processeur qui comprend les instructions de tous les modèles en même temps ?
Pour l'instant il ne fait que SH4. Pour le modèle général (notamment le type d'écran) ce sera par l'extension oui, pour SH3/SH4 mon plan c'est de démarrer en mode "hybride" avec seulement une partie du matériel, et si je détecte des accès matériel ou des syscalls qui marchent que sur l'un des deux je finis de charger le reste du matériel. Si je vois que l'add-in essaie de détecter je mettrais SH4 par défaut a priori.
Et pourquoi pas y contribuer si l'enfer des interruptions est déjà fonctionnel
Oui les interruptions marchent déjà ! Si tu veux te plonger dedans tu es le bienvenu, notamment y'a plein de trucs de haut niveau (tester, des benchmarks, les layouts clavier notamment) qui sont dispos à faire et pas trop durs.
Citer : Posté le 30/05/2025 14:57 | #
Impressionnant !
Tu as dû passer beaucoup de temps à faire du reverse engineering.
Cet outil pourrait être utile non seulement pour la conservation des programmes, mais aussi pour le développement futur, notamment pour le débogage.
Albert Einstein
Citer : Posté le 30/05/2025 17:34 | #
Voilà un projet qui promet, bravo! Du coup ça donne évidemment envie de tester. J'ai réussi à le compiler, mais ensuite je n'ai pas réussi à lancer gintclt comme sur le screenshot, l'emulateur n'apparait pas. J'ai lancé
./mq-headless /shared/tmp/gintctl.g3a
depuis build-linux (config: linux debian 12 dans WSL). Est-ce normal?
La trace:
Waiting 1 billion cycles...
debug: icbi instruction used and ignored
warning: [PC=003124f6] unhandled read @ a4150044 -> returning 0
...
warning: [PC=00318b9e] unhandled read @ a4d8005e -> returning 0
debug: read_r61524: read register 210 (TODO, returning 0)
debug: read_r61524: read register 211 (TODO, returning 0)
debug: read_r61524: read register 212 (TODO, returning 0)
debug: read_r61524: read register 213 (TODO, returning 0)
warning: [PC=003163c4] unhandled read @ a413fedc -> returning 0
...
warning: [PC=00316b32] unhandled read @ a4490004 -> returning 0
debug: DMA Channel 1: Transfer Ended
debug: Handling interrupt 0x820
debug: r61524: Finished full frame
debug: DMA Channel 0: Transfer Ended
...
debug: Handling interrupt 0xfa0
Total time: 1400 ms
Citer : Posté le 30/05/2025 17:45 | #
Le headless est je pense sans sortie graphique donc c'est normal.
il faut lancer la version ./mq
Il faut par contre configurer correctement azur avec imgui (sur la branche docking si je me souviens bien car sinon ça râle à la compilation).
Il faut bien importer toutes les sous libs et les 3rdParty.
Citer : Posté le 30/05/2025 17:53 | #
Le headless en effet c'est sans GUI, c'est un truc interne à moi pour profiler. Pour lancer gintctl il faut que gintctl.g3a soit dans le dossier courant. Un des trucs pas polis encore c'est qu'il faut exécuter depuis le dossier du projet avec build-linux/mq sinon il trouve pas les assets.
Citer : Posté le 30/05/2025 18:23 | #
j'ai surtout galéré avec imgui perso, car je comprenais pas pourquoi j'avais une erreur de compilation, quand j'ai vu (enfin) que la branche par défaut ne contient pas les fonctionnalités de docking de l'interface. Du coup en recompilant Azur avec cette modif de branche, ça allait tout de suite mieux.
Pourtant ça fait un moment que c'est dedans, mais c'est toujours pas basculé dans la branche master.
Citer : Posté le 30/05/2025 18:52 | #
Alors, je viens de réessayer, cette fois j'ai une stack overflow
build-linux/mq gintctl.g3a
MQ on Azur 0.1
azur_init: error: SDL_GL_SetSwapInterval: That operation is not supported
compileShader: Compiling shader: <inline>
compileShader: Compiling shader: <inline>
link: Linking program
compileShader: Compiling shader: gui/glsl/vs_tiles.glsl
compileShader: Compiling shader: gui/glsl/fs_tiles.glsl
link: Linking program
azur_main_loop: error: SDL_GL_SetSwapInterval(0): That operation is not supported
azur_main_loop: error: Defaulting to non-vsync
AddressSanitizer:DEADLYSIGNAL
=================================================================
==37==ERROR: AddressSanitizer: stack-overflow on address 0x7ffebfc95d50 (pc 0x7ffebfc95d50 bp 0x7ffebfc95d10 sp 0x7ffebfc957c8 T0)
#0 0x7ffebfc95d50 ([stack]+0x19d50)
#1 0x7b29cd4a90ca in __cxa_throw (/lib/x86_64-linux-gnu/libstdc++.so.6+0xa90ca)
SUMMARY: AddressSanitizer: stack-overflow ([stack]+0x19d50)
==37==ABORTING
Citer : Posté le 30/05/2025 18:56 | #
T'as dit avant que t'utilises la wsl, est ce que t'as moyen d'utiliser des programmes X11 avec ?
Et est ce que t'as accès à de l'accélération matérielle avec la wsl ?
Citer : Posté le 30/05/2025 18:58 | #
Je découvre des trucs moi... Parisse si tu configures avec -DCMAKE_BUILD_TYPE=Debug est-ce que tu as quelque chose de plus utile ?
Citer : Posté le 30/05/2025 19:18 | #
Voilà ce que me renvoie gdb:
(gdb) r gintctl.g3a
Starting program: /home/parisse/mq/build-linux/mq gintctl.g3a
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
MQ on Azur 0.1
[Detaching after fork from child process 529]
[New Thread 0x7ffff41ff6c0 (LWP 530)]
[New Thread 0x7fffd7a616c0 (LWP 531)]
[Thread 0x7fffd7a616c0 (LWP 531) exited]
[New Thread 0x7fffd7a616c0 (LWP 532)]
azur_init: error: SDL_GL_SetSwapInterval: That operation is not supported
compileShader: Compiling shader: <inline>
compileShader: Compiling shader: <inline>
link: Linking program
compileShader: Compiling shader: gui/glsl/vs_tiles.glsl
compileShader: Compiling shader: gui/glsl/fs_tiles.glsl
link: Linking program
azur_main_loop: error: SDL_GL_SetSwapInterval(0): That operation is not supported
azur_main_loop: error: Defaulting to non-vsync
Thread 1 "mq" received signal SIGSEGV, Segmentation fault.
0x00007fffffff9ca0 in ?? ()
(gdb) bt
#0 0x00007fffffff9ca0 in ?? ()
#1 0x00007fffe663896d in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#2 0x00007fffe6638242 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#3 0x00007fffe6640a58 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#4 0x00007fffe6640907 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#5 0x00007ffff7f1be37 in _Unwind_RaiseException () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#6 0x00007ffff72a90cb in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007fffe42926d8 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#8 0x00007fffe42a71e5 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#9 0x00007fffe3d2c52b in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#10 0x00007fffe3d32ce6 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#11 0x00007fffe3d41460 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#12 0x00007fffe3f4a513 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#13 0x00007fffe3f4bd73 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#14 0x00007fffe4099ca4 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#15 0x00007fffe409a27d in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#16 0x00007fffe409a40d in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#17 0x00007fffe40f74d2 in ?? () from /usr/lib/wsl/drivers/u0373951.inf_amd64_8acf4e15d023c549/B373799/amdxc64.so
#18 0x00007fffe68bd5aa in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#19 0x00007fffe68bce45 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#20 0x00007fffe68bcc24 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#21 0x00007fffe67ca6f4 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#22 0x00007fffe67836c7 in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#23 0x00007ffff43ef4b2 in ?? () from /usr/lib/wsl/lib/libd3d12.so
#24 0x00007ffff43ef1c6 in ?? () from /usr/lib/wsl/lib/libd3d12.so
#25 0x00007fffe67ba5fc in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#26 0x00007fffe67d01ea in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#27 0x00007fffe67cea9c in ?? () from /usr/lib/wsl/lib/libd3d12core.so
#28 0x00007ffff1d301fb in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
--Type <RET> for more, q to quit, c to continue without paging--
#29 0x00007ffff1d30730 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#30 0x00007ffff1d1e5f4 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#31 0x00007ffff182a49f in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#32 0x00007ffff18242fa in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#33 0x00007ffff1825336 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#34 0x00007ffff182c258 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#35 0x00007ffff135fa00 in ?? () from /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
#36 0x00007ffff52371bd in ?? () from /lib/x86_64-linux-gnu/libGLX_mesa.so.0
#37 0x00007ffff523b23b in ?? () from /lib/x86_64-linux-gnu/libGLX_mesa.so.0
#38 0x00007ffff7739be6 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#39 0x000055555558f4a7 in render () at /home/parisse/mq/gui/main.cc:448
#40 0x0000555555615df3 in azur_main_loop(std::function<void ()> const&, int, std::function<int ()> const&, int, int) ()
#41 0x000055555557b8ad in main () at /home/parisse/mq/gui/main.cc:667
(gdb)
Citer : Posté le 30/05/2025 19:40 | #
Du coup j'ai relancé une compilation dans une VM debian testing. Pas de segfault, mais l'écran de la calculatrice n'est pas affichée. Et il reste des warnings:
build-linux/mq gintctl.g3a
MQ on Azur 0.1
azur_init: error: SDL_GL_SetSwapInterval: That operation is not supported
compileShader: Compiling shader: <inline>
compileShader: Compiling shader: <inline>
link: Linking program
compileShader: Compiling shader: gui/glsl/vs_tiles.glsl
compileShader: Compiling shader: gui/glsl/fs_tiles.glsl
link: Linking program
azur_main_loop: error: SDL_GL_SetSwapInterval(0): That operation is not supported
azur_main_loop: error: Defaulting to non-vsync
=================================================================
==11483==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 604 byte(s) in 1 object(s) allocated from:
#0 0x7f633a0f4c57 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x7f63379ca538 (/lib/x86_64-linux-gnu/libGLX_mesa.so.0+0x38538) (BuildId: f8b678e57f8cefcadb045ca921e43c0691d812a3)
Direct leak of 448 byte(s) in 2 object(s) allocated from:
#0 0x7f633a0f4610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f63379c652e (/lib/x86_64-linux-gnu/libGLX_mesa.so.0+0x3452e) (BuildId: f8b678e57f8cefcadb045ca921e43c0691d812a3)
Indirect leak of 76160 byte(s) in 340 object(s) allocated from:
#0 0x7f633a0f4610 in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f63379c652e (/lib/x86_64-linux-gnu/libGLX_mesa.so.0+0x3452e) (BuildId: f8b678e57f8cefcadb045ca921e43c0691d812a3)
SUMMARY: AddressSanitizer: 77212 byte(s) leaked in 343 allocation(s).
Citer : Posté le 30/05/2025 19:52 | #
Ok ça c'est bon ! Le warning vsync pas de souci, les fuites de mémoire c'est dans mesa, c'est pas ma faute (et hors de mon contrôle).
Y'a pas d'écran et de clavier initialement parce que la machine est pas spécifiée, si tu fais "Reset add-in CG" ou "Reset and load gintctl.g3a" il va le configurer. Pour FX c'est pas encore fait je crois.
Edit : J'avais pas vu la stack trace, mais
#38 0x00007ffff7739be6 in ?? () from /lib/x86_64-linux-gnu/libSDL2-2.0.so.0
c'est dans le driver graphique...
Citer : Posté le 30/05/2025 21:14 | #
J'avais essayé sans succès, en fait il faut aussi cliquer sur Run et là gintctl marche, bravo!
Bon, khicas.g3a ne marche pas encore, mais c'est surement juste une question de temps...
Bon courage pour la suite du développement!
Citer : Posté le 02/06/2025 13:56 | #
J'ai fixé le build emscripten qui était en fait cassé depuis un moment. x)
Prochaine étape j'ai un bug dans Boson X à corriger et des instructions DSP à implémenter pour avoir le rendu d'images.
Autre cible pas trop lointaine le support mono SH4 qui devrait aller à peu près tout seul vu que le matériel est le même. (Le à peu près faisant référence à des subtilités que Drakalex007 a trouvé avec le fxlib qui embarque du code un peu trop bas-niveau pour être agréable)
Citer : Posté le 02/06/2025 15:02 | # |
Fichier joint
J'ai pu me plonger un peu dans l'architecture du projet et franchement chapeau, c'est déjà très fonctionnel et facilement modulable.
Actuellement l'émulateur peut lancer des addins CG (.g3a), mais pas d'addins FX (.g1a) (bien que tout le code soit pensé pour fonctionner avec les deux)
Je me suis donc amusé à ajouter un début de support pour les add-ins monochromes (et plus particulièrement ceux utilisant MonochromeLib).
J'ai notamment ajouté la gestion de l'écran LCD et du clavier, et j'ai déjà pu tester quelques addins sh3/sh4 qui semblent à première vue fonctionner correctement:
Je vais essayer de clean mes expérimentations et d'en faire une PR - dans un premier temps pour pouvoir discuter des modifications.
Une dernière chose, je note que les jeux sont trop rapides (peut-être dû au fait que RTC_GetTicks n'est pas encore implémenté?), je dirais que ce point est "prioritaire" pour une émulation agréable
Citer : Posté le 02/06/2025 16:16 | #
Il faudrait peut-être ajouter un mode activable qui réduit le nombre de cycles CPU ou le temps d'update de l'écran pour se rapprocher de la vitesse originale de la calculatrice pour les jeux qui n'utilisent pas de delta time.
Sinon, très impressionnant à ce que je vois sur les captures. L'UI est très clean, ça utilise quoi pour la faire ?