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.
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.
char* ML_vram_adress();
Retourne l'adresse de la VRAM (celle ci est différente sur l'OS 1, l'OS 2, et l'émulateur).
La VRAM est la mémoire vidéo, un espace mémoire de 1024 octets conçue pour recevoir les dessins avant d'être affichée à l'écran, selon le principe du double-buffering.
Cette fonction n'est pas forcément utile pour une utilisation classique de MonochromeLib, mais elle est utile à toutes les fonctions de la bibliothèque.
void ML_clear_vram();
Efface la VRAM.
Cette fonction est 5 fois plus rapide que Bdisp_AllClr_VRAM.
void ML_clear_screen();
Efface l'écran.
Cette fonction est 2 fois plus rapide que Bdisp_AllClr_DD.
Remarque : Il est inutile d'appeler ML_clear_screen juste avant ML_display_vram.
void ML_display_vram();
Copie le contenu de la VRAM à l'écran.
Cette fonction est 2 fois plus rapide que Bdisp_PutDisp_DD.
Remarque : Il est inutile d'appeler ML_clear_screen juste avant ML_display_vram.
void ML_set_contrast(unsigned char contrast);
Permet de définir la valeur du contraste.
Celle ci doit être comprise entre ML_CONTRAST_MIN et ML_CONTRAST_MAX.
unsigned char ML_get_contrast();
Retourne la valeur actuelle du contraste.
void ML_pixel(int x, int y, ML_Color color);
Permet de définir la couleur d'un pixel de la VRAM.
Le pixel en haut à gauche de l'écran a pour coordonnées (x=0, y=0), et le pixel en bas à droite (x=127, y=63).
void ML_point(int x, int y, int width, ML_Color color);
Dessine un point (carré) dans la VRAM, de centre (x, y), dont la longueur des coté (en pixel) est définie par width.
Exemple:
ML_point(10, 10, 3, ML_BLACK);
dessinera un rectangle noir allant de (9, 9) à (11, 11).ML_Color ML_pixel_test(int x, int y);
Retourne la couleur du pixel aux coordonnées (x, y), ML_BLACK ou ML_WHITE.
Si les coordonnées sont en dehors de l'écran, la fonction retourne ML_TRANSPARENT.
void ML_line(int x1, int y1, int x2, int y2, ML_Color color);
Trace une ligne entre les pixels de coordonnées (x1, y1) et (x2, y2) en utilisant l'algorithme de Bresenham.
void ML_horizontal_line(int y, int x1, int x2, ML_Color color);
Dessine une ligne horizontale.
Cette fonction est plus rapide qu'un appel à ML_line avec y1==y2.
void ML_vertical_line(int x, int y1, int y2, ML_Color color);
Dessine une ligne verticale.
Cette fonction est plus rapide qu'un appel à ML_line avec x1==x2.
void ML_rectangle(int x1, int y1, int x2, int y2, int border_width, ML_Color border_color, ML_Color fill_color);
Dessine un rectangle avec ou sans bordure.
Vous pouvez définir la couleur de la bordure et du remplissage du rectangle.
Si vous ne voulez pas de bordure, définissez border_width à 0.
void ML_polygon(const int *x, const int *y, int nb_vertices, ML_Color color);
Dessine un polygone.
Cette fonction demande en paramètre deux tableaux d'entiers, le premier contenant les abscisses des sommets du polygone, et le second contenant les ordonnées. Le paramètre nb_vertices doit être le nombre de sommets du polygone (le nombre de valeurs à lire dans les tableaux x et y).
Ensuite, la fonction trace des lignes entre ces sommets pour dessiner le polygone.
Exemple :
int abscisses[] = {60, 75, 70, 50, 45};
int ordonnees[] = {20, 30, 45, 45, 30};
ML_clear_vram();
ML_polygon(abscisses, ordonnees, 5, ML_BLACK);
ML_display_vram();
void ML_filled_polygon(const int *x, const int *y, int nb_vertices, ML_Color color);
Demande les mêmes paramètres que ML_polygon, mais dessine un polygon plein.
void ML_circle(int x, int y, int radius, ML_Color color);
Trace un cercle de centre (x, y) et de rayon radius en utilisant l'algorithme de Bresenham.
void ML_filled_circle(int x, int y, int radius, ML_Color color);
Similaire à ML_circle, mais dessine un cercle plein.
void ML_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
Trace une ellipse de centre (x, y) et de rayons radius1 et radius2. radius1 est la distance entre le centre et les points les plus à gauche et à droite de l'ellipse. radius2 est la distance entre le centre et les points les plus haut et bas de l'ellipse. Utilise l'algorithme de Bresenham.
void ML_ellipse_in_rect(int x1, int y1, int x2, int y2, ML_Color color);
Cette fonction appelle ML_ellipse. Elle demande les coordonnées d'un rectangle, et trace l'ellipse inscrite dans ce rectangle.
void ML_filled_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
Similaire à ML_ellipse, mais dessine une ellipse pleine.
void ML_filled_ellipse_in_rect(int x, int y, int radius1, int radius2, ML_Color color);
Similaire à ML_ellipse_in_rect, mais dessine une ellipse pleine.
void ML_horizontal_scroll(int scroll);
Permet de décaler tous les pixels de la VRAM vers la gauche ou la droite. Par exemple, si scroll=5, alors un pixel situé en (2, 3) sera déplacé en (7, 3). Si scroll est négatif, les pixels seront déplacés vers la gauche. Les pixels qui sortent de l'écran sont replacés de l'autre cotés.
void ML_vertical_scroll(int scroll);
Similaire à ML_horizontal_scroll, mais effectue le décalage verticalement.
void ML_bmp_or(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_and(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_xor(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_and_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_xor_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_8_or(const unsigned char *bmp, int x, int y);
void ML_bmp_8_and(const unsigned char *bmp, int x, int y);
void ML_bmp_8_xor(const unsigned char *bmp, int x, int y);
void ML_bmp_8_or_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_8_and_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_8_xor_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_16_or(const unsigned short *bmp, int x, int y);
void ML_bmp_16_and(const unsigned short *bmp, int x, int y);
void ML_bmp_16_xor(const unsigned short *bmp, int x, int y);
void ML_bmp_16_or_cl(const unsigned short *bmp, int x, int y);
void ML_bmp_16_and_cl(const unsigned short *bmp, int x, int y);
void ML_bmp_16_xor_cl(const unsigned short *bmp, int x, int y);
Toutes ces fonctions servent à dessiner des images au format de bitmap monochrome. Elles sont très utiles pour dessiner les tiles ou sprites des jeux.
Les fonction avec le préfixe ML_bmp_8 servent à dessiner des bitmaps de dimensions 8*8.
Les fonction avec le préfixe ML_bmp_16 servent à dessiner des bitmaps de dimensions 16*16.
Les autres demandent les dimensions du bitmap dans les paramètres width et height
Les fonction avec le suffixe _cl sont les fonctions avec clipping. C'est à dire qu'elle sont capables de dessiner un bitmap même s'il n'est pas totalement dans l'écran.
Les autres n'affiche le bitmap que s'il est entièrement dans l'écran. De ce fait, elles sont un petit peu plus rapides.
typedef enum {ML_TRANSPARENT=-1, ML_WHITE, ML_BLACK, ML_XOR, ML_CHECKER} ML_Color;
ML_Color est une énumération des différentes couleurs utilisables avec MonochromeLib.
Seul ML_TRANSPARENT a une valeur définie à -1, le compilateur donne donc aux autres les valeurs suivantes :
ML_rectangle(50, 20, 80, 40, 2, ML_BLACK, ML_CHECKER);
Ces constantes définissent la taille de l'écran pour laquelle MonochromeLib est faite pour fonctionner.
Ces constantes définissent les valeurs de contraste minimum et maximum acceptées par une Graph 85.
La VRAM (abréviation de Vidéo RAM) est une mémoire vidéo créée par le système d'exploitation.
Elle permet de mettre en oeuvre la technique du double-buffering.
L'écran de la Graph 85 fait 128*64 pixels, soit 8192. C'est un écran monochrome, ce qui signifie que chaque pixel a 2 états possibles, allumé ou éteint (noir ou blanc).
On peut donc stocker l'état d'un pixel en mémoire dans un bit (0 ou 1). Comme un octet contient 8 bits, on peut stocker l'état de l'ensemble des pixels de l'écran dans 1024 octets (8192/8 = 1024).
La VRAM est en effet un espace mémoire de 1024 octets.
Il existe une fonction du système d'exploitation (un syscall) qui permet de connaître l'adresse de la VRAM dans la mémoire. Une fois que l'on a cette adresse, on peut accéder à la VRAM en lecture et en écriture, pour y faire des dessins, ou analyser son contenu. C'est cette fonction qui est appelée par ML_vram_adress.
Au début de la programmation sur Graph 85, cette fonction n'était pas connue, mais nous connaissions l'adresse de la VRAM : 0x8800498D. Mais cette adresse a été modifée dans la version 2 du système d'exploitation, rendant plusieurs programmes inopérants. L'utilisation de ce syscall est donc nécessaire pour garantir le fonctionnement du programme sur toutes les versions du système d'exploitation.
La VRAM est organisée de la manière suivante :
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
... | |||||||||||||||
1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 |
memset(ML_vram_adress(), 255, 1024);
Cette ligne va copier la valeur 255 dans les 1024 octets de la VRAM. 255 en binaire s'écrit 11111111, que des 1. Cette instruction sert donc à remplir la VRAM de noir. Il suffit ensuite d'appeler ML_display_vram et l'écran sera tout noir.
La technique du double-buffering consiste à faire les dessins dans une mémoire vidéo (VRAM) avant de copier celle-ci sur l'écran réel. Cela permet de ne pas afficher une image "en construction" et évite le scintillement de l'écran.
Il faut commencer par effacer le contenu de la VRAM avec ML_clear_vram, puis faire les dessins, et enfin afficher le contenu de la VRAM à l'écran avec ML_display_vram.
Un bitmap est un tableau de donnée dans lequel un bit représente un pixel.
00111100 -> 60
01111110 -> 126
11111011 -> 251
11111101 -> 253
11111101 -> 253
11111111 -> 255
01111110 -> 126
00111100 -> 60
char balle[] = {60, 126, 251, 253, 253, 255, 126, 60};
Ce tableau est un bitmap 8*8 que l'on peut envoyer aux fonctions ML_bmp pour le dessiner.ML_bmp_or(balle, x, y, 4, 8);
Seule la moitié de gauche sera dessinée.
char balle[] = {60, 126, 251, 253, 253, 255, 126, 60};
ML_rectangle(1, 1, 12, 32, 0, ML_TRANSPARENT, ML_BLACK); //dessin du fond noir
//dessin sur fond noir
ML_bmp_8_or(balle, 3, 3);
ML_bmp_8_and(balle, 3, 13);
ML_bmp_8_xor(balle, 3, 23);
//dessin sur fond blanc
ML_bmp_8_or(balle, 15, 3);
ML_bmp_8_and(balle, 15, 13);
ML_bmp_8_xor(balle, 15, 23);