Table of Contents
- MonochromeLib
- Qu'est-ce que c'est ?
- Fonctions
- ML_vram_adress
- ML_clear_vram
- ML_clear_screen
- ML_display_vram
- ML_set_contrast
- ML_get_contrast
- ML_pixel
- ML_point
- ML_pixel_test
- ML_line
- ML_horizontal_line
- ML_vertical_line
- ML_rectangle
- ML_polygon
- ML_filled_polygon
- ML_circle
- ML_filled_circle
- ML_ellipse
- ML_ellipse_in_rect
- ML_filled_ellipse
- ML_filled_ellipse_in_rect
- ML_horizontal_scroll
- ML_vertical_scroll
- ML_bmp...
- Constantes
- Tutoriels
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.
Fonctions
ML_vram_adress
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.
Voir aussi: La VRAM, Double buffering, ML_display_vram
ML_clear_vram
void ML_clear_vram();
Efface la VRAM.
Cette fonction est 5 fois plus rapide que Bdisp_AllClr_VRAM
.
Voir aussi: La VRAM, ML_clear_screen, ML_display_vram
ML_clear_screen
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
.
Voir aussi: ML_clear_vram, ML_display_vram
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
.
Voir aussi: La VRAM, ML_clear_vram, ML_clear_screen
ML_set_contrast
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
.
Voir aussi: ML_CONTRAST, ML_get_contrast
ML_get_contrast
unsigned char ML_get_contrast();
Retourne la valeur actuelle du contraste.
Voir aussi: ML_CONTRAST, ML_set_contrast
ML_pixel
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 (0, 0), et le pixel en bas à droite (127, 63).
Voir aussi: ML_Color, ML_pixel_test
ML_point
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és (en pixels) est définie par width.
Exemple:
ML_point(10, 10, 3, ML_BLACK);
dessinera un rectangle noir allant de (9, 9) à (11, 11).
Voir aussi: ML_Color, ML_pixel, ML_rectangle
ML_pixel_test
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
.
Voir aussi: ML_Color, ML_pixel
ML_line
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.
Voir aussi: ML_Color, ML_horizontal_line, ML_vertical_line
ML_horizontal_line
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.
ML_vertical_line
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.
ML_rectangle
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.
Voir aussi: ML_Color, ML_point
ML_polygon
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();
Et voilà un "joli" pentagone au milieu de l'écran.
Voir aussi: ML_Color, ML_filled_polygon, ML_line
ML_filled_polygon
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 polygone plein.
Voir aussi: ML_Color, ML_polygon
ML_circle
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.
Voir aussi: ML_Color, ML_filled_circle
ML_filled_circle
void ML_filled_circle(int x, int y, int radius, ML_Color color);
Similaire à ML_circle
, mais dessine un cercle plein.
Voir aussi: ML_Color, ML_circle
ML_ellipse
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.
Voir aussi: ML_Color, ML_ellipse_in_rect, ML_filled_ellipse
ML_ellipse_in_rect
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.
Voir aussi: ML_Color, ML_ellipse, ML_filled_ellipse_in_rect
ML_filled_ellipse
void ML_filled_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
Similaire à ML_ellipse
, mais dessine une ellipse pleine.
Voir aussi: ML_Color, ML_ellipse, ML_filled_ellipse_in_rect
ML_filled_ellipse_in_rect
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.
Voir aussi: ML_Color, ML_ellipse_in_rect, ML_filled_ellipse
ML_horizontal_scroll
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.
Voir aussi: ML_vertical_scroll
ML_vertical_scroll
void ML_vertical_scroll(int scroll);
Similaire à ML_horizontal_scroll
, mais effectue le décalage verticalement.
Voir aussi: ML_horizontal_scroll
ML_bmp...
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 88.
Les fonction avec le préfixe ML_bmp_16
servent à dessiner des bitmaps de dimensions 1616.
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.
Voir aussi: Bitmap
Constantes
ML_Color
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_TRANSPARENT
= -1ML_WHITE
= 0ML_BLACK
= 1ML_XOR
= 2ML_CHECKER
= 3
ML_XOR
permet d'inverser la couleur déjà présente dans la VRAM.
ML_CHECKER
est une couleur "damier". Elle rend 1 pixel sur 2 blanc, et l'autre noir, selon la rêgle suivante : si (x et y sont pair) ou (x et y sont impairs), alors le pixel devient noir, sinon il devient blanc.
Exemple:
ML_rectangle(50, 20, 80, 40, 2, ML_BLACK, ML_CHECKER);
ML_SCREEN_WIDTH et ML_SCREEN_HEIGHT
Ces constantes définissent la taille de l'écran pour laquelle MonochromeLib est faite pour fonctionner.
ML_SCREEN_WIDTH
= 128ML_SCREEN_HEIGHT
= 64
Ces constantes ne sont pas utilisées par la librairie, et leur modification n'affectera en rien son fonctionnement. MonochromeLib n'est pas conçue pour fonctionner avec un écran d'une autre dimension.
Voir aussi: ML_vram_adress
ML_CONTRAST_MIN, ML_CONTRAST_NORMAL et ML_CONTRAST_MAX
Ces constantes définissent les valeurs de contraste minimum et maximum acceptées par une Graph 85.
ML_CONTRAST_MIN
= 130ML_CONTRAST_NORMAL
= 168ML_CONTRAST_MAX
= 190
Voir aussi: ML_set_contrast, ML_get_contrast
Tutoriels
La VRAM
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 |
La case "0" est le premier octet de la VRAM, la case "1023" le dernier octet.
Exemple de manipulation :
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.
Voir aussi: ML_vram_adress, Double buffering
Double buffering
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
.
Voir aussi: ML_clear_vram, ML_display_vram
Bitmap
Un bitmap est un tableau de donnée dans lequel un bit représente un pixel.
Créer un bitmap 8*8
Un pixel étant soit noir soit blanc, on peut stocker son état dans un bit (0 ou 1). Un octet contient 8 bits, on peut donc y stocker 8 pixels. Pour un bitmap 8*8, chaque ligne va tenir dans un octet, on va donc avoir 8 octets, un par ligne.
Prenons un exemple, l'image d'une balle :
00111100 -> 60
01111110 -> 126
11111011 -> 251
11111101 -> 253
11111101 -> 253
11111111 -> 255
01111110 -> 126
00111100 -> 60
Ici, j'ai pris les nombres binaires correspondant à chaque ligne de l'image, et je les ai converti en décimal.
Nous obtenons donc le tableau suivant :
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.
Créer un bitmap de n'importe quelle taille
Maintenant que l'on sait comment sont codés les bitmaps 8*8, il va être simple de comprendre la gestion des autres dimensions.
Pour un bitmap 16*16, nous avons 16 bits par ligne, soit 2 octets.
2 octets par ligne multiplié par 16 lignes, nous donne 32 octets pour un bitmap 16*16. Les 2 premiers sont la première ligne, les 2 suivant, la seconde ligne, etc.
Pour un bitmap de largeur intérieure à 8, chaque ligne va tout de même prendre 1 octet. Les derniers bits de chaque octets seront simplement inutilisés.
Pour un bitmap d'une largeur supérieure à 8, mais non multiple de 8, ce sera pareil, les derniers bits du dernier octets de chaque ligne seront inutilisés.
Les fonctions ML_bmp appliquent un masque sur ces derniers bits pour qu'ils soient inactifs, quelque soit leur contenu. Ainsi, si je prends le bitmap balle créé précédemment, et que je le dessine de la manière suivante :
ML_bmp_or(balle, x, y, 4, 8);
Seule la moitié de gauche sera dessinée.
Les différents modes de dessin: OR, AND, XOR
Prenons comme exemple le bitmap de la balle créé précédemment, et dessinons-le des 3 manières différentes sur fond noir et blanc :
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);
Les fonctions ML_bmp_or
font un OR binaire entre les pixels de l'écran, et ceux du bitmap.
Pour rappel :
- 0 OR 0 = 0
- 0 OR 1 = 1
- 1 OR 0 = 1
- 1 OR 1 = 1
Donc l'application d'un bitmap en OR va copier les pixels noirs du bitmap et laisser les autres comme "transparent".
Le mode AND va copier uniquement les pixels blancs du bitmap.
Avec le mode XOR, les pixels noirs du bitmap vont inverser la couleur des pixels de l'écran, et les pixels blancs du bitmap seront sans effet.
Pour copier complètement le bitmap à l'écran sans transparence, il faut donc l'appliquer en AND puis en OR.
Si vous avez un sprite avec des pixels noirs, blancs, et transparents, il faut 2 bitmaps. Un premier contenant des 0 aux pixels blancs à appliquer en AND, et un second contenant des 1 aux pixels noirs à appliquer en OR. Les pixels à 1 dans le premier bitmap et à 0 dans le second, seront transparents.
Si vous voulez que les pixels noirs du bitmap soient copiés en blanc sur l'écran, il faut appliquer le bitmap en OR puis en XOR.
Bref, avez ces 3 modes de dessin, toutes les combinaisons sont possibles.
Logiciels d'encodage de bitmap
Il existe de nombreux logiciels pour encoder les bitmaps dans ce format.
- Tile Creator
- Sprite Maker (conçu pour Graph 100, mais est l'encodage est le même)
- Find_Sprites_In_Bitmap, un petit programme de ma conception.
Vous pouvez également faire le vôtre ! Ce n'est pas très compliqué, vous savez programmer en C, et vous connaissez maintenant l'encodage des bitmaps.
Voir aussi: ML_bmp...