Posté le 13/11/2021 21:14
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 131 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
Citer : Posté le 14/11/2021 14:38 | #
Bon,
j'ai crois savoir d'où vient le souci.
Je pense que le problème vient de la fonction de "ray-casting" qui est vraiment trop gourmande.
Je vais donc essayer de "l'alléger" un peu pour voir si ça résout le schmilblick ...
A plus
Sly
Ajouté le 15/11/2021 à 08:50 :
Après moultes galères, la source du bug a été isolée, elle provenait bien de mes routines de primitives graphiques avec gestion de la transparence.
Cette fois c'est OK, j'ai donc une base graphique qui gère le canal alpha sous la forme (R,G,B,A) avec chacune des composantes entre 0..255.
Il faudrait je pense à terme les convertir en ASM afin de booster les performances, mais globalement ça va pas trop mal.
A ce stade cela donne :
Je continue de prendre en main de SDK.
Et bien entendu, vu que le débogage de plantages est terminé, je peux passer au fond du problème : développer le jeu en lui même ...
Ciao
Sly
Citer : Posté le 15/11/2021 08:55 | #
Désolé de pas avoir regardé, un autre cas est encore sur le feu. Content que tu aies trouvé, au moins c'était bien de ton côté...
Tu peux utiliser GDB sur l'émulateur, même si c'est expérimental je dirais : https://www.planet-casio.com/Fr/forums/topic16575-1-fx-cg50-manager-plus-gdbserver-debuggez-vos-add-ins-et-casiowin.html
Sinon personnellement je fais du dprint() quand vraiment ça va pas et sinon de l'introspection. Si tu veux tu peux aussi envoyer du texte en USB à ton ordinateur si tu testes avec une vraie calto. Sur l'émulateur il n'y a pas beaucoup mieux je crois. Le système de fichiers tu verras vite que c'est plus une plaie qu'un outil, il est notamment extrêmement lent en écriture (~1 Mo/minute), avec un petit coût en plus côté gint.
Citer : Posté le 15/11/2021 09:43 | #
Désolé de pas avoir regardé, un autre cas est encore sur le feu. Content que tu aies trouvé, au moins c'était bien de ton côté...
Se gratter la tête est toujours formateur et permet de comprendre où on a fait la bêtise pour ne plus la faire. Ici dans mon cas "simplement" une erreur classique; écriture en mémoire dans une zone non prévue (l'erreur de débutant). A vouloir attaquer la mémoire directement pour accélérer les routines graphique de transparence, un "<" qui était en fait un "<=" dans le code !!!
D'ailleurs, j'ai pas trouvé de "librairie" graphique de primitives de ce style dans gint/fxSDK, en développant quelques routines supplémentaires, ça pourrait vous intéresser pour le SDK ? A ce stade ça gère chaque canal sur un "unsigned char", mais si besoin je peux faire les versions sur des "unsigned int" fusionnés (RGB565) afin d'être dans la philosophie de gint::dpixel. Faut juste me dire. Tel que je le comprends, pour l'instant le SDK est très orienté "plateformer" et ce sont principalement les copies de "tiles" qui sont implémentées via dimage/dsubimage (qui envoient du bois d'ailleurs soit dit en passant ).
Tu peux utiliser GDB sur l'émulateur, même si c'est expérimental je dirais : https://www.planet-casio.com/Fr/forums/topic16575-1-fx-cg50-manager-plus-gdbserver-debuggez-vos-add-ins-et-casiowin.html
Oui j'ai vu ça ce matin, faut que je me penche dessus.
Sinon personnellement je fais du dprint() quand vraiment ça va pas et sinon de l'introspection. Si tu veux tu peux aussi envoyer du texte en USB à ton ordinateur si tu testes avec une vraie calto.
Pour l'instant j'ai pas le hardware, mais logiquement c'est pour bientôt . Merci SynchroDonjon (et Pavel d'avoir choisi la Graph 35 ).
D'ailleurs; dois-je m'attendre à une différence de vitesse significative entre le vrai hardware et le simulateur ? Ca tourne pas trop mal pour un puzzle game sur l'émulateur, j'espère qu'il en sera de même sur un vrai hardware, sans avoir besoin de "PTune" avant.
Sur l'émulateur il n'y a pas beaucoup mieux je crois. Le système de fichiers tu verras vite que c'est plus une plaie qu'un outil, il est notamment extrêmement lent en écriture (~1 Mo/minute), avec un petit coût en plus côté gint.
C'est gravé physiquement dans la pierre avec un marteau et un burin ? La vache, ça pique les yeux de lire ça de nos jours ...
Il faudra de toute manière que j'implémente des input/output pour les lectures/sauvegarde de niveaux. Mais bon ce sera très petit en taille (des simples fichiers TXT de quelques Ko au maximum).
Comme toujours, merci pour ton aide précieuse Lephe
Ciao
Sly
Citer : Posté le 15/11/2021 10:08 | #
Ça peut être très cool ! Il y a quelques considérations ici. Note qu'il y a MonochromeLib qui traîne déjà pour les formes plus compliquées ; pour la transparence on n'a rien en effet.
Le côté "platformer" n'est pas particulièrement voulu, c'est surtout que gint fournit les trucs les plus fondamentaux sous forme optimisée et puis y'a une affinité pour les platformers par ici.
Je suggère juste de faire attention à la vitesse parce que y'a vraiment moyen de taper dans du très lent. J'ai pas trop vu ton code mais bien sûr les divisions sont à bannir, multiplications à factoriser, etc. Surtout si tu traites beaucoup de couleur d'un coup (eg. un sprite semi-transparent). On est à la limite entre ce qui se fait bien et ce qui doit se faire attentivement.
C'est à voir, on est généralement à la limite des 30 FPS sans overclock dans les platformers par exemple. L'attitude générale c'est "la majorité des choses on peut les faire, mais si c'est non-trivial il faut les faire attentivement". Tu auras tout le temps de voir venir cela dit, y'a une lib pour mesurer les perfs et plein d'outils d'optimisation.
C'est gravé physiquement dans la pierre avec un marteau et un burin ? La vache, ça pique les yeux de lire ça de nos jours ...
Il faudra de toute manière que j'implémente des input/output pour les lectures/sauvegarde de niveaux. Mais bon ce sera très petit en taille (des simples fichiers TXT de quelques Ko au maximum).
C'est le tradeoff - le précédent fs était fait maison, beaucoup plus rapide mais aussi tellement limité qu'on pouvait pas implémenter le standard C avec. Par exemple tous les fichiers devaient avoir une taille fixée à la création, on ne pouvait pas écrire un nombre impair d'octets (limitation de leur configuration de la ROM pour leur défense), on ne pouvait pas modifier un fichier créé (enfin on pouvait changer les 1 en 0 mais pas l'inverse), j'en passe et des meilleures. Là je crois que le fs est un fs normal (c'est du FAT, Yatis connaît tous les détails) c'est déjà ça. Perso je préfère fonctionnel à rapide, même si c'est vrai que du coup on a pris l'habitude de pas trop s'en servir.
Pour les sauvegardes, éditeurs de niveaux, etc. ça pose absolument aucun problème, juste avoir un écran avec une barre de progrès ou un truc du genre parce que c'est pas instantané.
Citer : Posté le 15/11/2021 10:47 | #
Ça peut être très cool ! Il y a quelques considérations ici. Note qu'il y a MonochromeLib qui traîne déjà pour les formes plus compliquées ; pour la transparence on n'a rien en effet.
Pour le moment mes routines sont très orientées "SDL-like" car c'est de là que je viens, mais je vais regarder ce qui existe déjà. Mon zinzin est limité à la CG-50/Graph 90+E, j'ai oublié de préciser
Je suggère juste de faire attention à la vitesse parce que y'a vraiment moyen de taper dans du très lent. J'ai pas trop vu ton code mais bien sûr les divisions sont à bannir, multiplications à factoriser, etc. Surtout si tu traites beaucoup de couleur d'un coup (eg. un sprite semi-transparent). On est à la limite entre ce qui se fait bien et ce qui doit se faire attentivement.
Pour le moment c'est "optimisé" level 1 je dirais : pas de division, mais en étant malin, on peut faire un "bit shift", et les multiplications sont factorisées (une par canal) :
De même quand le canal Alpha vaut 0, on skip le point (car totalement transparent) ou si canal Alpha vaut 255 alors on enclenche une routine fast pixel sans transparence. Mais globalement la transparence gérée en software reste un truc lourd en calculs.
Ca donne ça IRL (si tu vois des choses à améliorer, n'hésite surtout pas, car ne connaissant pas le proc, il y a peut être mieux à faire) :
/* draw a pixel at coordinates (X,Y) of color (R,G,B) */
/* all color values (R,G,B) to be in the range 0..255 */
void _fastPixelRGB( unsigned int X, unsigned int Y, unsigned char R, unsigned char G, unsigned char B )
{
if ( X<DWIDTH && Y<DHEIGHT)
{
unsigned int color = (((R>>3) << 11) | ((G>>2) << 5 ) | (B>>3));
gint_vram[ Y*DWIDTH + X ] = color;
}
}
/* return the color of the pixel at coordinates (X,Y) */
/* modifies R,G,B given as parameters */
/* all returns R,G,B are in range 0..255 */
void _getPixelRGB( unsigned int X, unsigned int Y, unsigned char *R, unsigned char *G, unsigned char *B )
{
if (X<DWIDTH && Y<DHEIGHT)
{
unsigned int color = gint_vram[ Y*DWIDTH + X ];
*R = (((color >> 11 ) & 0b11111 ) << 3);
*G = (((color >> 5) & 0b111111) << 2);
*B = ((color & 0b11111) << 3);
}
}
void _calculateBlendRGBA( unsigned int X, unsigned int Y, unsigned char *R, unsigned char *G, unsigned char *B, unsigned char A )
{
unsigned char Ro, Go, Bo;
_getPixelRGB( X, Y, &Ro, &Go, &Bo );
*R = Ro + (((*R-Ro)*A) >> 8);
*G = Go + (((*G-Go)*A) >> 8);
*B = Bo + (((*B-Bo)*A) >> 8);
}
void _pixelRGBA( unsigned int X, unsigned int Y, unsigned char R, unsigned char G, unsigned char B, unsigned char A )
{
if (X<DWIDTH && Y<DHEIGHT)
{
if (A==0) return;
else if (A==255) _fastPixelRGB( X, Y, R, G, B );
else
{
unsigned char Rf = R;
unsigned char Gf = G;
unsigned char Bf = B;
_calculateBlendRGBA( X, Y, &Rf, &Gf, &Bf, A );
_fastPixelRGB( X, Y, Rf, Gf, Bf );
}
}
}
On pourrait gagner un peu des cycles en splittant la fonction _getPixelRGB en 2 (une _getPixelRGB comme écrite actuellement pour appel direct par l'utilisateur et une_fastGetPixelRGB en static void pour appel depuis la fonction _calculateBlendRGBA pour faire sauter le test de X<largeur et Y<hauteur, sachant que ce test est fait dans la routine _pixelRGBA auparavant).
J'ai encore énormément à découvrir dans le SDK et les outils à disposition, mais clairement "y'a moyen de moyenner"
@+
Sly
Citer : Posté le 15/11/2021 10:53 | #
C'est pas mal déjà. Je soupçonne que tout est inliné de toute façon donc le test des bornes ne sera fait qu'une fois. L'approximation légère dans le >> 8 est tout à fait acceptable. Tu gagnerais sans doute à ne pas utiliser trois variables différentes pour les couleurs, une union entier/tableau semble appropriée.
Sinon ouais essaie de limiter la quantité que tu en mets à l'écran et tant que tu remplis pas toute la surface avec ça devrait le faire en termes de perfs.
Citer : Posté le 15/11/2021 12:34 | #
C'est pas mal déjà. Je soupçonne que tout est inliné de toute façon donc le test des bornes ne sera fait qu'une fois. L'approximation légère dans le >> 8 est tout à fait acceptable. Tu gagnerais sans doute à ne pas utiliser trois variables différentes pour les couleurs, une union entier/tableau semble appropriée.
Sinon ouais essaie de limiter la quantité que tu en mets à l'écran et tant que tu remplis pas toute la surface avec ça devrait le faire en termes de perfs.
Pour le moment c'est pas en inline, mais c'est prévu, on gagnera les "calls" à chaque itération.
Oui, je préfère mon approx ">>8" (soit diviser par 256) que me prendre une division par 255 . Le proc sera content ...
J'ai par contre une question métaphysique : dans gint, je comprends que la fonction dpixel gère le RGB565 comme du RGB5(0+5)5 (le bit en plus du vert n'est pas utilisé) donc toutes les composants sont sur 0..31 au lieu de R&B sur 0..31 et G sur 0..63.
Je suis parti sur l'optique de tout faire en "vrai" RGB565, mais du coup il y a un "biais" entre ma fonction pixel et dpixel de gint.
Y vois tu un problème ? As tu une préférence ou c'est complètement "open" du moment que c'est cohérant ?
Perso j'aime bien le vrai RGB565 qui rend les teintes un peu "greenish" quand on use du canal vert sur les 6bits au lieu de seulement 5bits, mais certains n'aiment pas du tout.
Sly
Citer : Posté le 15/11/2021 12:44 | #
Oh ne t'inquiète pas le compilateur il inline tout seul. Là tu vois avec -O2 déjà _getPixelRGB() et _calculateBlendRGBA() se font inliner automatiquement. _fastPixelRGB() est un peu trop gros pour qu'il le fasse sans réfléchir, mais rends-la static et pouf il dégaine (puisqu'en static après l'inlining il peut supprimer la fonction d'origine, ce qui annule l'inconvénient de dupliquer le code).
Je suis parti sur l'optique de tout faire en "vrai" RGB565, mais du coup il y a un "biais" entre ma fonction pixel et dpixel de gint.
Y vois tu un problème ? As tu une préférence ou c'est complètement "open" du moment que c'est cohérant ?
C'est bien du RGB565 partout. Il n'y a que le macro C_RGB() qui considère le vert sur 5 bits par homogénéité. Je préfère que tu sois cohérent avec l'API, ce qui tombe bien puisque c'est bien du RGB565.
Au fait tu peux donner des noms type "d*" à tes fonctions si tu veux, du genre dpixelRGBA() ou autre. Ça ne me pose pas de problème de les considérer comme une extension des fonctions de dessin natives (et de surveiller la compatibilité dans le futur).
Je suis pas sûr de ce que tu veux dire par là, mais note que l'écran de la Graph 90+E n'est pas un écran plasma avec des couleurs super fidèles (en particulier il n'est pas très saturé à mon goût) donc je suis pas sûr que les subtilités se voient. :P
Citer : Posté le 15/11/2021 13:15 | #
Oh ne t'inquiète pas le compilateur il inline tout seul. Là tu vois avec -O2 déjà _getPixelRGB() et _calculateBlendRGBA() se font inliner automatiquement. _fastPixelRGB() est un peu trop gros pour qu'il le fasse sans réfléchir, mais rends-la static et pouf il dégaine (puisqu'en static après l'inlining il peut supprimer la fonction d'origine, ce qui annule l'inconvénient de dupliquer le code).
OK nickel
C'est bien du RGB565 partout. Il n'y a que le macro C_RGB() qui considère le vert sur 5 bits par homogénéité. Je préfère que tu sois cohérent avec l'API, ce qui tombe bien puisque c'est bien du RGB565. Au fait tu peux donner des noms type "d*" à tes fonctions si tu veux, du genre dpixelRGBA() ou autre. Ça ne me pose pas de problème de les considérer comme une extension des fonctions de dessin natives (et de surveiller la compatibilité dans le futur).
Ca marche, je vais en profiter pour ajouter quelques primitives et je t'enverrai le code, tu pourras si besoin le remouliner "à ta sauce" pour le verser dans le Gitea de gint à l'occasion.
Logiquement en "vrai" RGB565, la couleur maximale (donc le blanc en théorie), est en fait R=0b11111000 (=248) G=0b11111100 (=252) et B=0b11111000 (=248) soit (248,252,248). La composante G est donc légèrement plus prononcée que les composantes R&B, ce qui donne une très légère "chaleur" à l'image (mais c'est hyper subtil), d'où l'appelation "Greenish screen". D'où la question , mais c'est du chipotage je te l'accorde. Cela dit, c'est toujours une question à se poser dans on travaille avec ce mode RGB565 car on a vite fait de rendre des morceaux de code incompatibles entre eux si on ne fait pas attention.
Une variante très sympa du RGB565 pour les jeux est le ARGB1555 qui code chaque couleur sur 5bits et garde le bit fort pour avoir une transparence nulle ou totale. Mais je ne l'ai hélas jamais vu implémenté dans un hardware correspondant.
Sly
Citer : Posté le 15/11/2021 13:51 | #
Je vois, mais ça c'est si l'écran en interne il utilise vraiment du RGB888 et qu'il n'applique pas de correction, aucun n'étant garanti.
(Note aussi du coup sur la question des maximums que dans ton blend tu multiplies au plus par 255 mais tu divises par 256 donc tu assombris un poil. Tu l'as peut-être vu.)
Dans bopti (le système derrière dimage) j'ai trouvé que le compromis n'en valait pas la peine et j'ai implémenté à la place un format appelé rgb565a qui réserve une valeur 16 bits à l'alpha et tout le reste est en RGB565. Tu as accès à ça dès que tu utilises fxconv. C'est un peu exotique mais les couleurs sont mieux préservées.
Citer : Posté le 15/11/2021 15:55 | #
Pour l'instant j'ai pas le hardware, mais logiquement c'est pour bientôt . Merci SynchroDonjon (et Pavel d'avoir choisi la Graph 35 ).
Je vois que j'ai bien choisi mon lot
Une petite remarque. L'émulateur fourni par CASIO est plus lent que la vraie calculatrice, il est donc tout à fait possible que ton jeu fonctionnera bien sur la calculatrice sans optimisations supplémentaires.
Citer : Posté le 15/11/2021 18:03 | #
Je vois que j'ai bien choisi mon lot
Une petite remarque. L'émulateur fourni par CASIO est plus lent que la vraie calculatrice, il est donc tout à fait possible que ton jeu fonctionnera bien sur la calculatrice sans optimisations supplémentaires.
Oui j'avoue que j'étais content que tu prennes la Graph 35 (même si je m'en serai accommodé) car la Graph 90 me tentait bien.
Merci pour l'info, je vais laisser en l'état pour le moment, sans forcément chercher à booster les performances, mais plutôt viser la maintenabilité du code. Si a terme le besoin de performance se fait sentir, je me mettrai alors les mains dans le cambouis pour optimiser à fond.
Je me tâte à regarder si une compilation/conversion de la SDL (1.2) est jouable ou pas, ça pourrait être cool d'avoir cette librairie pour le portage de jeux. Mais je sais pas évaluer à l'instant "t" ce que cela implique en terme de taf. Typiquement une grosse part du boulot pourrait être reprise de l'énorme avancée de Hoffa fait pour porter la lib sur la nSpire, mais en adaptant au hardware de la CG-50 (video et clavier + gestion mémoire spécifique avec heap très limité).
Mais ça fait pas mal de chose dans la "TODO list", entre la STL et la SDL faut pas être trop gourmand.
Ciao
Sly
Citer : Posté le 15/11/2021 18:57 | #
Tu verras les perfs que je t'aurai envoyé la machine du coup (ce qui ne devrait pas tarder ).
Pour la SDL 1.2 ça devrait être possible. Faut juste voir si tu veux émuler l'API ou ajouter une target à la lib. En tous cas je pense que c'est faisable, c'est juste qu'il y a pas beaucoup de grands chantiers en ce moment.
Au passage le tas est pas si petit que ça, 512 + 128 kio de base, et tu peux piquer de la RAM ailleurs s'il le faut (jusqu'à 6 Mo en cas de grosse grosse panique).
Mais oui la STL c'est déjà assez solide.
Citer : Posté le 15/11/2021 20:21 | #
Tu verras les perfs que je t'aurai envoyé la machine du coup (ce qui ne devrait pas tarder ).
Cool, j'ai hâte de voir la bête.
Pour la SDL 1.2 ça devrait être possible. Faut juste voir si tu veux émuler l'API ou ajouter une target à la lib. En tous cas je pense que c'est faisable, c'est juste qu'il y a pas beaucoup de grands chantiers en ce moment.
L'idée est de rajouter une cible pour se servir au maximum de l'existant et juste ajouter localement un "patch" pour brancher les fonctions proprement au hardware. D'après ce que je comprends (mais je peux être complètement dans le faux), la réécriture de la SDL consiste principalement à rediriger les aspects "vidéos" et "claviers", sachant qu'on peut faire en sorte de s'appuyer sur gint. Sur la nSpire, c'est cette philosophie qui est employée, et je trouve ça super pratique. La SDL est vraiment bien conçue dans le sens où il y a un header pour chaque sous-module de la lib (audio, video, mouse, keyboard, CDROM, ...), chacun activable via un #define dans un fichier de configuration par architecture/machine. Par exemple pour la CG-50, tu indiques que tu trash divers modules via par exemple dans le fichier SDL_config.h
#define SDL_CDROM_DISABLED 1
#define SDL_JOYSTICK_DISABLED 1
#define SDL_LOADSO_DISABLED 1
#define SDL_THREADS_DISABLED 1
in fine la lib est compilée en prenant en compte seulement les modules demandés. Par contre il faut tout de même faire en sorte que les modules à implémenter soient bien compatible avec le matériel.
Au passage le tas est pas si petit que ça, 512 + 128 kio de base, et tu peux piquer de la RAM ailleurs s'il le faut (jusqu'à 6 Mo en cas de grosse grosse panique). Mais oui la STL c'est déjà assez solide.
Ca c'est hyper intéressant car l'intérêt d'une lib comme la SDL, c'est d'avoir moultes ressources à manipuler, d'où besoin de pas mal de mémoire.
Je pense qu'il y a moins de boulot sur la SDL que sur la STL. Je pense que je vais me pencher sur la SDL en premier car la STL, c'est vraiment un gros morceau, surtout que vous m'avez refroidit Pavel et toi sur le filesystem. Donc il va vraiment falloir faire les choses proprement et de manière réfléchie.
A plus
Sly