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: 22261 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.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-05-15)

gint 2.9
  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.



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

Citer : Posté le 29/04/2022 12:24 | #


Re : j'ai fini tous les effets dynamiques de tous les formats. ENFIN.

Je vais enfin pouvoir m'amuser avec le reste
Slyvtt Hors ligne Community Manager Points: 747 Défis: 0 Message

Citer : Posté le 29/04/2022 19:15 | #


Cool, ça passe en prod quand ?

Question : sur une image disons de 64x64pixels symétriques haut/bas et gauche/droite, qu'est ce qui sera plus rapide :
un dimage old-school de l'image complete (64x64pixels) ou de faire un lot de 4 dimage_effect (HFLIP / VFLIP et HFLIP | VFLIP) pour reconstituer la totale ?

C'est quoi le reste que tu as en tête ?
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 29/04/2022 19:24 | #


Slyvtt a écrit :
Question : sur une image disons de 64x64pixels symétriques haut/bas et gauche/droite, qu'est ce qui sera plus rapide :
un dimage old-school de l'image complete (64x64pixels) ou de faire un lot de 4 dimage_effect (HFLIP / VFLIP et HFLIP | VFLIP) pour reconstituer la totale ?

Pour une fois, la réponse est simple ! HFLIP et VFLIP n'ont aucune influence sur les performances ; j'ai réussi à programmer toutes les variations à la vitesse de l'original. Le seul surcoût que tu auras c'est celui de faire 4 opérations, à savoir pas tant que ça (surtout que pour 64×64 le blit lui-même écrase pas mal le surcoût). Par contre, tu as un avantage massif à réutiliser 4 fois la même image, qui est que tu réutilises 4 fois les mêmes données, lesquelles ont une bonne chance de passer en cache (total 4096 octets en P8). En plus tu utilises 4 fois moins de RAM/ROM pour le stockage à proprement parler. Il vaut donc clairement mieux faire 4 effets.

C'est quoi le reste que tu as en tête ?

Tout ça !

Pas énorme donc, en fait là tout de suite je suis en train de basculer le code côté gint et tout nettoyer. À côté du gros assembleur (qui sera sans doute sur le dépôt ce soir), tout le reste sera de la promenade.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 30/04/2022 16:31 | # | Fichier joint


Mauvaises nouvelles ! J'ai intégré le code de mes fonctions de rendu fraîchement terminées à gint, et non seulement bopti ne laisse aucune marge pour gagner en perfs sur le bottleneck RAM, mais en plus avec le setup supplémentaire (pourtant pas immense), mon nouveau code est sensiblement plus lent que bopti quand on l'utilise sur la RAM ! Il n'est plus rapide que pour les formats complexes (eg. P4) avec beaucoup de transparence, et est jusqu'à 25% plus lent dans les cas mondains.

(Ce nouveau code reste largement supérieur quand utilisé avec le rendu fragmenté avec Azur, comme je l'ai raconté jusqu'ici. C'était mon principal objectif, et je suis très content de ce résultat.)

Impossible de pousser une mise à jour qui va ralentir les programmes de tout le monde, donc je repars case 1 pour écrire des fonctions de rendu avec effets dynamiques dans un style plus proche de bopti. Pas d'inquiétudes sur les délais, ce sera dix fois plus facile que ce que j'ai fait précédemment, du fait du style différent (le bottleneck RAM laisse beaucoup de latitude sur le CPU, et on va au plus simple).

Ça ne change pas non plus les fonctionnalités que je compte publier avec cette version.
Massena Hors ligne Rédacteur Points: 2088 Défis: 11 Message

Citer : Posté le 30/04/2022 20:29 | #


Oof. Bon courage, la fin est proche
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 02/05/2022 23:34 | # | Fichier joint


Update encore. Pour resituer le contexte : j'ai fini en fin de semaine dernière tous les effets dynamiques pour tous les formats dans Azur. C'est super rapide, et je suis super content du résultat. Mais si on l'applique dans gint, avec sa VRAM toute lente, c'est moins bon que le code actuel de gint 2.7.

J'ai déterminé que garder le même code pour gint et Azur était impossible, et donc entrepris de dupliquer tout le code frais d'Azur pour ensuite l'optimiser à la main dans gint. Quand je dis "optimiser", c'est en fait, selon les formats/effets :

  1. Soit le remplacer par le code actuel de gint 2.7, mais on garde les effets dynamiques.
  2. Soit le garder, dans les quelques cas où le code d'Azur est plus rapide que gint 2.7. C'est le cas en P8/P4 quand de la transparence est impliquée, parce que le code d'Azur saute les pixels transparents plus vite.

Actuellement, dans cette tâche, j'ai fini tous les formats 16-bit et P8. Tout n'est pas perdu, comme vous pouvez le voir sur le résumé de performances que j'ai généré ci-dessous.


C'est un peu dense, mais voilà comment ça se lit. La section du haut compare bopti vs. Azur, la section du bas compare bopti vs. gint 2.8. À chaque fois, les deux premières colonnes c'est bopti (avec une image opaque puis une image avec transparence). Les deux colonnes suivantes c'est les mêmes images mais avec Azur ou gint 2.8 ; enfin, les 4 colonnes de droite, ce sont les effets dynamiques.

Les colonnes 3 et 4 sont colorées en fonction du speedup par rapport à bopti. Comme vous pouvez le voir, sur mes scènes d'exemple, Azur démonte pas mal bopti avec des speedups dans le x2 voire x3 sur les formats à palette - le résultat de tout mon travail depuis l'annonce que j'allais refaire la gestion des images.

Bon, malheureusement, pour gint vanilla avec la VRAM ces optimisations ne sont pas disponibles, et vous pouvez voir que gint 2.8 (noté "gint(VRAM)") ne brille pas tout autant. C'est en fait pareil que bopti partout, sauf P8/P4 avec transparence, où le speedup dépend beaucoup de la quantité de pixels transparents. Ici j'en ai beaucoup (j'ai pris le célèbre acacia d'OutRun) donc on gagne plutôt pas mal. (Et P4 opaque je l'ai pas encore ajusté.)

Pour les 4 colonnes de droite, la couleur et le facteur d'accélération sont calculés par rapport au même type d'image mais sans effet dynamique, et indiquent en quelque sorte le "coût" de l'effet dynamique.

Je suis un peu frustré parce qu'avoir deux copies du système de rendu n'est pas très propre à mon goût, mais je voudrais vraiment passer à autre chose (pour autre chose = Rogue Life) donc je vivrai avec. Avec un peu de chance tout ça sera fini, euh... allez, demain, soyons optimistes.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 06/05/2022 22:29 | # | Fichier joint


(Ce message sera inclus dans les notes de publication de gint 2.8.)

Alright, donc même s'il aura fallu un mois et demi, je suis content de pouvoir annoncer le support du rendu d'images avec effets dynamiques dans gint 2.8.

Nouveau header <gint/image.h>

Toutes les fonctionnalités que je décris ici sont définies dans un nouveau header <gint/image.h>. Il contiendra aussi, dans un futur plutôt proche, des fonctions d'édition d'images comme celles de libimg.

Les effets dynamiques

Un effet dynamique, c'est une transformation de l'image (effet) appliquée à la volée durant le rendu (dynamique). Le cas classique c'est faire un miroir pour inverser le sens d'une image, mais on peut aussi jouer sur les couleurs.

À partir de gint 2.8, toutes les images de tous les formats supportent une petite palette d'effets dynamiques, ce qui vous donne plus d'options de dessin sans compromettre sur la vitesse (voir les performances ci-dessous). Ces effets sont les suivants :

Effets géométriques (cumulables)
  • IMAGE_HFLIP : miroir horizontal.
  • IMAGE_VFLIP : miroir vertical.

Effets de couleur (maximum un par appel)
  • IMAGE_CLEARBG efface une couleur (pour les format sans transparence).
  • IMAGE_SWAPCOLOR remplace une couleur par une autre (pour les formats sans transparence).
  • IMAGE_ADDBG ajoute un fond (pour les formats avec transparence).
  • IMAGE_DYE remplace toutes les couleurs opaques par une unie (pour les formats avec transparence).

Les fonctions dimage() et dsubimage() ne changent pas, mais de nouvelles fonctions sont ajoutées pour utiliser ces effets. Chaque fonction correspond à un effet de couleur choisi, et le paramètre effects accepte IMAGE_HFLIP et IMAGE_VFLIP en plus. En voici la liste avec le détail d'utilisation de chaque effet.

Pas d'effet de couleur

Les deux fonctions suivantes affichent une image sans effet de couleur. C'est comme dimage() ou dsubimage() sauf que le dernier paramètre supporte les miroirs. Comme toutes les fonctions de ce module, elles sont spécifiques par format ; c'est pas pour vous embêter, mais parce qu'une fonction générique qui pourrait appliquer tous les effets sur tous les formats (il y en a une) lierait beaucoup de code inutile à votre add-in, ce qui prend de la place pour rien.

dimage_{rgb16,p8,p4}(x, y, image, effects)
dsubimage_{rgb16,p8,p4}(x, y, image, left, top, w, h, effects)

Le paramètre effects supporte aussi quelques flags d'utilité générale :

  • IMAGE_NOCLIP_INPUT pour sauter la vérification que le rectangle indique pour l'image source (dans la version dsubimage()) est bien contenu dans l'image ;
  • IMAGE_NOCLIP_OUTPUT pour sauter la vérification que l'image ne dépasse pas de la VRAM durant le dessin ;
  • IMAGE_NOCLIP pour les deux.
  • (Le vieux flag DIMAGE_NOCLIP marche aussi par compatibilité.)

CLEARBG : Rendre une couleur transparente

Pour les images qui n'ont pas déjà de la transparence, cet effet sélectionne dynamiquement un fond à éliminer. Notez qu'il y a un paramètre supplémentaire color_or_index. Pour RGB16, on indique directement la couleur, tandis que pour P8/P4 c'est l'indice dans la palette.

dimage_{rgb16,p8,p4}_clearbg(x, y, image, effects, color_or_index)
dsubimage_{rgb16,p8,p4}_clearbg(x, y, image, left, top, w, h, effects, color_or_index)

L'effet IMAGE_CLEARBG est implicite quand on utilise cette fonction, il n'y a pas besoin de le spécifier (ce sera pareil pour tous les autres effets d'ailleurs). Par contre on peut toujours ajouter IMAGE_HFLIP, IMAGE_VFLIP, ou les options de clipping.

(Les deux fonctions "sans effet de couleur" utilisent CLEARBG pour les images converties avec transparence.)

SWAPCOLOR : Échanger une couleur par une autre

Cet effet remplace une couleur par une autre (c'est juste ADDBG légèrement généralisé). La couleur source est indiquée par un indice en P8/P4, mais la couleur de remplacement est toujours une couleur complète 16-bits, ce qui veut dire qu'on peut donner une couleur qui n'existe pas dans la palette.

dimage_{rgb16,p8,p4}_swapcolor(x, y, image, effects,
                               source_color_or_index, replacement_color)
dsubimage_{rgb16,p8,p4}_swapcolor(x, y, image, left, top, w, h, effects,
                                  source_color_or_index, replacement_color)

ADDBG : Ajouter un fond à une image transparente

Pour une image transparente, on peut changer dynamiquement la couleur de fond. Là aussi c'est une couleur explicite sur 16-bits : on peut donc utiliser une couleur hors-palette pour P8/P4.

dimage_{rgb16,p8,p4}_addbg(x, y, image, effects, bg_color)
dsubimage_{rgb16,p8,p4}_addbg(x, y, image, left, top, w, h, effects, bg_color)

DYE : Teinter tous les pixels opaques de façon uniforme

Pour une image transparente, cet effet remplace tous les pixels non transparents par une couleur désignée. C'est utile pour faire "clignoter" un sprite si quelqu'un prend des dégâts, pour afficher une police sous une couleur différente, et probablement quelques autres détails.

dimage_{rgb16,p8,p4}_dye(x, y, image, effects, fg_color)
dsubimage_{rgb16,p8,p4}_dye(x, y, image, left, top, w, h, effects, fg_color)

Fonctions génériques

Les fonctions suivantes acceptent n'importe quel effet de couleur ; passez dans effects le flag d'effet approprié, et ajoutez les arguments habituels de la fonction (par exemple IMAGE_DYE avec la couleur de teinte). Notez que pour les boucles serrées genre les tilesets qui tournent très souvent et avec des petites images, la va_list peut coûter un peu cher ; dans ce cas je conseille d'appeler la bonne fonction tout de suite.

dimage_{rgb16,p8,p4}_effect(x, y, image, effects, ...)
dsubimage_{rgb16,p8,p4}_effect(x, y, image, left top, w, h, effects,...)

dimage_effect(x, y, image, effects, ...)
dsubimage_effect(x, y, image, left, top, w, h, effects, ...)

Un autre inconvénient de ces fonctions c'est qu'elles vont lier à votre add-in tout le code de tous les effets pour tous les formats, ce qui est dommage ; ça augmente la taille du G3A et ralentit un peu le transfert.

Version alternative de CLEARBG

En P4, une fonction d[sub]image_p4_clearbg_alt() avec le même prototype que CLEARBG existe. Elle utilise une autre méthode d'affichage qui va plus vite pour les grandes images avec beaucoup de transparence, mais moins vite sur les petites images bien opaques. Ça gagne 2-3 FPS dans OutRun, donc c'est ça de pris.

Les performances

TL;DR : Pas de changement majeur par rapport à gint 2.7, mais Azur va être glorieux.

Mon plan initial pour implémenter ces effets était de (1) les écrire pour Azur, qui avait à l'époque ma dernière itération du système de rendu d'images, puis (2) réutiliser le code d'Azur dans gint. Pour diverses raisons, la partie 2 a majoritairement échoué (me causant ample frustration ces deux dernières semaines), et j'ai bataillé pour garder les performances de bopti. Mais j'ai explosé le compteur côté Azur.

Voici le résumé de performances généré par mon outil de benchmarking :


La section du haut compare bopti vs. Azur, la section du bas compare bopti vs. gint 2.8. À chaque fois, les deux premières colonnes c'est bopti (avec une image opaque puis une image avec transparence). Les deux colonnes suivantes c'est les mêmes images mais avec Azur ou gint 2.8 ; enfin, les 4 colonnes de droite, ce sont les effets dynamiques.

Les colonnes 3 et 4 sont colorées en fonction du speedup par rapport à bopti. Comme annoncé, Azur détruit pas mal bopti et va jusqu'à 2x voire 3x plus vite sur les formats à palette. Pour gint 2.8, c'est essentiellement pareil qu'avant.

Les 4 colonnes suivantes indiquent la vitesse de chaque effet dynamique par rapport aux colonnes 3 et 4, et représentent le "coût" de chaque effet. Comme vous pouvez le voir, le contrat des effets dynamiques est bien respecté : ça ne change presque rien par rapport au rendu normal. Pour le DYE P4 dans gint 2.8 le gros speedup vient du fait que ça utilise l'algorithme CLEARBG alternatif et le test était fait sur une image favorable pour cet algo.

Pour les curieux, voici l'état du document original traquant toutes ces modifications. Vous pouvez voir que les speedups côté Azur sont vraiment proches des rapports entre les nombre de cycles par pixel de chaque effet ; c'est parce que le CPU est limitant dans la plupart de mes tests.


Voilà, c'est un gros morceau, mais déjà un bon début.
Slyvtt Hors ligne Community Manager Points: 747 Défis: 0 Message

Citer : Posté le 06/05/2022 22:56 | #


Bravo Lephe, c'est vraiment un super boulot
Je sens qu'on va voir apparaître des trucs vraiment magnifiques avec tous ces nouveaux effets et ces nouvelles possibilités.
Notamment les graphistes vont bien s'amuser avec le DYE je pense.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 07/05/2022 19:40 | #


Merci. Les effets actuels sont vraiment modestes ; juste de quoi ajouter/enlever un fond, et dye. On pourrait en implémenter d'autres, par exemple pour assombrir/éclaircir/etc. Mais comme pour l'instant on est limités à un effet de couleur à cause de la structure du code, ça ne marcherait pas avec de la transparence, donc ce serait pas pratique.

Je crois l'avoir mentionné à un moment, mais je rêverais de pouvoir implémenter un compilateur qui génère les boucles assembleur serrées à partir d'une description d'un effet dynamique. Dans 10 ans peut-être, lol.
Slyvtt Hors ligne Community Manager Points: 747 Défis: 0 Message

Citer : Posté le 07/05/2022 20:47 | #


Ca y est un va avoir des vrais shaders dans gint
avec compilation à la volée et un pipeline de rendu à la Vulkan/OpenGL

Ajouté le 08/05/2022 à 07:39 :
On saurait ajouter des effets de distorsion par exemple ?
Au niveau calcul se serait beaucoup plus lourd par contre, mais par exemple pour une téléportation avoir un effet DYE sur la couleur et en même temps un calcul de sinusoïde sur le décalage de positionnement des pixels en X (via une fonction externe à priori, comme un shader) en fonction du temps et de la position Y dans l'image.

On peut aussi imaginer des effets plus complexe avec X et Y qui bougent (par exemple une spirale).

Je précise avant de me faire taper, que c'est juste une question et que je n'ai pas ce besoin
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 08/05/2022 23:52 | #


Tu peux toujours, mais entre le fait que tu cumules DYE et la distorsion, et la complexité inhérente de l'effet (la forme de la sortie n'étant plus rectangulaire), ce serait trop douloureux à coder de façon optimisée comme ça en assembleur.

Ce genre de trucs je le ferais plutôt en préprocessing, de la même façon que par exemple les rotations et agrandissements de sprites dans After Burner sont calculés dans des images (même si l'effet est codé en assembleur...).

Éventuellement un effet de distorsion appliqué à l'écran complet en post-processing ça sonne raisonnable ; c'est le genre de trucs que je collerais bien comme shader dans Azur.

Donc est-ce que l'effet est possible ? Oui, tu peux toujours coder ce que tu veux en C. Mais pour ce qui est d'un effet dynamique intégré à dimage(), ce serait pousser trop loin la définition du contrat que dimage() essaie de remplir
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 11/05/2022 21:09 | #


J'étais en voyage à Londres pendant quelques jours sans ma calto, donc j'ai commencé la seule chose disponible aisément qui est d'écrire les fonctions de manipulation d'images dans <gint/image.h> (les fonctions de libimg essentiellement).

Ça se fait, sauf pour P4 qui est très chiant parce que les demi-octets c'est terrible à utiliser. Donc je vais probablement ne proposer la plupart des fonctions que pour RGB16 et P8 (ce qui est déjà un plus par rapport à libimg qui ne supporte que RGB16), étant admis que les images P4 peuvent être converties en P8 et réciproquement pour obtenir le même effet.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 15/05/2022 22:55 | #


(Ce message sera inclus dans les notes de publication de gint 2.8.)

Le nouvel en-tête <gint/image.h> dont j'ai parlé dans ce message et qui est disponible sur Graph 90+E contient aussi quelques changements sur le format des images et plein de nouvelles fonctions.

Changements sur le format

Le nouveau format d'image combine l'ancien format avec les fonctionnalités que libimg apportait. J'avais déprécié le nom image_t pour éviter la confusion quand j'ai publié libimg, mais vu sa faible utilisation et le fait que le nouveau header la remplace, j'ai désactivé le warning. C'est quand même pratique d'écrire image_t.

Les changements sont les suivants :

  • Le champ alpha a disparu ; pour simplifier le traitement des images, chaque format a une valeur de transparence dédiée. Pour RGB565A c'est 0x0001 (quasi-noir), pour P8_RGB565A et P4_RGB565A c'est le premier indice de la palette (à savoir -128 et 0 respectivement). La fonction image_alpha() donne la valeur pour chaque format.
  • Un champ stride indiquant la distance entre chaque ligne en octets a été ajouté. Ça permet à image_sub() d'exister.
  • Le tableau de données data ne contient maintenant plus que les pixels, et la palette est séparée dans un tableau palette dont la dimension est indiquée dans color_count.
  • Le champ profile a été renommé format, pas juste pour vous embêter mais parce que P4 et P8 ont changé dans cette update, et que je sais qu'il y a du code qui traîne qui manipule les images directement et qui crashera s'il n'est pas modifié. Avec ce changement il y aura une erreur de compilation, ce qui est mieux qu'un crash silencieux.

De façon générale vous êtes toujours libres de lire les champs. Vous pouvez aussi les modifier plus ou moins à loisir ; le pire que vous risquez c'est de vous planter sur la gestion de mémoire et de perdre des pointeurs qu'il fallait free().

API pour créer des images

En plus d'obtenir des images avec fxconv, vous pouvez aussi en créer dynamiquement. Notamment la fonction image_alloc() qui crée une image de la dimension demandée au format spécifié. image_alloc() remplit tout sauf la palette, que vous pouvez spécifier ensuite avec image_set_palette(), image_alloc_palette(), image_copy_palette() ou à la main. Toute image créée dynamiquement doit être libérée par image_free().

Comme fonctions de plus bas niveau, vous avez image_create() qui crée juste la coquille de l'image sans lui donner de données ni de palette ; c'est utilisé par image_create_vram() qui donne accès à la VRAM sous la forme d'une image RGB565 et par image_sub() qui donne accès à un sous-rectangle d'une image comme si c'était une image indépendante (P8/RGB16 seulement).

Opérations de base

Les opérations les plus classiques sont image_get_pixel() pour obtenir la valeur d'un pixel (soit la couleur 16-bit soit un indice dans la palette, selon le format) et image_set_pixel() pour les écrire. image_decode_pixel() permet de décoder les indices en accédant à la palette. Toutes ces fonctions sont assez lentes si vous les utilisez en boucle, et l'intention c'est que toute fonction un peu compliquée voudra accéder directement aux tableaux data et palette de l'image.

image_fill() remplit une image d'une couleur donnée et image_clear() de la couleur transparente (pour les formats avec transparence).

Enfin, image_copy() permet de copier d'une image vers une autre en convertissant la plupart des formats. Elle possède une variation image_copy_alloc() qui alloue la cible et permet donc de créer une nouvelle image avec conversion. Ça reprend un thème classique de libimg où plein de fonctions ont une variante _alloc() qui alloue l'image cible au lieu de la prendre en paramètre.

Transformations

La plupart des fonctions de transformation de <gint/image.h> ne marchent pas sur les images P4, parce que ce format est juste casse-pieds à programmer et souvent plus lent à cause du décodage.

Pour l'instant, seules quelques transformations géométriques sont supportées : image_hflip(), image_vflip(), et une fonction étonnamment puissante, image_linear(). Les trois ont, comme précédemment, une variation nommée _alloc() qui alloue l'image de destination au lieu d'en prendre une en argument.

image_linear() implémente une transformation linéaire, ce qui permet de réaliser n'importe quelle combinaison de rotation, redimensionnement, et miroir en même temps. La boucle interne est codée en assembleur, et After Burner s'en sert en temps réel pour ses sprites. Spécifier la transformation linéaire à la main est un peu dur, donc quelques fonctions intermédiaires sont fournies pour le faire pour vous.

Un tutoriel complet sur toutes ces choses serait sans doute bienvenu, mais je pense qu'il y a des choses plus urgentes à traiter dans les tutoriels d'utilisation de gint, donc je vais en rester là pour l'instant.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 15/05/2022 23:45 | #


(Ce message sera inclus dans les notes de publication de gint 2.8.)

J'ai enfin intégré à gint le support de l'overclock, avec l'aide de SlyVTT qui a passé beaucoup de temps à collecter des données et à prototyper le système.

Pour l'instant l'overclock est disponible sur Graph 90+E et sur Prizm (mais je ne peux pas tester sur Prizm, donc j'attends encore un test/confirmation).

Pour l'utiliser, ce n'est pas très difficile. <gint/clock.h> fournit une énumération avec les 5 niveaux d'overclock de Ftune/Ptune, ainsi que deux fonctions :

#include <gint/clock.h>

enum {
    CLOCK_SPEED_UNKNOWN = 0,
    CLOCK_SPEED_F1 = 1,
    CLOCK_SPEED_F2 = 2,
    CLOCK_SPEED_F3 = 3,
    CLOCK_SPEED_F4 = 4,
    CLOCK_SPEED_F5 = 5,
    CLOCK_SPEED_DEFAULT = CLOCK_SPEED_F1,
};

int clock_get_speed(void);
void clock_set_speed(int speed);

clock_get_speed() détermine le niveau actuel (ou UNKNOWN si c'est une combinaison de paramètres qui n'est pas un niveau par défaut de Ftune/Ptune) et clock_set_speed() change le niveau d'overclock. En principe vous pouvez le faire n'importe quand, cela dit je ne serais pas surpris qu'un cas particulier m'ait échappé si vous le faites au milieu d'un transfert USB ou à 60 fois par seconde. x)

Voilà ça c'est tout simple. Enjoy ! o/
Kikoodx Hors ligne Labélisateur Points: 2969 Défis: 11 Message

Citer : Posté le 16/05/2022 00:11 | #


Super pour l'overclock ! J'aurais aimé avoir moyen de restaurer le niveau overclock de l'utilisateur à la sortie de l'add-in (même si il est custom), mais c'est déjà vraiment pas mal.
mi lape ala.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 16/05/2022 00:22 | #


Hmm en effet ce serait bien d'avoir ça.
Slyvtt Hors ligne Community Manager Points: 747 Défis: 0 Message

Citer : Posté le 16/05/2022 09:28 | #


Hello,

dans l'absolu ça doit être possible de faire une sauvegarde de l'état d'overclock, même si la valeur retournée est CLOCK_SPEED_UNKNOWN. Il faudrait lire et stocker l'ensemble des valeurs des registres (au lieu de juste les comparer à la bases des paramètres existants dans PTune/FTune) et de les restaurer à la sortie de manière identique.

Juste peut être un peu plus hasardeux car on sait pas trop ce qu'on peut trouver comme combinaison, sachant que les jeux de paramètres de Ptune/FTune sont tout de mêmes réputés sûrs (car pas trop violents pour chaque architecture et surtout largement testés).

Mais après tout pourquoi pas ajouter des fonctions clock_save_user_speed() et clock_restore_user_speed() ...

Si il y a une demande. Mais honnêtement, y a t il beaucoup de monde qui overclock en dehors des paramètres de PTune/FTune ? Je suis pas certain.
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 16/05/2022 09:40 | #


L'idée c'est pas tant de sauvegarder/restaurer hors des paramètres de Ftune que de sauvegarder/restaurer tout court - un add-in qui overclocke automatiquement pour maintenir ses FPS, par exemple, a sans doute envie que le niveau d'overclock revienne à sa valeur initiale quand on quitte.
Slyvtt Hors ligne Community Manager Points: 747 Défis: 0 Message

Citer : Posté le 16/05/2022 10:05 | #


Oui c’est a ca que je pensais : faire une photographie de l’état initial de l’ensemble des paramètres au lancement de l’addin puis a la fin les restaurer comme si de rien n’était.

Tu penses que ça le ferait pas ?
Lephenixnoir Hors ligne Administrateur Points: 22261 Défis: 149 Message

Citer : Posté le 16/05/2022 10:37 | #


Bien sûr que si, c'est ce que tous les drivers de gint font déjà !
Slyvtt Hors ligne Community Manager Points: 747 Défis: 0 Message

Citer : Posté le 16/05/2022 12:27 | #


OK, on pourra regarder alors. Ca devrait pas être un problème, juste peut être un peu de boulot pour remettre à plat la liste complète de tout ce qu'on peut toucher via les outils PTune/FTune pour être certains de ne rien oublier. Mais à voir si c'est vraiment nécessaire. Il serait à mon sens plus utile en priorité d'offrir ces mêmes deux fonctions aux monochromes en décortiquant les versions dédiées de PTune afin de les amener elles aussi sur cette première étape de "l'overclock facile".

J'ai deux/trois questions concernant les image_t :

- à lire le display-cg.h et image.h, ainsi que tes explications, on a perdu la compatibilité du membre "data" entre image_t et bopti_image_t, donc quand je triffouillais la palette dans MagicLight, mon code n'est donc plus portable (en soit c'est pas un problème, c'est juste pour vérifier).

- tu peux donner un exemple d'utilisation de image_create_vram() STP. J'imagine que c'est pour gagner un blit (en évitant un dimage() sur un écran complet), mais j'avoue avoir du mal à voir comment on s'en sert. Si on alloue une image en VRAM et qu'on fait un dimage() d'un sprite par exemple, on va "killer" les data de l'image de la VRAM. J'avoue que j'ai du mal à voir comment le système est pensé.

- autre question portage, du coup le resize de OutRun sur les RGB565 est opérationnel désormais et si je comprends bien il faut que je passe par image_linear() (en fait un image_linear_alloc() qui va enlever pas mal de complexité je pense) pour faire un scale up. On est bien d'accord aussi que dans le cas général, il faut passer les valeurs dans la structure image_linear_map, sauf si on utilise les fonctions individuelles (rotation, scale, translation) auquel cas on spécifie les paramètres "simples" de la transformation et on reçoit en retour le image_linear_map correspondant. (Je sais pas si ma question est claire en fait ).

En tout cas, y'a de la viande dans cette update on va pouvoir s'amuser ...
Précédente 1, 2, 3 ··· 10 ··· 20 ··· 30 ··· 40 ··· 50 ··· 60 ··· 62, 63, 64, 65, 66, 67 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 42 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