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 14/02/2020 15:14 | #
Aha ! Eh... c'est possible mais ça c'est "très dur" par contre. Je peux le coder c'est pas un problème, mais ce sera lent.
La composition avec transparence (alpha compositing, je ne sais pas comment le dire mieux) c'est très calculatoire. D'abord il faut décomposer les couleurs en canaux, pas moyen de tricher avec la représentation binaire. Ensuite, en principe, il faut sortir de l'espace RGB et aller dans le linéaire pour faire la composition. Donc il faut jouer de l'exponentation avec le gamma. Tu peux approximer ça en des carrés et des racines carrées. Une fois composé (quelques multiplications et additions), il faut revenir du linéaire vers le RGB et recomposer les couleurs.
Tu rentres dans le traitement d'images à proprement parler.
Il me semble que dans Gravity Duck Prizm il fait pas ça (?), de mémoire le sprite du canard fond au blanc et ensuite soit il disparaît immédiatement soit le blanc se fond dans le décor. C'est très différent sur le plan calcul.
Citer : Posté le 14/02/2020 15:29 | #
Ah c'est coûteux en effet. Mais ça pourrait être utile dans certaines situations.
L'explosion à la mort du canard m'a l'air d'être un effet de transparence. Le cercle blanc s'affiche en transparence au-dessus des éléments du décor et de fond.
Citer : Posté le 14/02/2020 15:33 | #
Afficher du blanc avec un niveau de transparence variable ça s'imite facilement. Il suffit d'utiliser la formule d'éclaircissement que j'ai montrée plus haut plusieurs fois. (Après 5/6 fois tout devient blanc.)
Tandis qu'afficher une image sur une autre en semi-transparent, ça c'est une autre affaire...
Citer : Posté le 14/02/2020 15:49 | #
D'accord. Justement je pense que c'était plus qu'assombrir l'image, mais je dois me tromper si tu le dis
Je pense avoir fait une bêtise, j'ai supprimé build-cg pour le regénérer entièrement (les images n'étaient pas mises à jour), et j'obtiens ces erreurs :
making levels.c
building for cg
:: Making into build-cg
sh-elf-gcc -c src/levels.c -o build-cg/src/levels.c.o -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields -Wall -Wextra -Os -D FXCG50 -m4-nofpu -I include -MMD -MT build-cg/src/levels.c.o -MF build-cg/src/levels.c.d -MP
fxconv -i assets-cg/img/ground.png -o build-cg/assets/img/ground.png.o --cg --toolchain=sh-elf name:img_ground profile:p4
fxconv -i assets-cg/img/spike.png -o build-cg/assets/img/spike.png.o --cg --toolchain=sh-elf name:img_spike profile:p4
fxconv -i assets-cg/img/jitem_popup.png -o build-cg/assets/img/jitem_popup.png.o --cg --toolchain=sh-elf name:img_jitem_popup profile:p4
fxconv -i assets-cg/img/jitem.png -o build-cg/assets/img/jitem.png.o --cg --toolchain=sh-elf name:img_jitem profile:p4
fxconv -i assets-cg/img/player.png -o build-cg/assets/img/player.png.o --cg --toolchain=sh-elf name:img_player profile:p4
fxconv -i assets-cg/img/elevator.png -o build-cg/assets/img/elevator.png.o --cg --toolchain=sh-elf name:img_elevator profile:p4
sh-elf-gcc -o build-cg/platform.elf build-cg/src/collide.c.o build-cg/src/player.c.o build-cg/src/draw.c.o build-cg/src/levels.c.o build-cg/src/main.c.o build-cg/assets/img/ground.png.o build-cg/assets/img/spike.png.o build-cg/assets/img/jitem_popup.png.o build-cg/assets/img/jitem.png.o build-cg/assets/img/player.png.o build-cg/assets/img/elevator.png.o -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields -Wall -Wextra -Os -D FXCG50 -m4-nofpu -I include -T fxcg50.ld -lgint-cg -lgint-cg -lgcc -Wl,-Map=build-cg/map
sh-elf-gcc: error: build-cg/assets/img/ground.png.o: No such file or directory
sh-elf-gcc: error: build-cg/assets/img/spike.png.o: No such file or directory
sh-elf-gcc: error: build-cg/assets/img/jitem_popup.png.o: No such file or directory
sh-elf-gcc: error: build-cg/assets/img/jitem.png.o: No such file or directory
sh-elf-gcc: error: build-cg/assets/img/player.png.o: No such file or directory
sh-elf-gcc: error: build-cg/assets/img/elevator.png.o: No such file or directory
Makefile:107: recipe for target 'platform.g3a' failed
make: *** [platform.g3a] Error 1
done
En effet, le dossier build-cg/assets/img est vide. Quel est le problème ? Merci d'avance
Citer : Posté le 14/02/2020 15:58 | #
C'est ma faute.
Je l'ai mentionné rapidement sur l'issue, mais le code de p8 et p4 est sur le dépôt... de gint. La partie fxSDK est encore sur mon PC personnel. Donc les fichiers convertis ne sont pas produits...
Je vais pousser tout ça ce soir (dans ~2 heures). Désolé... x)
Citer : Posté le 14/02/2020 16:02 | #
C'est drôle je viens de répondre à ton message sur le Gitea, je venais de le comprendre par moi-même x)
Pas de problème o/
Citer : Posté le 19/02/2020 22:29 | #
Pas de problème o/
Hey mais j'ai oublié, il ne fallait pas hésiter à me le rappeler. C'est poussé, tu peux récupérer la branche master et réinstaller le fxSDK pour avoir les profils de couleur p4 et p8 sur fxconv pour Graph 90. Si tu étais sur dev, j'ai fusionné et supprimé la branche (ça rendait encore des gens confus...) donc repasse sur master.
Citer : Posté le 20/02/2020 14:34 | #
Pour la compilation de gint, j'ai un problème lors du make
File "/mnt/c/Users/damie/Programmation/gintLibs/bin/fxconv", line 86
err(f"execution mode -{mode} expects an input file")
^
SyntaxError: invalid syntax
Makefile:109: recipe for target 'src/font5x7.png.o' failed
make: *** [src/font5x7.png.o] Error 1
même avec python 3.7.6 (et python3 et python qui sont des alias de python3.7 pour être sur). Je sais pas trop d'ou ca vient, a priori mes libs sont a jour maintenant, et j'ai essayé de supprimer et re-cloner gint, mais cela n'a pas changé; est-ce que ca serait mon installation de fxsdk ou de gcc qui a eu un problème?
Ajouté le 20/02/2020 à 14:35 :
(A noter aussi que lorsque je clone le git de gint j'ai une "warning: remote HEAD refers to nonexistent ref, unable to checkout." et du coup un dossier vide, mais un git checkout compat corrige ce soucis)
envie de plonger dans la mer pour ramasser des tresors? => ballon sea
envie de sauver l'univers dans un jeu avec une longue durée de vie? => saviors of the future
un add-in addictif avec plein de secret et de trophées => evasion survival
un shmup bien dur et sadique => saviors 2
merci a tout le monde pour son soutien
zelda prizm de smashmaster (en esperant qu'il puisse le finir)
les tests de marmotti
un RPG de dark storm
(dont je connais le nom, mais pas vous )Arcuz !Citer : Posté le 20/02/2020 14:39 | #
L'endroit de l'erreur est le premier endroit du script où il y a une f-string. Il est clair que le Python qui exécute ce script ne l'a pas reconnu. Ce que tu as fait semble solide, mais il doit rester une arnaque...
Note que les alias ça ne change rien dans un Makefile. Pour savoir ce que make lance il faut désactiver tes alias et utiliser which, ou simplement le bugger avec strace, ou d'autres.
L'histoire du git checkout compat c'est "normal".
Ajouté le 22/02/2020 à 19:12 :
Je viens de pousser un commit qui règle un problème passager avec getkey().
C'est un peu compliqué. Si on appelle getkey() et qu'on appuie sur la touche K, getkey() s'en souviendra. Ça sert à éviter qu'on puisse interférer avec la répétition de K en appuyant sur une autre touche. Cependant, si après avoir obtenu l'information K de getkey() on se met à récupérer des événements autrements (pollevent(), waitevent() ou clearevents()), getkey() peut rater l'information de relâchement de K, auquel cas il continuera injustement de refuser les autres touches.
J'ai ajouté une vérification à l'entrée de getkey() permettant d'éviter ça. Si la dernière touche pressée ne l'est plus quand on entre dans getkey(), alors getkey() se réinitialise.
Citer : Posté le 23/02/2020 13:20 | #
C'est ça le bug que j'avais signalé plus tôt ! J'utilisais getkey, mais dès qu'il y avait validation, à aucun moment getkey n'enregistrait que la touche de validation avait été pressée puisque je passais en pollevent()
https://dev.planet-casio.com/Fr/forums/topic13572-33-gint-un-noyau-pour-developper-des-add-ins.html#173013
C'est génial ça, je vais pouvoir me remettre à utiliser getkey alors
Citer : Posté le 23/02/2020 16:14 | #
Le triple buffering n'était pas encore en place sur Graph 90+E, donc je suis en train de faire ça. Je suis parvenu à mettre en évidence les artefacts visuels qui se produisent si on commence le frame suivant sur la même VRAM, mais uniquement en tordant mon code pour le faire apparaître, et en faisant exprès de dessiner sur la fin de la VRAM, dont je savais pertinemment qu'elle n'était pas encore modifiée.
Voilà donc un constat intéressant pour ceux qui seraient tentés de lancer des gros projets. Il est possible de bénéficier à la fois de la vitesse de transfert du DMA (jusqu'à 10 ms gagnées par frame !) tout en n'utilisant qu'une seule VRAM (170 ko économisés !). Il suffit de commencer chaque frame en dessinant en haut de la VRAM. Par exemple, si on dessine un terrain construit sur un ensemble de tiles, on peut faire ça :
• Envoyer le frame précédent avec dupdate().
• (Optionnel : faire un truc annexe comme le moteur physique ou les IAs pour laisser le DMA prendre de l'avance.)
• Faire le rendu du terrain. Au début de chaque ligne, vérifier dans les registres du DMA que la bande horizontale concernée a déjà été envoyée à la VRAM, et dessiner.
Cette méthodologie aurait pu être présentée bien avant, mais ce que je réalise maintenant c'est que très peu de temps sera perdu, voire pas de temps du tout (bon à part le fait que de toute façon la RAM n'est pas parallèle de toute façon). Et croyez-moi 170 ko de RAM ça peut vous sauver la vie
Voilà voilà, sinon le triple buffering est poussé sur la branche compat, ce qui fait de la pile graphique par défaut de gint l'une des options les plus performantes pour Graph 90+E clé en main. Pour indication, le visualisateur hexa de mémoire de gintctl, une application pas très exigeante en ressources mais dont le code ne fait pas particulièrement attention aux performances, tourne à 43 FPS.
Autres modifications notable :
• Ajout de DWIDTH et DHEIGHT donnant la taille de l'écran (je ne sais plus qui me l'avait demandé)
• Ajout d'une couleur C_RGB(r,g,b) sur Graph 90 (0 ≤ r,g,b ≤ 31)
Ajouté le 23/02/2020 à 16:15 :
Je me suis demandé ! Bon ben désolé de pas m'en être rendu compte à ce moment-là. La bonne nouvelle, c'est que keydown() était exactement la solution à ce problème. Maintenant, je suis certain que mon modèle clavier est fiable, robuste et polyvalent. Et ça fait bien 3 ans que j'en tente des variantes dans tous les sens ! xD
Ajouté le 25/02/2020 à 23:50 :
Du progrès sur le retour au menu.
J'ai codé une fonction qui permet de sortir temporairement de gint pour exécuter du code à la fxlib (!). C'est réservé à des cas d'usage très particuliers, à savoir revenir au menu principal et gérer les TLB miss. J'ai bien galéré avec les ETMU, mais ça commence à marcher.
Donc pour l'instant on peut sortir d'un add-in sur monochrome et revenir au menu principal. Il se passe encore des choses bizarres quand on re-rentre (notamment, ça freeze), mais c'est un bon progrès.
Citer : Posté le 26/02/2020 11:13 | #
Qu'en est-il du crash qui se produis quand on sort d'un add-in puis qu'on éteint la calto et qu'ont re-entre dans l'add-in ? As-tu une quelconque idée du fonctionnement du mécanisme pour revenir au menu ? Si oui, serait-il préférable de faire nous-mêmes le changement de contexte au lieu de passer par GetKey() (je suppose que non mais je n'ai jamais désassemblé cette partie de l'OS peut-être pourrions-nous trouver un syscall qui fasse le retour menu proprement) ?
Citer : Posté le 26/02/2020 11:21 | #
Évidemment comme je ne peux pas rerentrer je n'ai même pas essayé d'éteindre. Chaque chose en son temps !
Selon moi, le retour au menu est un appel de fonction à l'intérieur de GetKey(), et si on sélectionne une appli ça invoque les destructeurs de l'add-in et appelle un syscall pour démarrer la nouvelle application. Donc vu comme ça, effectivement il y a peut-être moyen de ne pas appeler GetKeyWait(). Ce qui aurait deux petits avantages :
1. Pas besoin de s'embêter avec un timer pour injecter KEY_CTRL_MENU.
2. Pas besoin de s'embêter pour faire arrêter GetKeyWait() sans appuyer sur une touche quand on revient dans l'add-in.
J'avoue que ça m'arrangerait bien, et j'ai bien envie de regarder.
Citer : Posté le 07/03/2020 12:24 | #
Bonjour, y a-t-il une fonction permettant d'obtenir le temps réel en entier de secondes ?
Les fonctions de rtc.h ne permettent d'obtenir qu'une structure, je peux convertir mais c'est galère et pas très utile.
Merci d'avance
Citer : Posté le 07/03/2020 13:46 | #
Pour l'instant il n'y a rien d'autre que rtc.h, mais c'est le bon moment d'en ajouter.
Cela dit tu veux quoi exactement ? Je comprends pas trop le cas d'usage encore...
Citer : Posté le 07/03/2020 21:56 | #
N'y aurait-il pas comme un petit problème ?
Clonage dans 'gint'...
remote: Énumération des objets: 2485, fait.
remote: Décompte des objets: 100% (2485/2485), fait.
remote: Compression des objets: 100% (1325/1325), fait.
remote: Total 2485 (delta 1611), réutilisés 1681 (delta 1078)
Réception d'objets: 100% (2485/2485), 1023.54 KiB | 3.85 MiB/s, fait.
Résolution des deltas: 100% (1611/1611), fait.
warning: la HEAD distante réfère à une référence non existante, impossible de l'extraire.
Autre question : Dois-je me placer dans $PREFIX/include pour clone gint ?
Citer : Posté le 07/03/2020 22:14 | #
Il faut git checkout compat pour avoir la branche, il n'y a pas de master actuellement... et c'est un peu stupide, faut vraiment que je la crée même si le truc n'est techniquement pas en release stable.
Surtout pas, mets-toi en-dehors de $PREFIX, très en-dehors.
Citer : Posté le 07/03/2020 22:17 | #
C'est possible de se mettre dans /tmp pour clone gint ?
Citer : Posté le 07/03/2020 22:37 | #
Oui, mais t'as probablement envie de garder le dépôt parce qu'il va falloir que tu récupères les modifications futures. :]
Ajouté le 10/03/2020 à 16:31 :
Avec l'arrivée imminente de libimg, une bibliothèque de manipulation de bitmaps répondant au problème permanent que bopti n'est bon qu'à dessiner dans la VRAM, je vais renommer le type image_t en bopti_image_t, pour éviter la confusion avec l'espace de noms img_* utilisé par libimg, et en particulier le type d'images img_t. De même, le type:image de fxconv va devenir type:bopti-image.
Ça va se faire tranquillement avec des warnings dans un premier temps, et je pense que je ne supprimerai vraiment les anciens termes qu'à la sortie complète de gint, donc pas tout de suite.
Citer : Posté le 10/03/2020 16:38 | #
Je suis en train de lire le topic de libimg
Vu que tu vas renommer cette variable autant l'appeler bopti_img_t non ? Je pense que ce serait plus cohérent et court.
Citer : Posté le 10/03/2020 16:41 | #
Hmm c'est plus court c'est vrai, mais d'un côté on a dimage() et type:bopti-image. Je sais pas si c'est plus lisible aussi... mais bon, j'ai le temps de voir.