Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » gint : un noyau pour développer des add-ins
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

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), même un peu de C++ (voir µSTL)
  • 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.

VersionDateInfos supplémentaires
gint 2.9.021 Août 2022
gint 2.8.017 Mai 2022Effets dynamiques sur les imagesAPI de manipulations d'images
Overclock intégré
gint 2.7.119 Mars 2022Tutoriel capture des flux standards
gint 2.7.031 Décembre 2021
gint 2.6.029 Août 2021Tutoriel de capture vidéo par USB
gint 2.5.28 Juin 2021
gint 2.5.12 Juin 2021
gint 2.5.026 Mai 2021Intégration de fxlibc (dépôt) — Tutoriel de communication par USB
gint 2.4.027 Avril 2021Api GINT_CALL() pour les callbacks
gint 2.3.12 Février 2021
gint 2.3.029 Janvier 2021
gint 2.2.112 Janvier 2021
gint 2.2.011 Janvier 2021
gint 2.1.116 Septembre 2020
gint 2.1.021 Août 2020Polices UnicodeNouvelle API du moteur de gris
gint 2.0.3-beta10 Juillet 2020Modifications de l'API timer
gint 2.0.2-beta17 Juin 2020
gint 2.0.1-beta1er Juin 2020

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 (2022-08-21)

gint 2.10
  1. 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. Je vais peut-être coder des effets algébriques pour m'amuser un peu.
  2. Fignoler le driver USB. Ajouter la communication PC→calto, des pipes interruption/isochrones. Ajouter le support de descripteurs de fichiers USB. Potentiellement pousser jusqu'à avoir GDB pour debugger.

Non classé

  • Support de scanf() dans la fxlibc.
  • 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.
  • Overclock sur Graph mono.



Précédente 1, 2, 3 ··· 10 ··· 20 ··· 30 ··· 40 ··· 50 ··· 59, 60, 61, 62, 63, 64, 65 ··· 67, 68, 69 Suivante
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 20/12/2021 18:51 | #


Slyvtt a écrit :
Prépare ta soirée, je vais bientôt poster la v0.9B qui sera "almost done", la v1.0 sera la version avec tous les niveaux dispos et la fin de l'histoire afin de ne pas tout "teaser" avant ...

Wow j'ai vu ça c'est génial ! Je le teste ce soir après manger.

Tu sais quand ça va passer en release ?

Je suis en train de finaliser l'API. En gros non seulement je veux m'assurer que toutes les fonctions de base sont fournies, mais aussi que toutes les fonctionnalités offertes par BFile de base sont couvertes histoire qu'utiliser BFile soit vraiment inutile sur la Graph 35+E II et la Graph 90+E.

Pour information, l'API Unix actuelle supporte les fonctions suivantes :

  • open(2) pour les fichiers, avec O_RDONLY, O_WRONLY, O_RDWR (évidemment) ; mais aussi O_CREAT, O_TRUNC et O_EXCL.
  • creat(2) (trivial)
  • read(2), write(2)
  • lseek(2), sauf la position courante qui n'est pas suivie sur Graph 35+E II (mais la libc devra la suivre, je serai peut-être obligé de la garder à la main)
  • pread(2), pwrite(2) (pwrite(2) nécessite la position courante)
  • close(2)
  • unlink(2)

Note que l'API des descripteurs de fichiers supporte des descripteurs customisés, ce qui permettra à terme d'ajouter des fichiers en RAM (facile) et des descripteurs de fichiers pour communiquer par USB (facile aussi a priori). Ou des trucs à la demande... et bien sûr tu pourras toujours faire fdopen(3) dessus et derrière ça roule comme sur un OS sérieux.

Le but dans l'immédiat est de rajouter l'API pour les répertoires. Note qu'il n'y a pas d'API standardisée pour lire depuis une répertoire au niveau syscall (Linux utilise l'obsolète readdir(2), ou désormais getdents(2), mais c'est tout caché). À la place, gint fournit directement les fonctions POSIX, à savoir opendir(3), readdir(3) etc. J'ai quasiment fini de coder et tester :

  • mkdir(2)
  • rmdir(2), qui pour l'instant supprime aussi les dossiers non-vides
  • open(2) supporte les répertoires, ainsi que les opérations lseek(2) et close(2)
  • opendir(3), readdir(3), seekdir(3), telldir(3), rewinddir(3), closedir(3)
  • dirfd(3), fdopendir(3)

Pour l'instant il n'y a pas de plan de supporter un truc plus avancé comme scandir(3) ou glob(3), mais ça viendra peut-être plus tard. La deadline que je vise se compte en jours tout au plus.

Une fois que ça ce sera fait (mon espoir secret est que ce soit le cas ce soir) je retourne sur <stdio.h> dont j'ai codé les toutes bases (la structure FILE et le buffering).
Slyvtt Hors ligne Community Manager Points: 832 Défis: 0 Message

Citer : Posté le 20/12/2021 20:38 | #


Super, tu avances bien.
Avec ça tu auras une API compatible standard C, c'est nickel.

Bon courage pour le test
Ninestars Hors ligne Membre Points: 2449 Défis: 24 Message

Citer : Posté le 21/12/2021 10:34 | #


Super ! Ça va bien simplifier la gestion des fichiers ! Bravo
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 21/12/2021 10:35 | #


Merci. Que sur la Graph 35+E II et Graph 90+E pour l'instant. Le vieux système de fichiers est trop mauvais pour supporter une telle interface. Après ce sera toujours possible d'ouvrir des fichiers en RAM et de faire majoritairement pareil je pense, à voir.
Ninestars Hors ligne Membre Points: 2449 Défis: 24 Message

Citer : Posté le 21/12/2021 10:42 | #


Ohhh pas de problèmes pour moi tu sais... avec ma nouvelle 90E+ je suis au gout du jour désormais
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 21/12/2021 10:45 | #


Ok bien reçu
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 23/12/2021 01:22 | #


Tout ce qui est mentionné dans ce message est maintenant poussé, et testé plutôt en détail.

Je pense qu'il me manque encore un genre de stat() pour pouvoir supporter tout <stdio.h> mais pour l'instant on va dire que ça peut attendre.
Massena Hors ligne Rédacteur Points: 2150 Défis: 11 Message

Citer : Posté le 23/12/2021 08:40 | #


Du coup l'API de fichiers est complète et fonctionnelle maintenant ? Et gint passe à une nouvelle version ?
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 23/12/2021 09:22 | #


Quasiment ouais ! Niveau gint c'est à peu près bon, j'attends juste de voir si j'ai besoin de stat() etc. Mais une nouvelle version est imminente en effet.

Côté fxlibc il y a encore <stdio.h> à supporter (fopen() et compagnie).
Kikoodx Hors ligne Labélisateur Points: 2979 Défis: 11 Message

Citer : Posté le 23/12/2021 11:10 | #


Super j'attendais ça avec impatience depuis quelques jours

Cependant j'ai de petites erreurs. J'inclus fnctl.h, sys/stat.h, unistd.h et O_WRONLY n'est pas trouvé par gcc. Si je remplace par 0 ça compile, mais close et open sont indéfinis. Faut mettre à jour autre chose que gint ? Inclure d'autres headers ? Merci d'avance

Logs complets :
> fxsdk build-cg
Consolidate compiler generated dependencies of target proj
[  3%] Building C object CMakeFiles/proj.dir/src/input.c.obj
/home/kdx/projects/jtmm2/src/input.c: In function ‘input_init’:
/home/kdx/projects/jtmm2/src/input.c:22:52: error: ‘O_WRONLY’ undeclared (first use in this function)
   22 |         if (log) input.fd_log = open("jtmm2.demo", O_WRONLY);
      |                                                    ^~~~~~~~
/home/kdx/projects/jtmm2/src/input.c:22:52: note: each undeclared identifier is reported only once for each function it appears in
make[3]: *** [CMakeFiles/proj.dir/build.make:132: CMakeFiles/proj.dir/src/input.c.obj] Error 1
make[2]: *** [CMakeFiles/Makefile2:83: CMakeFiles/proj.dir/all] Error 2
make[1]: *** [Makefile:91: all] Error 2
make: *** [Makefile:2: all] Error 2

> fxsdk build-cg
Consolidate compiler generated dependencies of target proj
[  3%] Building C object CMakeFiles/proj.dir/src/input.c.obj
[  6%] Linking C executable proj
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld: CMakeFiles/proj.dir/src/input.c.obj: in function `_input_deinit':
input.c:(.text+0x24): undefined reference to `_close'
/home/kdx/.local/share/giteapc/Lephenixnoir/sh-elf-gcc/lib/gcc/sh3eb-elf/11.1.0/../../../../sh3eb-elf/bin/ld: CMakeFiles/proj.dir/src/input.c.obj: in function `_input_init':
input.c:(.text+0x6c): undefined reference to `_open'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/proj.dir/build.make:396: proj] Error 1
make[2]: *** [CMakeFiles/Makefile2:83: CMakeFiles/proj.dir/all] Error 2
make[1]: *** [Makefile:91: all] Error 2
make: *** [Makefile:2: all] Error 2

mi lape ala.

J'suis un méga chômeur
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 23/12/2021 11:12 | #


Ah pardon j'ai oublié de spécifier que les en-têtes et une partie des définitions sont dans la fxlibc ! Ça fait partie du standard POSIX et compte tenue de l'approche qu'on a prise avec Yatis c'est défini dans la fxlibc même si les détails sont implémentés dans gint.

Si tu veux la motivation c'est que Yatis pourra implémenter pareil dans Vhex et ensuite les abstractions construites par-dessus (comme fopen()) il en bénéficiera dans Vhex sans avoir à les recoder.
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 31/12/2021 10:58 | #


Nouvelle version : gint 2.7.0

Une assez grosse release qui contient surtout des corrections de bugs ainsi que -tenez-vous bien- le support pour le système de fichiers !

Release associée du fxSDK : fxSDK 2.7.0
Release associée de la fxlibc : fxlibc 1.3.0

Ajouts :
  • Un système de descripteurs de fichiers qui permet d'accéder aux fichiers avec BFile (sur Graph 35+E II et Graph 90+E), mais permettra aussi dans le futur de manipuler des fichiers dans la RAM (sur tous les modèles) ou de communiquer par USB avec les fonctions standard (write(), fwrite(), etc - sur SH4).
  • Beaucoup de fonctions de l'API Unix et standard pour manipuler les fichiers de la mémoire de stockage - plus de détails ci-dessous.
  • Le type de systèmes de fichiers est maintenant exposé dans gint[HWFS] (<gint/hardware.h>) : soit HWFS_FUGUE (Graph 35+E II, Prizm et Graph 90+E), soit HWFS_CASIOWIN (les autres mono).

Changements :
  • Les images pour bopti au format p4 qui sont de taille impaire ont maintenant un demi-octet nul à la fin de chaque ligne. Précédemment, les lignes pouvaient commencer au milieu d'un octet. Ce changement est utile pour supporter les formats p4 et p8 optimisés dans Azur.
  • La pile fait maintenant 14 kio au lieu de 8 kio sur Graph 35+E II parce que BFile utilise des grosses variables locales. Ça réduit donc de 6 kio la taille du (déjà petit) tas disponible dans la RAM utilisateur. Une System ERROR pour les dépassements de pile a été ajoutée, mais elle ne détecte pas l'overflow tout le temps (c'est un problème difficile).
  • <gint/bfile.h> expose maintenant BFile_Seek() (tous modèles), BFile_GetPos() (Graph 90+E uniquement), et les codes d'erreur.

Corrections de bugs :
  • Les lignes verticales à x=395 sur Graph 90+ étaient ignorées.
  • sleep_us_spin() pouvait tourner à l'infini si les interruptions étaient activées durant l'appel, parce que TCR.UNIE était laissé actif sur le timer. L'interruption pouvait alors effacer TCR.UNF sans qu'il ne soit vu par le thread principal.
  • Exécuter dupdate() très fréquemment sur Graph 90+E pouvait freeze parce que la fonction attendait la fin d'un dupdate() précédent avant d'envoyer les pixels mais après avoir envoyé les coordonnées de la fenêtre. Les écritures par le DMA d'un dupdate() encore en cours pouvaient donc interférer avec les commandes qui indiquent les coordonnées.
  • Les registres mach et macl n'étaient pas sauvegardés correctement lors d'une interruption sur SH3, ce qui cassait les multiplications d'une façon assez marrante par moments.

Support des API Unix et standard pour le système de fichiers

Sur les calculatrices avec Fugue (ie. Graph 35+E II et Graph 90+E), gint supporte l'accès au système de fichiers par les API Unix et une partie du standard POSIX. N'oubliez pas de faire un world switch pour accéder au système de fichiers.

Les headers <unistd.h>, <fcntl.h>, <dirent.h> et <sys/stat.h> sont fournis par la fxlibc, tandis que le code est fourni par gint.

Pour ce qui est des fichiers, gint implémente les fonctions suivantes :

  • open(2), avec O_RDONLY, O_WRONLY, O_RDWR (évidemment) ; mais aussi O_CREAT, O_TRUNC et O_EXCL.
  • creat(2) (trivial)
  • read(2), write(2)
  • lseek(2), sauf la position courante qui n'est pas suivie sur Graph 35+E II
  • pread(2), pwrite(2) (pwrite(2) nécessite la position courante)
  • close(2)
  • unlink(2)
  • stat(2)

Et côté répertoires :

  • mkdir(2) et rmdir(2)
  • open(2), lseek(2) et close(2) sur les répertoires (mais il vaut mieux utiliser opendir(3))
  • opendir(3), readdir(3), seekdir(3), telldir(3), rewinddir(3), closedir(3)
  • dirfd(3), fdopendir(3)

Ça veut dire que, sur Graph 90+E au moins, personne ne devrait plus jamais avoir à s'embêter avec BFile
Ninestars Hors ligne Membre Points: 2449 Défis: 24 Message

Citer : Posté le 31/12/2021 11:26 | #


Excellent, super maj
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 10/01/2022 14:43 | #


Après avoir bataillé 4 jours, j'ai fini par mettre le doigt sur un bug qui était passé inaperçu durant la précédente mise à jour.

(Pour ceux qui se demandent comment ce genre de choses arrive, c'est assez facile : ça marche très bien pendant des jours, parfois des semaines ou des mois, et tout à coup ça crashe parce que les étoiles se sont «alignées» pour permettre la manifestation du bug. Et là je sors mon manteau, ma pipe, ma loupe et ma déprime jusqu'à ce que le crash élusif mène à une explication concrète.)

Donc l'origine de ce bug c'est un détail que j'avais oublié depuis longtemps et qui est qu'on ne peut pas écrire dans un fichier depuis la ROM (virtualisée ou pas) ; les données qu'on envoie doivent être dans la RAM. On ne sait pas exactement pourquoi, parce que l'explication dépend de plein de détails cachés de l'OS. Le truc c'est que plein de choses sont dans la ROM. Par exemple :

write(fd, "Hello, world!\n", 14);
//        ^^^^^^^^^^^^^^^^^
//        Ça c'est dans la ROM!

Donc voilà un de mes tests a crashé Jeudi pour ça et j'ai compris ce matin. Du coup j'ai modifié write() pour que si on lui demande d'écrire depuis la ROM il se débrouille pour copier d'abord les données vers la RAM (par blocs ou d'un coup selon combien de mémoire est disponible à ce moment-là), ce qui est transparent pour vous.

Un nouveau patch de gint arrivera donc sous peu, le temps que tout ça soit bien testé.
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 19/03/2022 21:20 | #


Petit tutoriel que je lierai dans le changelog : comment utiliser les flux standards (stdin/stdout/stderr) dans gint. Pour rappel, les flux standards sont les "fichiers" qui lient le programme à (habituellement) votre terminal, et qui sont utilisé par printf(), scanf(), etc.

Dans gint, les flux standards existent, mais il n'y a pas pour autant de terminal intégré. Par défaut, stdin() ne transmet juste aucun texte, et stdout/stderr mettent tout le texte qu'ils reçoivent à la poubelle.

Vous pouvez cependant les fermer/rouvrir pour récupérer chaque lecture/écriture dans une fonction de votre choix. La façon de faire ça est de définir un nouveau type de fichier avec vos propres fonctions de lecture/écriture, et de rouvrir les descripteurs de fichiers des flux standards avec ces types-là. Oui le mécanisme permet de faire des fichiers à la Linux, pour l'USB, écrire en RAM, etc.

Regardons à quoi ressemble le mécanisme pour stdio/stderr (les flux où on écrit, eg. avec printf()). D'abord il faut définir la fonction d'écriture, qui a le même prototype que write() :

ssize_t stdouterr_write(void *data, void const *buf, size_t size)
{
    /* On vient de recevoir le texte [buf] de longueur [size]. C'est le moment de
       l'enregister, l'afficher, etc. */
    /* [data] est un paramètre personnalisé, voir ci-dessous. */
}

Ensuite on définit le type de fichiers qu'on va attribuer à stdout/stderr, pour lequel on n'implémente aucune autre fonction.

fs_descriptor_type_t stdouterr_type = {
    .read = NULL,
    .write = stdouterr_write,
    .lseek = NULL,
    .close = NULL,
};

Et enfin on est prêts à rouvrir les descripteurs avec ce nouveau type. Le second paramètre est enregistré dans le descripteur et passé à la fonction via le paramètre data. Ici je l'ignore, je mets NULL.

#include <gint/fs.h>
#include <unistd.h>

close(STDOUT_FILENO);
close(STDERR_FILENO);
open_generic(&stdouterr_type, NULL, STDOUT_FILENO);
open_generic(&stdouterr_type, NULL, STDERR_FILENO);

Et voilà, à partir de maintenant printf() et toute la compagnie envoient vers notre fonction stdouterr_write() et on peut faire ce qu'on veut dedans.

Pour stdin, c'est pareil sauf que c'est la fonction de lecture qu'on modifie :

ssize_t stdin_read(void *data, void *buf, size_t size)
{
    /* On nous demande de fournir [size] caractères dans [buf]. Dans un terminal
       on demanderait à l'utilisateur de taper quelque chose (+ buffer) */
}

fs_descriptor_type_t stdin_type = {
    .read = stdin_read,
    .write = NULL,
    .lseek = NULL,
    .close = NULL,
};

close(STDIN_FILENO);
open_generic(&stdin_type, NULL, STDIN_FILENO);

Et voilà, je suis sûr que ce sera utile pour porter des programmes et/ou garder du code cross-platform bien en place
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 19/03/2022 21:36 | # | Fichier joint


Nouvelle version : gint 2.7.1

Une version assez mineure côté gint, mais côté fxlibc tout le support pour les fichiers de <stdio.h> a été ajouté (fopen(), fprintf(), etc). Jetez d'abord un œil là-bas, puis regardez les infos ci-dessous !

Release associée du fxSDK : fxSDK 2.7.1
Release associée de la fxlibc : fxlibc 1.4.0

Le support des flux standards a été ajouté dans la libc, ce qui signifie que maintenant printf() marche. Par contre, le texte n'arrive nulle part par défaut, c'est à vous de définir une fonction pour le récupérer.

Mini-tutoriel : Utiliser les flux standard.

Assez peu de changements donc :

  • Les écritures dans les fichiers pouvaient crasher semi-aléatoirement si les données écrites provenaient de la ROM, ce qui est une limitation connue de système de fichiers. gint contourne maintenant ce problème en copiant d'abord vers la RAM (détails ici).
  • Les descripteurs de fichiers pour la mémoire de stockage traquent maintenant la position «manuellement» (au lieu de se fier à Fugue pour la donner), parce que Fugue raconte des conneries de temps en temps. pread() ne marchait pas précédemment et marche maintenant.
  • gint[HWRAM] indique maintenant 8 Mio sur Graph 90+E au lieu de 2 Mio (comme la Prizm).
  • Le linker se plaindra maintenant si votre section RAM est tellement grosse qu'elle empiète sur la pile. Je pense que ça n'est encore arrivé à personne, de loin.
  • Corrigé un bug d'affichage de dimage() qui se produisait uniquement sur les images au format p4 de largeur impaire quand on affichait avec dsubimage() une sous-image avec top>0.

C'est tout pour cette fois, mais pour la prochaine version je prévois de revamp un peu bopti sur Graph 90+E pour vous donner enfin les fonctions de redimensionnement, miroir horizontal/vertical, etc. que vous me demandez souvent, sous une forme efficace (pas juste ce que libimg donne qui n'est qu'à moitié convaincant).
Slyvtt Hors ligne Community Manager Points: 832 Défis: 0 Message

Citer : Posté le 19/03/2022 21:43 | #


Yo, ça c'est de la release tout tombe d'un coup, c'est Noel avant l'heure.
Je plussoie pour les fonctions sur les sprites.
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 20/03/2022 11:27 | #


J'ai réécrit le topic pour donner un meilleur aperçu des fonctionnalités, et ajouté quelques exemples.

Slyvtt a écrit :
Yo, ça c'est de la release tout tombe d'un coup, c'est Noel avant l'heure.
Je plussoie pour les fonctions sur les sprites.

Merci ! Pour les sprites je vais commencer par récupérer les formats optimisés que j'utilise dans Azur, puisque le code de dessin là-bas (qui est beaucoup plus récent et utilise des subtilités d'assembleur beaucoup plus pointues que j'ai maîtrisées récemment) est franchement mieux.

Mon objectif principal est d'avoir des "fonctions génériques" pour manipuler les images, idéalement pour reprendre la structure de dessin classique et ensuite pouvoir faire des extensions à la pelle sans avoir à manipuler beaucoup de code à chaque fois.

Quelques exemples de trucs qui passeraient bien dans le format générique : miroir vertical/horizontal, remplacement d'une couleur par une autre (pour les images monochromes par exemple), certains effets de distorsion horizontale verticale (division de la taille par une puissance de 2 par exemple), et si je m'en sors bien peut-être même agrandissement par facteurs entiers (voire tout ça combiné lol). Ce genre d'effets pourrait se faire directement à l'affichage sans copier les images.

À côté de ça, je veux aussi ajouter une vraie API pour lire/modifier les pixels et les images, avec les transformations classiques (redimensionnement arbitraire nearest-neighbor, changements de luminosité, saturation, etc). Essentiellement fusionner libimg dans gint, en supportant au passage les formats à palette (le format interne 16-bit de libimg est pas assez performant en général).

Il y aura clairement deux types de transformations, celles qui n'ajoutent pas de nouvelles couleurs ou les modifient juste sans en changer le nombre, et donc passent bien sur les formats à palette ; et celles qui les changent complètement, et donc ne passeront que sur les formats 16-bit (par exemple redimensionnement avec interpolation, alpha blending, etc).

Voilà, comme d'hab je profite d'une demande simple pour remédier à des problèmes un peu plus profonds d'une façon un peu ambitieuse. Ce sera pas immédiat du coup ; désolé. Sur le moyen/long terme ce sera bénéfique, promis.
Lephenixnoir Hors ligne Administrateur Points: 22584 Défis: 149 Message

Citer : Posté le 21/03/2022 23:20 | # | Fichier joint


Alright donc voici un début de plan pour les histoires des images.

Situation actuelle : le code de bopti est... en assembleur. Assez mauvais pour de l'assembleur avec mes connaissances actuelles. La version du dessin que j'ai codée dans Azur est d'une beauté infinie à côté... et probablement 2 fois plus rapide sur le CPU. Mon plan est de récupérer le code d'Azur pour le passer dans gint parce que ça sert à rien d'améliorer du code que j'ai déjà refait en mieux.

Je ne sais pas quel gain de vitesse réel je peux attendre de ce transfert parce qu'Azur dessine dans la XRAM (qui est très rapide) alors que bopti dessine dans la RAM. Si la RAM est le facteur limitant, alors il n'y a peut-être pas vraiment de marge à grignoter. Mais ça reste la seule option sérieuse, surtout si on prend en compte l'overclock.

Les formats : actuellement bopti a 4 formats : RGB565, RGB565A, P8 et P4. Les deux formats à palette, P8 et P4, ont tous les deux la transparence intégrée et il se trouve que c'est ce qui coûte le plus cher en termes de perfs. Azur spécialise P8 et deux variations P8_RGB565 et P8_RGB565A qui font ce que vous imaginez. En plus de ça, il réduit la palette de 256 entrées à juste ce qui est nécessaire à la conversion, ce qui devrait être évident. Et enfin, il numérote les couleurs à partir de -128 au lieu de 0 parce que ça économise un demi-cycle par pixel durant la lecture de la palette. P4 est aussi spécialisé en P4_RGB565 et P4_RGB565A même si là il n'y a que l'absence de transparence qui change. Je compte faire suivre ces formats dans gint, ce qui ne change rien de l'extérieur.

Fusion de libimg : une fois ces formats bien posés et fixés, je compte exposer dans l'API gint de quoi accéder aux informations, pixels etc. des images, plus essentiellement les fonctions de libimg (dépôt) qui est actuellement figée au RGB565A, ce qui est vraiment pas suffisant en perfs. À cela on peut ajouter des redimensionnements quelconques comme dans la démo récente, des changements de palette, et autres joyeusetés. Bien sûr des conversions de format, même si je promets pas que l'encodage 16-bit → palette soit super élégant.

Il y aura clairement deux types de transformations ; celles qui ne changent pas le nombre de couleurs et seront donc disponibles pour transformer les images P8_* et P4_*, et celles qui changent le nombre de couleurs (redimensionnement avec interpolation, alpha blending, etc) et qui ne seront naturellement disponibles que sur les images RGB565 et RGB565A.

QOI : Il est question de supporter le format QOI (issue). Ça me plaît bien. Je ne pense pas que ce soit sérieusement possible de décoder le QOI au rendu en temps raisonnable, mais je suis chaud pour essayer. Dans tous les cas il sera toujours possible de décoder en bopti_image_t dans la RAM au lancement de l'add-in, ce qui économise de la place dans le G3A, qui est presque plus rare que la RAM.

Effets dynamiques : Et le plus gros (que je mets à la fin juste à cause du gros tableau ci-dessous), les effets dynamiques : les transformations qu'on fait à la volée en affichant, sans créer de nouvelle image. Je vous mets le tableau puis j'explique ce que ça veut dire.


Pour chaque format et chaque transformation j'ai indiqué :

  • La stratégie : d'après une analyse rapide, comment je peux modifier le code d'Azur pour implémenter l'effet ;
  • Le surcoût en performance : combien de cycles par pixel on perd avec l'effet ;
  • Ce qu'il faut modifier dans le code : ça peut aller de "paramétrisation" (on ajoute juste un paramètre sur la fonction existante), à "loop core" (il faut modifier la boucle centrale donc dupliquer la fonction) à "new function" (explicite). Vous noterez le gros problème que les effets se cumulent pas bien, ça devient un peu tendu s'il faut faire une nouvelle fonction pour chaque combinaison.

Les effets considérés sont les suivants (je prends les suggestions) :

  • Vertical flip : inversion de l'ordre des lignes en gardant les lignes inchangées.
  • Horizontal flip : inversion de l'ordre des colonnes en gardant les colonnes inchangées.
  • Opaque color remap : transformation plus ou moins arbitraire sur les couleurs opaques.
  • Background color : remplacer la transparence par une couleur opaque.
  • Erase one color : remplacer une couleur opaque d'une image sans transparence par du transparent.
  • Code injection : insérer du code assembleur pour manipuler à peu près ce qu'on veut.

Vous pouvez voir que dans l'ensemble y'a pas mal de trucs accessibles en performance, mais comment structurer le code pour les faire marcher sans tout dupliquer toutes les 3 lignes est un casse-tête potentiel. On sent, en arrière-plan, une logique se dégager avec un très beau modèle de transformations à côté duquel je ne veux pas passer sans réfléchir, mais qui ne serait clairement pas trivial à obtenir.

Notez que pour les fonctions qui modifient les images (pour faire comme libimg) c'est un peu pareil, y'a un squelette générique pour parcourir les pixels d'une image et faire des transformations, et pour que les transformations aillent vite et bien il faut qu'elles soient en assembleur et bien optimisées. Pour que le squelette soit réutilisable et que chaque transformation réimplémente pas tout, faut pas s'y prendre n'importe comment.

Stade actuel : réflexion.
Slyvtt Hors ligne Community Manager Points: 832 Défis: 0 Message

Citer : Posté le 21/03/2022 23:59 | #


C’est un très beau programme que tout cela.

En idées supplémentaires :
Isolation de chacune des composantes d’une image
Conersion en niveau de gris
Blender une images avec un fond avec un niveau alpha

Mais c’est peut être trop spécifique (et très clairement non prioritaire...)
Kikoodx Hors ligne Labélisateur Points: 2979 Défis: 11 Message

Citer : Posté le 22/03/2022 00:26 | #


Joli programme ! Les effets dynamiques vont certainement ouvrir de nouveaux horizons, j'adore tout ce que tu prévois !

QOI

Je suis très hype pour QOI ! À la fois pour les options que ça donne pour la compression de l'add-in, et pour la flexibilité des projets.

Il serait potentiellement très utile d'avoir l'option de charger des ressources QOI externes en tant que bopti :
Le transfert d'un add-in peut devenir lent quand le projet grossit, transférer uniquement les ressources modifiées ferait gagner beaucoup (beaucoup !) de temps
SDL2_image supportera QOI avec sa prochaine release, il serait potentiellement beaucoup plus facile d'écrire des jeux cross platform complets avec le standard QOI et les fonctionnalités d'IO toutes fraîches de gint. Je dis ça, je dis rien

Les effets considérés sont les suivants (je prends les suggestions) :

Mon effet favori de libimg est img_dye, qui remplace tous les pixels opaques par une couleur spécifiée. C'était très pratique pour faire des effets

Tu as listé les deux flips séparèment, est-ce que ça veut dire qu'ils auront des fonctions dédiées ? D'intuition je me serais attendu à une fonction unique qui prend une combinaison de flags (IMG_FLIP_NONE ou IMG_FLIP_HORI | IMG_FLIP_VERT par exemple). Je suis curieux.
mi lape ala.

J'suis un méga chômeur
Précédente 1, 2, 3 ··· 10 ··· 20 ··· 30 ··· 40 ··· 50 ··· 59, 60, 61, 62, 63, 64, 65 ··· 67, 68, 69 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2022 | Il y a 43 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd