[SDK] MonochromeLib - une lib graphique monochrome
Posté le 09/06/2010 02:22
MonochromeLib, qu'est ce que c'est ?
MonochromeLib est une bibliothèque de dessin pour le SDK Casio Graph 85.
Elle fournit aux développeurs des fonctions optimisées pour tracer toute sorte de choses à l'écran.
Chaque fonction de MonochromeLib est bien plus rapide que son équivalent dans fxlib.h, et elle fournit de nombreuses fonctionnalités supplémentaires.
Comment l'utiliser
Pour utiliser la bibliothèque, copiez les 2 fichiers dans le dossier de votre projet, ajoutez MonochromeLib.c à votre projet (dans la fenêtre "Files in project" dans le SDK), ajoutez #include "MonochromeLib.h" au début de votre code.
Pour n'ajouter à votre projet que les fonctions dont vous avez besoin, chaque fonction est protégée par un #ifdef, et les #define de chaque fonction sont commentés par défaut.
Pour pouvoir utiliser une fonction, il suffit d'éditer MonochromeLib.h et de décommenter les #define des fonctions que vous voulez utiliser.
/!\ Important
Si vous rencontrez une erreur de compilation de ce type :
** L2310 (E) Undefined external symbol "_ML_pixel" referenced in "C:\...\CASIO\fx-9860G SDK\Projet\Debug\MonochromeLib.obj"
et que le #define de la fonction en question est bien actif dans MonochromeLib.h, alors il faut juste recompiler MonochromeLib.c
Pour cela, Utilisez la fonction Project > Rebuilt all dans le SDK. Si cela ne résoud pas le problème, supprimez le dossier Debug de votre projet, et recompilez normalement.
N'attendez plus !
Une documentation complète est maintenant fournie dans l'archive zip, en anglais et en français.
Questions récurrentes :
Problème : voici mon code, le compilateur ne veux pas le compiler :
unsigned char image[] = { ... };
ML_clear_vram();
ML_BMP_OR(image, 21, 42, 34, 34);
ML_clear_vram();
Solution : toutes les fonctions de MonochromeLib s'appellent en minuscule : les seules majuscules sont celles du "ML". Relisez la doc ou le
wiki, et regardez l'orthographe exacte de la fonction.
Version actuelle : 22 novembre 2011
Télécharger MonochromeLib
Citer : Posté le 19/01/2016 19:22 | # | Fichier joint
Hum... remplace ton fichier Monochrome.lib par celui que j'utilise (en PJ).
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 19/01/2016 19:23 | # | Fichier joint
Et le Header
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 19/01/2016 19:23 | #
le .c ?
Le header quelle est cette bête ?
Ajouté le 19/01/2016 à 19:25 :
Ca ne change rien
Un beat them all pour les CPC 19
Un jeu de Tank multijoueur en version graphique
Un jeu de boxe rigolo
Le moteur de combat épique d'un RPG
soccer physics : Un jeu de foot totalement wtf !
Survie 1 & 2 te laisseras-tu attraper par la méchante IA ?
Séquestrez les tous avec Catch'em all !
Joué à la calcultarice et pécher ? Facile !
Battle un système de combat dément !!
Débombe pas tout à fait un démineur
Mon mario pour le concours des 10 ans de PC
Casio jump un doodle jump pas comme les autres !
Rush four your life : tu cours ou tu meurs
Cookie clicker ! More cookies MOOORE !
Move et esquive : bouge pour esquiver les ennemis !
Guitar Hero !! Let's rock !
INVASION : Au secours on se fait envahir !
Un devine nombre entièrement customisable (mon 1er jeu)
Un outil pour dessiner des sprites en super drawstat et qui vous le compile pour vous donner un code utilisable dans vos programmes
Un super programme de dessin bourré de trucs funcs
Sortir une version finale de Tankasio
Bien m'améliorer en C parce que pour l'instant c'est pas jojo
Une ou plusieurs idées qui mûrissent petit à petit
Citer : Posté le 19/01/2016 19:25 | #
Ben c'est les .c et .h de Monochrome.lib , à inclure dans le projet (tu sais la petite fenêtre en long à gauche ).
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 19/01/2016 19:27 | #
C'est bon je venais de comprendre
Cela ne fonctionne toujours pas
set SHC_INC=C:\Users\jdc\Desktop\Calculatrice\SDK\OS\SH\include
set PATH=C:\Users\jdc\Desktop\Calculatrice\SDK\OS\SH\bin
set SHC_LIB=C:\Users\jdc\Desktop\Calculatrice\SDK\OS\SH\bin
set SHC_TMP=C:\Users\jdc\Documents\CASIO\fx-9860G SDK\Mes projets\Test lib\Debug
Executing Hitachi OptLinker04 phase
"C:\Users\jdc\Desktop\Calculatrice\SDK\OS\SH\bin\Optlnk.exe" -subcommand=C:\Users\jdc\AppData\Local\Temp\hmk26A5.tmp
** L2310 (E) Undefined external symbol "_ML_line" referenced in "C:\Users\jdc\Documents\CASIO\fx-9860G SDK\Mes projets\Test lib\Debug\TestLib.obj"
Optimizing Linkage Editor Abort
HMAKE MAKE UTILITY Ver. 1.1
Copyright (C) Hitachi Micro Systems Europe Ltd. 1998
Copyright (C) Hitachi Ltd. 1998
ERROR: Process failed with return code: 1
Build was not successful.
Un beat them all pour les CPC 19
Un jeu de Tank multijoueur en version graphique
Un jeu de boxe rigolo
Le moteur de combat épique d'un RPG
soccer physics : Un jeu de foot totalement wtf !
Survie 1 & 2 te laisseras-tu attraper par la méchante IA ?
Séquestrez les tous avec Catch'em all !
Joué à la calcultarice et pécher ? Facile !
Battle un système de combat dément !!
Débombe pas tout à fait un démineur
Mon mario pour le concours des 10 ans de PC
Casio jump un doodle jump pas comme les autres !
Rush four your life : tu cours ou tu meurs
Cookie clicker ! More cookies MOOORE !
Move et esquive : bouge pour esquiver les ennemis !
Guitar Hero !! Let's rock !
INVASION : Au secours on se fait envahir !
Un devine nombre entièrement customisable (mon 1er jeu)
Un outil pour dessiner des sprites en super drawstat et qui vous le compile pour vous donner un code utilisable dans vos programmes
Un super programme de dessin bourré de trucs funcs
Sortir une version finale de Tankasio
Bien m'améliorer en C parce que pour l'instant c'est pas jojo
Une ou plusieurs idées qui mûrissent petit à petit
Citer : Posté le 19/01/2016 19:34 | #
Tu dois avoir 2 fois le même nom de fonction ML_Line() dans tout ton code, cherche dans tout tes .c le doublon et supprime celui qui ne se trouve pas dans Monochrome.lib .
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 19/01/2016 19:37 | # | Fichier joint
Ba il est dans testlib.c mais je suppose que c'est normal puisque c'est mon programme
Sinon je n'ai que usefull.c en autre .c. Et il n'est pas dedans
(j'ai mis les sources en fichier joint si vous voulez tester de build)
Un beat them all pour les CPC 19
Un jeu de Tank multijoueur en version graphique
Un jeu de boxe rigolo
Le moteur de combat épique d'un RPG
soccer physics : Un jeu de foot totalement wtf !
Survie 1 & 2 te laisseras-tu attraper par la méchante IA ?
Séquestrez les tous avec Catch'em all !
Joué à la calcultarice et pécher ? Facile !
Battle un système de combat dément !!
Débombe pas tout à fait un démineur
Mon mario pour le concours des 10 ans de PC
Casio jump un doodle jump pas comme les autres !
Rush four your life : tu cours ou tu meurs
Cookie clicker ! More cookies MOOORE !
Move et esquive : bouge pour esquiver les ennemis !
Guitar Hero !! Let's rock !
INVASION : Au secours on se fait envahir !
Un devine nombre entièrement customisable (mon 1er jeu)
Un outil pour dessiner des sprites en super drawstat et qui vous le compile pour vous donner un code utilisable dans vos programmes
Un super programme de dessin bourré de trucs funcs
Sortir une version finale de Tankasio
Bien m'améliorer en C parce que pour l'instant c'est pas jojo
Une ou plusieurs idées qui mûrissent petit à petit
Citer : Posté le 19/01/2016 19:52 | #
Nan Mais ... Déjà t'as pas Ajouté les MonochromeLib.c et usefull.c au projet, je parle pas des includes , Genre dans la fenêtre à gauche du SDK, il y a "Sources Files", tu fais clic droit -> Add et tu sélectionnes tes fichiers .c
Ajouté le 19/01/2016 à 19:53 :
Et ensuite, tu as viré des trucs auquel fallait pas touché :boulet3: (c'est pas comme si c'était marqué en commentaire quoi...)
unsigned long BR_Size;
#pragma section
#pragma section _TOP
int InitializeSystem(int isAppli, unsigned short OptionNum)
{
return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}
#pragma section
Rajoutes ça à la fin du programme de TestLib.c .
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 19/01/2016 19:57 | #
AAAAAAAAAAAHHHHHHHHH !!!
Bah ça fonctionne mieux
Merci merci merci mille fois kirafi et Fife et désolé de vous avoir embêté pour un truc aussi idiot au final
Un beat them all pour les CPC 19
Un jeu de Tank multijoueur en version graphique
Un jeu de boxe rigolo
Le moteur de combat épique d'un RPG
soccer physics : Un jeu de foot totalement wtf !
Survie 1 & 2 te laisseras-tu attraper par la méchante IA ?
Séquestrez les tous avec Catch'em all !
Joué à la calcultarice et pécher ? Facile !
Battle un système de combat dément !!
Débombe pas tout à fait un démineur
Mon mario pour le concours des 10 ans de PC
Casio jump un doodle jump pas comme les autres !
Rush four your life : tu cours ou tu meurs
Cookie clicker ! More cookies MOOORE !
Move et esquive : bouge pour esquiver les ennemis !
Guitar Hero !! Let's rock !
INVASION : Au secours on se fait envahir !
Un devine nombre entièrement customisable (mon 1er jeu)
Un outil pour dessiner des sprites en super drawstat et qui vous le compile pour vous donner un code utilisable dans vos programmes
Un super programme de dessin bourré de trucs funcs
Sortir une version finale de Tankasio
Bien m'améliorer en C parce que pour l'instant c'est pas jojo
Une ou plusieurs idées qui mûrissent petit à petit
Citer : Posté le 19/01/2016 19:57 | #
Vous réglez un petit problème en messages qui se serait réglé en 2 minutes sur TS / Teamviewer / Skype, j'ai déjà eu à faire avec ce genre de soucis et c'est bien chiant d'en trouver la source x)
Citer : Posté le 07/08/2016 23:42 | #
Comment implémenter une fonction qui ne clear la vram que dans un rectangle ? (similaire à BDisp_AreaClearDDVRAM())
int i, end, *pointer_long, vram;
char *pointer_byte;
vram = (int)ML_vram_adress();
end = 4-vram&3;
pointer_byte = (char*)vram;
for(i=0 ; i<end ; i++) pointer_byte[i] = 0;
pointer_long = (int*) (vram+end);
for(i=0 ; i<255 ; i++) pointer_long[i] = 0;
pointer_byte += 1020+end;
end = vram&3;
for(i=0 ; i<end ; i++) pointer_byte[i] = 0;
}
void ML_clear_area_vram(int x1, int y1, int x2, int y2) {
//?
}
Je vois pas du tout comment faire parce que je comprends rien à ce qui se passe (quelle signification a la valeur de end, pourquoi il fait 3 boucles for au lieu d'une ?)
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 07/08/2016 23:53 | #
En fait, faut voir ML_clear_vram comme un memset(<vram>, 0, 1024);.
La VRAM, c'est facile à manipuler, puisque ce sont des octets pleinement utilisés, y a pas de questions de fill bits, pas de coordonnées de l'utilisateur à prendre en compte, etc.
Un rectangle, c'est déjà moins évident, à cause du point central : est-ce que la coordonnée horizontale tombe en plein milieu d'un octet ? Est-ce que cette coordonnée plus la longueur du rectangle tombe également en plein milieu ?
Un exemple d'implémentation (pas testé, sans aucun doute optimisable), où tout est supposé valide :
{
// premiers bytes en travers
while (w >= 8 ) {
*vram &= ~(255 >> offset);
*++vram &= ~(255 << (8 - offset));
w -= 8;
}
// dernier byte non entier (voire nul)
int byte = ~(255 << w); // le tout bitwise and 255 (mais normalement y a pas besoin)
*vram &= ~(byte >> offset);
*++vram &= ~(byte << (8 - offset));
}
void clear_rectangle(int x, int y, int w, int h)
{
unsigned char *vram = ML_vram_address();
// on avance au premier octet qui nous intéresse
vram += y * 16 + x / 8;
// pour chaque ligne
while (h--) {
clear_rectangle_line(vram, w, x % 8 );
vram += 16; // ligne suivante
}
}
Mon blog ⋅ Mes autres projets
Citer : Posté le 08/08/2016 08:02 | #
Pour répondre à la question de Zezombye (ce que Cake n'a pas fait x)), il y en fait un os dans la technique de manipulation de la VRAM. Le principe est pourtant simple : plus on écrit de bits à la fois et plus ça va vite. On veut donc utiliser des int, comme la boucle du milieu : ça fait 32 pixels écrits par opération
Seulement voilà, pour écrire 4 octets il faut une adresse multiple de 4 (principe inhérent à de très nombreux processeurs aujourd'hui). Et la VRAM du système n'est pas alignée sur une adresse multiple de 4. Elle se termine par 0xd de mémoire. Du coup elle n'est pas non plus alignée sur une adresse multiple de 2 octets.
Qu'à cela ne tienne : on voit bien que si on écrit les premiers octets on va rapidement atteindre une adresse multiple de 4. C'est ce qu'il fait : la première boucle traite au plus trois octets et les écrit un par un. Ensuite on atteint une adresse multiple de 4, donc il utilise un pointeur en int * et il écrit les octets 4 par 4 (dans le même temps processeur !). Là c'est la partie où la vitesse est élevée ! Enfin, il y a quelques octets à la fin qui restent, donc il les écrit à la main, un par un, dans la dernière boucle.
Note au passage que privilégier les opérations sur 32 bits est la première optimisation à surveiller quand on manipule le dessin : c'est celle qui se montre généralement la plus efficace.
Pour le coup du rectangle, j'ai trouvé une méthode simple pour gérer ça dans gint. Le principe est de dire qu'un rectangle, c'est un certain nombre de fois la même ligne. Du coup si on arrive à décrire correctement une ligne, on est bons. Il y a 16 octets de VRAM par ligne, on peut donc écrire une fonction qui prend deux paramètres (x1, x2) et qui nous renvoie 16 char dans lequel le rectangle est représenté par des bits à 1.
Par exemple (ici avec 2 char, pour faire court. J'ai inclus les deux points) :
>> [ 0000 0111, 1111 1100 ]
Le code est le suivant (adapté depuis celui de gint où on utilisait 4 int, il peut rester des erreurs) :
{
int l1 = x1 >> 3;
int l2 = x2 >> 3;
int i = 0;
while(i < l1) masks[i++] = 0x00;
while(i <= l2) masks[i++] = 0xff;
while(i < 16) masks[i++] = 0x00;
x1 &= 7;
x2 = ~x2 & 7;
masks[l1] &= (0xff >> x1);
masks[l2] &= (0xff << x2);
}
Le reste est assez trivial, il suffit d'itérer sur la mémoire et d'appliquer un ET logique entre chaque ligne de VRAM et notre ligne de masques :
{
uint8_t masks[16];
getMasks(x1, x2, masks);
int begin = y1 << 4; // Offset of line 'y1'
int end = (y2 + 1) << 4; // Offset of line 'y2' + 1
for(int i = begin; i < end; i++) vram[i] &= ~masks[i & 15];
}
Je crois que j'ai tout dit. Gint le fait sur des int donc typiquement ce serait 4 fois plus rapide.
Citer : Posté le 25/12/2019 02:29 | #
Bonsoir, comme j'ai fait une installation toute fraîche pour prog sur Linux j'ai essayé de refaire marcher MonochromeLib avec fxlib. Par défaut le code compile (si on remplace #include <stdlib.h> par #include <fxlib.h>) mais ne s'exécute pas correctement sur la calculette. J'avais déjà rencontré le problème mais grâce à ElDarkPhoenix on a corrigé le problème. Comme je me suis repenché sur le problème en cette soirée j'en ai profité pour faire un relooking au code qui gère les syscalls... de plus ça permet aux optimisations de gcc de fonctionner.
Je passe de ça :
static int (*SysCall)( int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallCode;
char* ML_vram_adress()
{
return (char*)((*SysCall)(0, 0, 0, 0, 309));
}
à ça :
char *(*SysCall)(int, int, int, int, int) = (volatile void *)&SysCallCode;
char *ML_vram_adress() { return SysCall(0, 0, 0, 0, 309); }
J'ai enlevé les static car j'ai l'impression que ça sert à rien dans ce cas et j'ai changé les types de retour pour éviter les cast non obligatoires... Le mot-clé volatile je l'ai posé un peu au pif mais sans lui les optimisations de gcc passent pas
J'utilise toujours fxlib car sa fonction de rafraîchissement d'écran est compatible avec le mode projecteur de la casio (p7screen) J'ai pas vu de fonction qui peut faire ça avec gint.
Citer : Posté le 25/12/2019 08:32 | #
Merci pour l'info ! Le changement que tu as fait ressemble pas mal à la façon d'appeler les syscalls sur SH4. L'ancienne méthode d'appels de syscalls en C ne marchait pas sur SH4 pour je ne sais quelle raison (et le fait que le compilo soit là, bon...).
Tu as certainement aussi mis du volatile dans ML_display_vram() sur les registres de l'écran, c'était nécessaire la dernière fois que j'ai compilé ML avec GCC avec optis.
En effet, gint ne supporte pas le projecteur, et je doute qu'il le fasse dans le futur.
Citer : Posté le 25/12/2019 11:44 | #
Bon ça me rassure que tu valides mon bout de code... Je n'ai pas touché à ML_display_vram() car je ne l'utilise pas... D'après mes souvenirs elle ne supporte pas non plus le mode projecteur.
Citer : Posté le 25/12/2019 11:46 | #
Yup c'est le cas, le protocole du projecteur intervient dans une sous-fonctions appelée à la fin de Bdisp_PutDisp_DD(), j'ai désassemblé dans ce coin-là une fois.
Citer : Posté le 27/12/2019 04:37 | #
Juste pour info, l'ancienne façon d'appeler du code ne marche plus parce qu'il vient copier SysCallCode dans une zone non executable de la mémoire et ça plante quand on jump dessus (et cette zone était executable en SH3). Alors que si tu mets en const, il va jumper directement dans la mémoire où le programme est stocké puisque c'est une constante, pas besoin de copier le tableau.
C'était un des fix de SH4CompatibilityTool : https://gitea.planet-casio.com/Ziqumu/SH4compatibilityTool/src/branch/master/DOCUMENTATION.md#monochromelib-and-syscall-call-method
Citer : Posté le 27/12/2019 08:21 | #
Ah right, le coup de la RAM virtualisée non exécutable. C'est ce qu'on gagne à vouloir coder ça en C... x)
Citer : Posté le 16/08/2020 20:49 | #
aucune des solutions ne marche dans mon cas
Citer : Posté le 16/08/2020 20:53 | #
Pour appeler des syscalls ? Il y a probablement une arnaque quelque part, les méthodes en question sont utilisées en prod actuellement sur à peu près tout les modèles.