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 04/08/2018 23:49 | #
Seulement ça se complique au fur et à mesure que tu optimises... mais oui, à essayer.
Accessoirement tu peux récupérer le driver timer et basta. En l'occurrence gint n'est dans le principe pas nécessaire. L'OS peut emmerder mais avec un peu de chance non.
Citer : Posté le 05/08/2018 00:41 | #
Pourquoi tu pourrais pas compiler windmill sous gint ?
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 05/08/2018 08:36 | #
Tu as release le nouveau gestionnaire d'interruption ? Si oui, je ferai quelques tests de son sur S4C
Citer : Posté le 05/08/2018 10:46 | #
Pourquoi tu pourrais pas compiler windmill sous gint ?
GCC semble optimiser des choses dans le code de Windmill, et bien que ça compile, ça ne marche pas. En général c'est que le code oublie de préciser des « contraintes » et le compilateur saute dessus pour optimiser plus, mais finit par casser le programme. Avec le SDK le problème ne se pose pas parce qu'il n'optimise rien...
Tu as release le nouveau gestionnaire d'interruption ? Si oui, je ferai quelques tests de son sur S4C
Tu peux toujours pull la branche compat du dépôt, mais il n'y a pas de clavier...
Citer : Posté le 05/08/2018 11:52 | #
N'est-il pas possible de compiler en précisant de n'opérer aucune optimisation ?
Citer : Posté le 05/08/2018 11:56 | #
Je l'ai fait, de mémoire, mais même de base, il ne reste pas passif. C'est peut-être un truc à la con qui bloque ?
Ajouté le 09/08/2018 à 16:18 :
Pas de progrès immédiat à annoncer, mais je travaille sur le clavier, sur SH4 le principe (acquérir les touches pressées) marche.
Maintenant j'essaie de structurer le programme autour correctement. J'ai un buffer dans lequel je peux stocker :
- Soit l'historique des états de clavier
- Soit les évènements (touche pressée, maintenue, relâchée...)
Jusque-là j'étais sur l'historique des états mais le buffer n'a qu'une seconde de capacité même quand il ne se passe rien. C'est gênant. Un buffer d'évènements ne se remplit pas s'il ne se passe rien... c'est plus avantageux.
J'envisage également de générer au lieu de stocker les événements de répétition de touches, c'est à étudier.
Au milieu de tout ça il reste qu'il faut être précautionneux dans le design parce que si par exemple l'instant où je relâche une touche est manqué (parce que le buffer est plein donc l'information est perdue par exemple), la touche risque de ne jamais être considérée comme relâchée. Si on s'y prend correctement ce genre de problèmes se corrigent spontanément, mais ça demande un peu de soin.
Voilà pour cette petite update
Citer : Posté le 09/08/2018 22:13 | #
Ok. Quoi qu'il arrive, tu nous tiens au jus, suivant l'implémentation finale (ça a changé pas mal de fois il me semble ) ça changera l'architecture des projets. (J'ai toujours Osu! sur le feu, j'avance doucement mais sûrement, pour l'instant y'a pas de quoi nourrir une RDP, donc j'attends encore un chouille)
Citer : Posté le 09/08/2018 22:19 | #
No problem pour le jus ! Je sais que j'ai tendance à changer assez vite mes APIs, il faudra que je m'adapte quand ce sera release et utilisé... o_o"
Citer : Posté le 12/08/2018 21:10 | #
Bon, c'est un peu chiant, mais du coup voilà.
Procédure d'installation
$ cd gint
$ ./configure
$ make
# make install
Compilation (à partir des sources de Calto Hero, qui compilaient y'a pas si longtemps)
sh3eb-elf-gcc build/src/editor.c.o build/src/main.c.o build/src/load.c.o build/src/engine.c.o build/src/bfile.s.o build/assets/font-island.bmp.o build/assets/game-background.bmp.o build/assets/balls.bmp.o build/assets/explosion.bmp.o `fxsdk --libs` -o build/calthero.elf `fxsdk --cflags` -std=c11 -Wall -Wextra -pedantic
/usr/bin/sh3eb-elf-ld: cannot find build/version.o
Il se trouve que l'erreur survient aussi sur un projet bidon :
int main(int a, void *args) {
return 1;
}
[darks@walhalla test]$ sh3eb-elf-gcc -c main.c -o main.o `fxsdk --cflags` -std=c11 -Wall -Wextra -pedantic
main.c: In function 'main':
main.c:1:14: warning: unused parameter 'a' [-Wunused-parameter]
int main(int a, void *args) {
~~~~^
main.c:1:23: warning: unused parameter 'args' [-Wunused-parameter]
int main(int a, void *args) {
~~~~~~^~~~
[darks@walhalla test]$ sh3eb-elf-gcc main.o `fxsdk --libs` -o addin.elf `fxsdk --cflags` -std=c11 -Wall -Wextra -pedantic
/usr/bin/sh3eb-elf-ld: cannot find build/version.o
collect2: error: ld returned 1 exit status
À l'inverse, un make all dans le dossier de gint fonctionne (si ce n'est que j'ai pas le bon wrapper dans mon path).
Citer : Posté le 12/08/2018 21:29 | #
J'arrive à reproduire le bug. Je regarde plus en détail.
Ajouté le 12/08/2018 à 21:34 :
Le linker script mentionnait ce fichier. J'ai toujours cru que c'était « s'il existe », mais apparemment pas.
J'ai adapté et commit un fix qui semble passer. Tu peux confirmer ?
Citer : Posté le 12/08/2018 21:39 | #
C'est tout bon o/
Au passage, tu peux publier le wrapper sur le Gitlab ?
Citer : Posté le 12/08/2018 21:41 | #
Au passage, tu peux publier le wrapper sur le Gitlab ?
J'aimerais éviter, si possible. Il a besoin d'être réécrit, pour être honnête... normalement il devrait être intégré au fxSDK une fois que c'est fini.
Ajouté le 14/08/2018 à 14:10 :
J'ai réussi à écrire le système d'enregistrement des évènements du clavier.
En fait je l'ai fait sous trois formes différentes sans réussir à me débarrasser d'un bug gênant et non trivial. Basiquement, quand on presse beaucoup de touches et qu'on les relâche, certains relâchements ne sont pas pris en compte.
Si je lis dans les registres du KEYSC ce qu'il en est depuis l'interruption qui analyse le clavier, il dit que les touches en question sont toujours pressées. Si je le fais hors de l'interruption, il dit qu'elles ne le sont pas et le bug disparaît.
Je l'ai déjà rencontré il y a quelques années, et le « contournement » que j'avais mis en place est la raison pour laquelle le clavier ne marche plus quand on overclocke dans les versions actuelles de gint.
Je continue de chercher mais ça s'annonce assez bizarre, je n'ai pas encore d'idée d'où ça peut venir.
Ajouté le 14/08/2018 à 15:34 :
Croyez-le ou pas, j'arrive à contrôler l'apparition du bug en fonction de l'espace où mon driver fais les analyses du clavier : depuis une interruption, j'ai des artefacts, mais depuis le programme utilisateur, rien. Je continue de chercher... '-'
Citer : Posté le 15/08/2018 01:01 | #
Au passage, est-ce que tu peux préciser les bons paramètres d'enregistrement (méthode pour Gimp par exemple) pour que fxconv fasse pas du caca ?
Impossible d'afficher un foutu sprite en N&B + alpha
Genre, les paramètres pour :
– les sprites, N&B, N&B+A
– les polices, N&B
– les sprites, 4G, 4G+A
Ajouté le 15/08/2018 à 01:04 :
Je précise que ça vient vraiment de fxconv, parce que si je mets un lien symbolique vers un sprite de gintdemo, il s'affiche. C'est une question de paramètres d'enregistrement uniquement.
Citer : Posté le 15/08/2018 08:33 | #
Pour les sprites, normalement :
- Bitmap uniquement.
- RGB888, ARGB8888, RGB565 ou monochrome.
- fxconv détecte automatiquement s'il y a besoin d'ajouter un calque de transparence (si l'image contient des pixels transparents) ou s'il faut passer en gris.
- Les gris sont #555555 et #aaaaaa.
Pour les polices :
- Il y a un header où on doit dessiner du texte, c'est super pas pratique à utiliser, je veux pas garder ce système.
- Copie l'en-tête depuis une police déjà prête, genre celle dans gint/src/display, et change juste la taille des glyphes.
- La police est faite de lignes qui sont séparées par une ou plusieurs lignes blanches consécutives sur toutes la largeur de l'image.
- Chaque ligne est faite de glyphes séparés par une ou plusieurs colonnes blanches consécutives sur toute la hauteur de la ligne.
- Les pixels gris sont autorisés, affichés comme blanc mais ne participent pas à ses démarcations (vois ").
Si ça ne marche pas, fais donc voir les images ; je n'ai jamais rencontré le moindre problème donc c'est certainement arrangeable.
Citer : Posté le 15/08/2018 10:30 | #
Les polices c'est ok (coup de chance ? Aucune idée…) mais pour les sprites j'ai toujours un bel écran blanc.
Je te laisse faire mumuse avec cette ligne et les images présentes dans le projet.
Citer : Posté le 15/08/2018 11:02 | #
Je clône, j'envoie ton g1a, j'ai isometric.bmp qui s'affiche à l'écran.
Je n'ai même pas recompilé.
Ça marche sur ma Graph 35+ SH3 et ma Graph 75+E SH4.
... tu es sûr que tout va bien de ton côté ?
Citer : Posté le 15/08/2018 11:03 | #
Justement, isometric c'est l'image que j'ai piqué de gint, c'est la seule qui fonctionne
— Edit —
J'avoue, j'ai pas été clair pour le coup
Citer : Posté le 15/08/2018 11:15 | #
Hmm, curieusement le RGB888 contente mieux fxconv. C'est pas normal en tous cas.
J'ai passé tes images dans le bon format, retiré de l'index les fichiers de build et commit tout ça. Le nouveau g1a devrait donner ce que tu veux.
Citer : Posté le 15/08/2018 11:18 | #
« J'ai passé tes images dans le bon format » À savoir ? Je vais avoir pas mal de sprites, je vais pas te demander de tous les faire
Citer : Posté le 15/08/2018 11:19 | #
Eh bien, RGB888. Gimp te propose ça dans "Advanced options" quand tu exportes en bitmap.
Citer : Posté le 15/08/2018 11:22 | #
Bizarre, il me semblait que tu perdais la transparence avec ça. Bref, je regarderai en détail ce soir.
Merci pour le coup de main