gint : un noyau pour développer des add-ins
Posté le 20/02/2015 17:30
Ce topic fait partie de la série de topics du fxSDK.
En plus des options de programmation intégrée comme le Basic Casio ou Python, la plupart des calculatrices Casio supportent des
add-ins, des programmes natifs très polyvalents avec d'excellentes performances. Les add-ins sont généralement programmés en C/C++ avec l'aide d'un ensemble d'outils appelé SDK.
Plusieurs SDK ont été utilisés par la communauté avec le temps. D'abord le
fx-9860G SDK de Casio avec fxlib pour Graph monochromes (plus maintenu depuis longtemps). Puis le
PrizmSDK avec libfxcg pour Prizm et Graph 90+E (encore un peu actif sur Cemetech). Et plus récemment celui que je maintiens, le
fxSDK, dont gint est le composant principal.
gint est un unikernel, ce qui veut dire qu'il embarque essentiellement un OS indépendant dans les add-ins au lieu d'utiliser les fonctions de l'OS de Casio. Ça lui permet beaucoup de finesse sur le contrôle du matériel, notamment la mémoire, le clavier, l'écran et les horloges ; mais aussi de meilleures performances sur le dessin, les drivers et la gestion des interruptions, plus des choses entièrement nouvelles comme le moteur de gris sur Graph monochromes.
Les sources de gint sont sur la forge de Planète Casio :
dépôt Gitea Lephenixnoir/gint
Aperçu des fonctionnalités
Les fonctionnalités phares de gint (avec le fxSDK) incluent :
- Toutes vos images et polices converties automatiquement depuis le PNG, sans code à copier (via fxconv)
- Un contrôle détaillé du clavier, avec un GetKey() personnalisable et un système d'événements à la SDL
- Une bibliothèque standard C plus fournie que celle de Casio (voir fxlibc), et la majorité de la bibliothèque C++
- Plein de raccourcis pratiques, comme pour afficher la valeur d'une variable : dprint(1,1,"x=%d",x)
- Des fonctions de dessin, d'images et de texte optimisées à la main et super rapides, surtout sur Graph 90+E
- Des timers très précis (60 ns / 30 µs selon les cas, au lieu des 25 ms de l'OS), indispensables pour les jeux
- Captures d'écran et capture vidéo des add-ins par USB, en temps réel (via fxlink)
Avec quelques mentions spéciales sur les Graph monochromes :
Un moteur de gris pour faire des jeux en 4 couleurs !
La compatibilité SH3, SH4 et Graph 35+E II, avec un seul fichier g1a
Une API Unix/POSIX et standard C pour accéder au système de fichiers (Graph 35+E II seulement)
Et quelques mentions spéciales sur les Graph 90+E :
Une nouvelle police de texte, plus lisible et économe en espace
Le dessin en plein écran, sans les bordures blanches et la barre de statut !
Un driver écran capable de triple-buffering
Une API Unix/POSIX et standard C pour accéder au système de fichiers
Galerie d'add-ins et de photos
Voici quelques photos et add-ins réalisés avec gint au cours des années !
Arena (2016) — Plague (2021)
Rogue Life (2021)
Momento (2021)
Communication avec le PC (cliquez pour agrandir)
Utiliser gint pour développer des add-ins
Les instructions pour installer et utiliser gint sont données dans les divers tutoriels recensés dans le
topic du fxSDK. Il y a différentes méthodes de la plus automatique (GiteaPC) à la plus manuelle (compilation/installation de chaque dépôt). Le fxSDK est compatible avec Linux, Mac OS, et marche aussi sous Windows avec l'aide de WSL, donc normalement tout le monde est couvert
Notez en particulier qu'il y a des
tutoriels de développement qui couvrent les bases ; tout le reste est expliqué dans les en-têtes (fichiers
.h) de la bibliothèque que vous pouvez
consulter en ligne, ou dans les ajouts aux changelogs ci-dessous.
Changelog et informations techniques
Pour tester les fonctionnalités et la compatibilité de gint, j'utilise un add-in de test appelé gintctl (
dépôt Gitea Lephenixnoir/gintctl). Il contient aussi une poignée d'utilitaires d'ordre général.
Ci-dessous se trouve la liste des posts indiquant les nouvelles versions de gint, et des liens vers des instructions/tutoriels supplémentaires qui accompagnent ces versions.
Anecdotes et bugs pétés
Ô amateurs de bas niveau, j'espère que vous ne tomberez pas dans les mêmes pièges que moi.
TODO list pour les prochaines versions (2023-04-03)
gint 2.11
- Changements de contextes CPU. À reprendre du prototype de threading de Yatis pour permettre l'implémentation d'un véritable ordonnanceur. Demandé par si pour faire du threading Java.
- Applications USB. Ajouter le support de descripteurs de fichiers USB. Potentiellement pousser jusqu'à avoir GDB pour debugger.
- Support de scanf() dans la fxlibc. Codé par SlyVTT, plus qu'à nettoyer et fusionner.
Non classé
- Regarder du côté serial (plus facile que l'USB) pour la communication inter-calculatrices (multijoueur) et ultimement l'audio (libsnd de TSWilliamson).
- Un système pour recompiler des add-ins mono sur la Graph 90+E avec une adaptation automatique.
- Support des fichiers en RAM pour pouvoir utiliser l'API haut-niveau sur tous les modèles et éviter la lenteur de BFile à l'écriture quand on a assez de RAM.
Citer : Posté le 12/07/2015 15:55 | #
Bon, je vais pas laisser tomber cette idée.
Ayant constaté que ça ne fonctionnait pas du tout sur SH4, j'ai repris de zéro.
Pour l'instant je ne touche pas la vbr ni rien, je tente juste de mettre du code en face de ma nouvelle vbr et de voir si je peux l'exécuter.
Parce que voilà le problème : si je mets le code dans la ram classique à 0x08100000, il plante quand je l'exécute. En revanche, si je le mets dans la ram réelle, qui ne nécessite pas l'utilisation du mmu, à 0x88008000, là ça fonctionne.
Là où ça se corse c'est que Kristaba utilisait cette adresse, ce qui fonctionne bien sur SH3, mais sur SH4 quand l'add-in s'arrête il n'y a plus d'add-ins dans le menu...
Ajouté le 12/07/2015 à 16:48 :
Hmph, bingo.
Il y a les handles du filesystem en plein milieu de cette zone mémoire.
Par contre, ils sont trop loin de l'origine pour que je les écrase normalement.
Citer : Posté le 12/07/2015 16:51 | #
Rassure-moi, tu fais les tests sur l'émulateur ?
C'est un coup à bousiller sa calto ça
Si t'arrive à sortir un truc potable, je testerai bien avec Arcuz
Citer : Posté le 12/07/2015 16:53 | #
Oh non, je ne risque rien. C'est de la RAM.
Si t'arrive à sortir un truc potable, je testerai bien avec Arcuz
Tu veux vraiment qu'il soit numéro 1 celui-là, hein
Bon, alors pour donner une idée de la memory map :
→ 0x88008000 : début de la ram réelle et adresse de début de la section .data
→ 0x88008700 : fin de la section .data
→ 0x88008bec : premier handle du système
Donc a priori, c'est pas vraiment ça...
Ajouté le 12/07/2015 à 16:54 :
Et puis aucune chance que ça se passe pareil sur émulateur. Trop bas niveau pour ça, je pense.
Ajouté le 12/07/2015 à 16:55 :
Ah oui, j'ai trouvé l'adresse la liste d'add-ins que je croyais avoir écrasée : elle est à 0x88006d9c, soit avant la zone mémoire que j'utilise...
Ajouté le 12/07/2015 à 17:04 :
Bon, le problème semble reporté. Au lieu d'utiliser le 32 kio disponibles, je me contente des 12 kio de la fin et ça a l'air de passer.
Bon, de toute façon faut pas déconner, 12 kio ça fait 0x3000 octets. Sachant que l'alignement de la vbr en utilise d'office 0x700, il m'en reste grosso modo 0x2300 (plus de 8000 octets) pour des procédures additionnelles, ce qui est largement suffisant.
Ajouté le 12/07/2015 à 17:28 :
Alors, j'ai réussi à mettre en place un interrupt handler qui fait du boulot.
J'ai aussi réussi à rediriger vers l'ancienne vbr en restaurant le registre sans nettoyer la source de l'interruption (ce qui rappelle automatiquement le handler du système). Thoériquement à partir de ça je peux me démerder pour rappeler un handler du système sans trop de problèmes et de manière générale.
En toute sincérité, je trouve la SH4 bien moins énervante à manipuler que la SH3.
Mon interrupt handler ne fait rien pour l'instant, juste afficher à l'écran le contenu des registres intevt et intevt2 qui sont censés m'indiquer quelle est la source de l'interruption. Pour l'instant, ils valent encore zéro tout le temps, mais j'y travaille.
J'ai aussi un compteur qui s'incrémente à chaque interruption et je peux dire que ça va vite !
Comme je détourne la vbr et que je ne traite aucun event, pour l'instant, je ne peux pas terminer le programme (donc je reset manuellement la machine à chaque essai), du coup je ne sais pas si ça se termine proprement.
Citer : Posté le 12/07/2015 19:26 | #
C'est cool que tu es repris le projet !
Bon courage.
Ajouté le 12/07/2015 à 19:30 :
Si tu arrives à faire un moteur de gris pour SH4 propre, je me mets au C de suite.
Citer : Posté le 12/07/2015 20:12 | #
C'est cool que tu es repris le projet !
Bon courage.
Merci !
Si tu arrives à faire un moteur de gris pour SH4 propre, je me mets au C de suite.
Je vais être franc... c'est bien parti. Très bien parti.
Citer : Posté le 12/07/2015 20:22 | #
Tu veux que du monde utilise le fxSDK ? Tu le rend exclusif
Blague à part, ça serai vraiment génial
Citer : Posté le 12/07/2015 20:27 | #
Tu veux que du monde utilise le fxSDK ? Tu le rend exclusif
Ha ha mais spoile pas tout voyons
J'ai encore quelques problèmes (la machine ne détecte plus l'add-in ?), je vous tiens au courant de toute façon.
Ajouté le 12/07/2015 à 20:32 :
Mon interrupt handler ne fait rien pour l'instant, juste afficher à l'écran le contenu des registres intevt et intevt2 qui sont censés m'indiquer quelle est la source de l'interruption. Pour l'instant, ils valent encore zéro tout le temps, mais j'y travaille.
Ben voyons, utiliser les adresses du 7705 en bossant sur un 7724
Bon, c'est pas encore fini mais j'ai une valeur. En gros maintenant je fais un gros switch sur cette valeur et je vais commencer à avoir de quoi coder des fonctions de standard custom pour les touches ou les timers par exemple... fini fxlib de ce côté-là si ça fonctionne !
Après, j'empile le moteur de gris par-dessus, ça c'est loin, très loin d'être compliqué en comparaison...
Citer : Posté le 12/07/2015 20:39 | #
Quand je te dis que tu ne regarde pas au bon endroit ><
Par contre, t'es obligé de traiter les cas selon le proco ? Du coup tu ferai quoi, deux versions (SH3 et SH4) ou une seule un peu plus lente (quoi que, en static ça doit aller) qui traite les deux ? Je parie sur la seconde, mais sait-on jamais
Citer : Posté le 12/07/2015 20:43 | #
Non mais le problème c'est que c'est pas possible d'en avoir une seule. Les adresses des registres changent, les codes d'interruption aussi.
Pour l'instant ce que je fais n'est compatible qu'avec la SH4.
Btw il n'y a pas de table de codes d'interruptions directement dans la doc du SH4 donc il va falloir éplucher ça en détail... :-'
Citer : Posté le 12/07/2015 20:44 | #
Y'a pas moyen de faire une variable qui trie les codes d'interruption en fonction de la plateforme ?
Citer : Posté le 12/07/2015 20:59 | #
Y'a pas moyen de faire une variable qui trie les codes d'interruption en fonction de la plateforme ?
Ça peut se faire mais c'est un peu tendu. Somme toute, je pense que c'est possible, mais il faut un moyen d'identifier la plateforme et comme c'est censé être une lib donc déjà précompilée... je verrai ça, mais je peux aussi avoir deux version différentes. C'est chiant mais c'est faisable.
Par contre le SH4 est magnifique ! FPU, KEYSC (keyboard scanner) intégrés, ça va être une partie de plaisir à gérer !
Ajouté le 13/07/2015 à 11:01 :
Bon, je suis en train de m'occuper de la gestion du clavier. Lorsque l'interruption vient du keyboard scanner (KEYSC), le registre intevt prend la valeur 0x0be0, donc c'est facile à détecter.
J'arrivais à arrêter les interruptions (c'est-à-dire remettre l'interrupt flag à 0) mais j'en avais plus après.
Et puis je me suis rendu compte que les 4 registres du KEYSC font tous 2 octets mais qu'ils sont séparés de 4. J'avais une structure de 4 shorts, donc ça pouvait pas fonctionner...
Maintenant, elles sont de retour, et j'arrive même plus à les arrêter
Citer : Posté le 13/07/2015 12:21 | #
Pour avoir une idée, t'obtiens environ combien d'interruptions par seconde ? (Avec ton compteur)
Sinon, tu préviendras quand il faudra essayer sur SH3, j'aimerai tester si ça derange pas
Citer : Posté le 13/07/2015 12:26 | #
Ben, en fait pour l'instant la même se répète à l'infini : donc je peux pas te dire, d'autant plus que je les ai toutes bloquées sauf celles de clavier... et pour cause : toute interruption doit être nettoyée par le programme : donc, si une interruption non gérée survient, elle se répètera à l'infini. Et ça, c'est pas accpetable...
Pour l'instant sur SH3, rien. Je suis d'autant plus embêté que la gestion du clavier est tout à fait différente mais je pense que je saurai écrire un moteur équivalent.
Bon, d'ailleurs j'ai encore des problèmes pour localiser les registres avec ma structure. Ils sont pas au bon endroit... cela dit c'est plutôt une bonne nouvelle parce que ça signifie que je sais où est le problème.
Citer : Posté le 13/07/2015 12:29 | #
Pour peu que le problème vienne de là
Citer : Posté le 13/07/2015 12:32 | #
Pour peu que le problème vienne de là
Hmph, maintenant je les ai réalignés mais même problème qu'avant : une fois qu'une interruption est arrivée le reste est ignoré.
Ajouté le 13/07/2015 à 22:44 :
Bon, j'arrive définitivement pas à contrôler le KEYSC (gestionnaire de clavier)... j'ai beau appliquer à la lettre les instructions de la doc, ça ne fonctionne pas.
Je n'ai que quelques informations :
→ La première interruption n'est reçue que si j'appelle GetKey()
→ Appeler plusieurs fois GetKey() ne permet pas de récupérer plusieurs interruptions, sauf si les appels sont dans la routine de traitement de la première interruption
→ J'arrive pas du tout à modifier le registre KYCR2 (registre de contrôle 2 du module) qui est pourtant crucial
Ajouté le 16/07/2015 à 09:41 :
Bon, je laisse tomber la gestion du clavier pour l'instant.
La raison, c'est que je suis convaincu que GetKey() fait ce qu'il veut avec les registres et que je n'ai pas réussi à récupérer une interruption avec une fonction équivalente.
Je vais commencer par gérer les timers (qui devraient être plus simples), histoire de pouvoir afficher à l'écran des informations sur le clavier sans avoir à utiliser GetKey().
Ajouté le 16/07/2015 à 11:08 :
Bon, je crois que j'ai définitivement la preuve que GetKey() se fout complètement de ma figure. Deux paramètres pour refuser les interruptions du clavier et il tourne toujours...
Pour être plus formel, je pense que GetKey() configure lui-même le module de gestion du clavier pour s'assurer, par exemple, qu'une fois le soc mis en pause appuyer sur une touche le réveillera bien, ou que les valeurs renvoyées lui conviendront bien. Du coup, comme pour une raison que je ne connais pas je ne peux pas récupérer d'interruptions du clavier sans avoir appelé GetKey(), je ne contrôle rien du tout.
Notez du coup que ça veut dire que GetKey() configure correctement le clavier, lui. Sauf que je n'ai pas sa source (son symbole dans fxlib n'est qu'un bête appel de syscall), et que même si je crois savoir possible de désassembler des syscalls ce sera le foutoir.
Ajouté le 16/07/2015 à 11:43 :
Bon, alors le problème est pire que ça : impossible d'écrire une valeur dans un registre.
Je commence à me demander si j'ai les bonnes addresses. Mais c'est celles de la doc. Bon, alors au moins est-ce que c'est bien un 7724 ?
Can you confirm me that :
- SH7305 is Fx9860GII SH4
- SH7337 is Fx9860G SH3
- SH7355 is Fx9860GII SH3
Yes.
Et merde.
Citer : Posté le 16/07/2015 12:14 | #
Mea culpa
J'avais quand même bien dit que je n'étais pas sur
Citer : Posté le 16/07/2015 12:16 | #
Mea culpa
J'avais quand même bien dit que je n'étais pas sur
Non mais c'est pas de ta faute
Bon, vu que Sentaro21 a du bûcher dur pour sortir FTune2, qu'il précise bien être destiné au SH7305, je vais lui envoyer un mail histoire de voir s'il a la doc.
Citer : Posté le 16/07/2015 12:18 | #
T'as ses coordonnés ? Je dois pouvoir les trouver sinon.
Citer : Posté le 16/07/2015 12:19 | #
Il a laissé son mail dans la description de Ftune2.
Citer : Posté le 16/07/2015 12:22 | #
Parfait alors.
Faudra d'ailleurs que je pense à uploader les infos sur le CP sur le site
Citer : Posté le 26/07/2015 09:16 | #
Bon, j'ai du nouveau.
Le SH4 n'est sans doute pas un SH7724 mais un SH7305, or ce dernier n'existe tout simplement pas, où que je cherche. Si vraiment ça me branche je taperai au hasard dans les docs de tous les mpus recensés par TeamFX pour trouver le bon mais je lui demanderai quand même, on ne sait jamais.
D'ici là, je suis repassé sur SH3.
La zone mémoire utilisée pour la SH4 fonctionne aussi. Donc l'appel du handler est commun. J'arrive à détecter les pressions de touches mais je ne me suis pas encore penché sur la reconnaissance de la touche.
J'arrive aussi à utiliser un timer de manière tout à fait arbitraite et comme il me plaît. Ça commence à être intéressant.
Ajouté le 26/07/2015 à 16:03 :
J'ai bossé avec l'écran ensuite. ML ne fonctionnait pas. En revanche, la fonction assembleur de kucalc dans revolution-fx, elle, fonctionnait. (Et dire qu'il disait à une époque, « it's already optimized since it's in pure assembleur », il auraît pu optimiser un peu l'assembleur quand même, un compilateur aurait fait presque aussi bien.) Du coup je l'ai réécrite à ma façon (c'est-à-dire plus linéaire et donc compréhensible) et j'arrive à manipuler l'écran.
J'ai mis mes timers, les valeurs de Kristaba sont pas géniales. Du coup je vais publier un add-in de test bientôt. Là, tout de suite, j'ai un dragon en 4 couleurs sous les yeux, c'est l'extase. (voyez le chat s'il n'est pas encore trop tard, Kirafi peut témoigner que je ne mens pas)