Documentation

HAUT

Documentation de la bibliothèque memory 3.0

Présentation de memory

Pourquoi memory ?

La bibliothèque memory a été créée pour pallier à la difficulté d'utilisation de Bfile. Cette dernière, partie intégrante de fxlib, ne permettait pas de manipuler simplement la mémoire et empêchait donc les programmeurs moins avancés de créer des systèmes complets. Or, l'utilisation de la mémoire de la calculatrice est indispensable à tout système de sauvegarde, donc à de nombreux jeux.

Les avantages de memory

memory est basée sur Bfile, mais est à un plus haut niveau. Elle permet de simplifier l'utilisation de la mémoire et possède entre autres les caractéristiques suivantes :

Utilisation de memory

Comme toutes les bibliothèques C, memory est constituée d'un ensemble de fonctions. Les noms de celles-ci sont basés sur un modèle simple: le préfixe memory suivi du nom de la fonction, pour éviter un conflit entre une fonction de la bibliothèque et une fonction du programme.
Pour utiliser une telle fonction, il sufit comme pour toute fonction d'écrire son nom suivi de parenthèses entre lesquelles seront placés les paramères, sans oublier le point-virgule à la fin de l'instruction. Mais avant cela, il faut penser à deux choses :

Liste des fonctions

Fonctions fondamentales

int memory_createfile(char *adresse, int size);// Prototype
int x = memory_createfile("\\\\fls0\\FICHIER",20);//   Exemple
DESCRIPTION Crée un fichier à l'adresse adresse et de size octets.
RETOUR Retourne un code d'erreur standard.
DEPENDANCES Bfile_OpenFile(), memory_char2font()
int memory_createdir(char *adresse);// Prototype
int x = memory_createdir("\\\\crd0\\MYGAME");//   Exemple
DESCRIPTION Crée le répertoire à l'adresse adresse.
RETOUR Retourne un code d'erreur standard.
DEPENDANCES Bfile_CreateDirectory(), memory_char2font()
int memory_openfile(char *adresse, int mode);// Prototype
int handle = memory_openfile("\\\\fls0\\MYGAME.SAV",_OPENMODE_READ);//   Exemple
DESCRIPTION Ouvre le fichier à l'adresse adresse dans le mode mode et en renvoie le handle.
RETOUR Retourne le handle de gestion du fichier si l'ouverture a réussi, ou un code d'erreur standard sinon.
DEPENDANCES Bfile_OpenFile(), memory_char2font()
NOTA BENE Seuls quatre fichiers peuvent être ouverts à la fois. Au cinquième, vous aurez un code d'erreur de valeur -7.
L'utilisation des variables _OPENMODE_READ et affiliées nécessite l'inclusion de fxlib.h.
int memory_closefile(int handle);// Prototype
int x = memory_closefile(handle);//   Exemple
DESCRIPTION Ferme le fichier géré par la variable handle.
RETOUR Retourne un code d'erreur standard.
DEPENDANCES Bfile_CloseFile(), memory_char2font()
int memory_writefile(int handle, char *data, int length);// Prototype
int x = memory_writefile(handle,"Texte quelconque",17);//   Exemple
DESCRIPTION Écrit dans le fichier géré par la variable handle les données au pointeur data sur une longueur de length octets.
RETOUR Retourne un code d'erreur standard.
DEPENDANCES Bfile_WriteFile(), memory_char2font()
NOTA BENE N'oubliez pas qu'une chaîne de caractères comporte un caractère NULL à sa fin, ce qui augmente sa taille d'un octet.
int memory_readfile(int handle, void *buffer, int size, int pos);// Prototype
int x = memory_readfile(handle,buffer,20,-1);//   Exemple
DESCRIPTION Lit le fichier géré par la variable handle depuis la position en octets pos. Si cette dernière est égale à -1, la lecture reprend là où elle s'était arrêtée la fois précédente, ou au début du fichier s'il vient d'être ouvert. Les size octets lus seront placé à l'adresse buffer.
RETOUR Retourne un code d'erreur standard.
DEPENDANCES Bfile_ReadFile(), memory_char2font()
NOTA BENE Attention à disposer d'assez de mémoire allouée à l'adresse buffer.
int memory_seekfile(int handle, int offset);// Prototype
int x = memory_seekfile(handle,-10);//   Exemple
DESCRIPTION Déplace le curseur virtuel du fichier géré par la variable handle de offset octets. Si offset est négatif, le curseur remonte vers le début du fichier.
RETOUR Retourne le nombre d'octets pouvant être lus d'un coup depuis la nouvelle position si la manipulation réussit, un code d'erreur standard sinon.
DEPENDANCES Bfile_SeekFile(), memory_char2font()
int memory_filesize(int handle);// Prototype
int size = memory_filesize(handle);//   Exemple
DESCRIPTION Renvoie la taille en octets du fichier géré par la variable handle.
RETOUR Retourne la taille du fichier si l'opération réussi, ou un code d'erreur standard sinon.
DEPENDANCES Bfile_GetFileSize(), memory_char2font()
int memory_deletefile(char *adresse);// Prototype
int x = memory_deletefile("\\\\fls0\\RECORDS.SAV");//   Exemple
DESCRIPTION Supprime le fichier à l'adresse adresse.
RETOUR Retourne un code d'erreur standard.
DEPENDANCES Bfile_DeleteFile(), memory_char2font()

Fonctions ajoutées

char **memory_alloc(int l);// Prototype
char **files = memory_alloc(20);//   Exemple
DESCRIPTION Alloue de la mémoire pour une recherche de l fichiers.
RETOUR Retourne le pointeur sur la mémoire allouée.
DEPENDANCES malloc()
NOTA BENE Le nombre de fichiers trouvé par la recherche ne pourra être supérieur au nombre de fichiers alloué.
void memory_free(char **files, int l);// Prototype
memory_free(files);//   Exemple
DESCRIPTION Libère un pointeur alloué pour la recherche de l fichiers.
RETOUR Ne retourne rien.
DEPENDANCES free()
int memory_find(char *adresse, char **files, int l);// Prototype
int n = memory_find("\\\\crd0\\*.SAV", files, 20); //   Exemple
DESCRIPTION Effectue une recherche de fichier correspondant au motif adresse. Les noms des fichiers trouvé seront placés au pointeur files alloué par memory_alloc(), dans la limite de l éléments.
RETOUR Retourne le nombre de fichiers trouvés.
DEPENDANCES memory_char2font(), Bfile_FindFirst(), Bfile_FindNext(), Bfile_FindClose()
NOTA BENE La valeur l doit impérativement être inférieure ou égale à celle utilisée pour allouer le pointeur files.
VOIR AUSSI Les motifs de recherche
int memory_exists(char *adresse);// Prototype
if(memory_exists("\\\\fls0\\RECORDS.SAV")) memory_deletefile("\\\\fls0\\RECORDS.SAV"); //   Exemple
DESCRIPTION Indique si le fichier à l'adresse adresse existe.
RETOUR Retourn 1 si le fichier existe, 0 sinon.
DEPENDANCES memory_find()
void *memory_load(char *adresse);// Prototype
void *data = memory_load("\\\\crd0\\FOLDER\\RESULTS.SAV");//   Exemple
DESCRIPTION Charge le fichier de la mémoire à l'adresse adresse.
RETOUR Retourne un pointeur sur les données allouées et chargées si l'opération a réussi, NULL sinon.
DEPENDANCES memory_char2font(), calloc(), Bfile_OpenFile(), Bfile_GetFileSize(), Bfile_CloseFile()
NOTA BENE N'oubliez pas de libérer le pointeur avec free() après utilisation pour éviter les fuites de mémoire.
int memory_save(char *adresse, void *data, int l);// Prototype
int x = memory_save("\\\\fls0\\MYGAME.SAV",saveData,48);//   Exemple
DESCRIPTION Sauvegarde les données du pointeur data sur une longueur de l octets dans le fichier à l'adresse adresse.
RETOUR Retourne 0 si l'opération a réussi, le code d'erreur standard de la première erreur rencontrée sinon.
DEPENDANCES memory_char2font(), memory_exists(), memory_writefile()

Fonctions utilisateur

int memory_user_select(char **files, int l, int extension, int exit);// Prototype
int n = memory_user_select(files,20,1,0);//   Exemple
DESCRIPTION Interface de choix de fichiers. L'utilisateur choisit le fichier de son choix dans la liste de fichiers files. Celle-ci peut être obtenue par memory_find(). La variable l est le nombre maximal de fichiers pouvant être présents dans la liste. Le paramètre extension définit si les extensions sont ou non affichées, où exit définit si l'utilisateur peut annuler la sélection et quitter l'interface en appuyant sur [EXIT].
RETOUR Retourne l'index du fichier choisi dans la liste, ou -1 si l'utilisateur quitte avec [EXIT], le paramètre exit étant non nul.
DEPENDANCES malloc(), strcmp(), Bdisp_AllClr_VRAM(), Bdisp_SetPoint_VRAM(), PrintXY(), Bdisp_DrawLineVRAM(), GetKey()
void *memory_user_autoload(char *prefix, char *selector, int l, int extension, int exit);// Prototype
unsigned char *data = memory_user_autoload("\\\\crd0\\","*",20,0,1);//   Exemple
DESCRIPTION Fonction de chargement automatique de fichiers. Le paramètre prefix est le répertoire de recherche et selector le motif de recherche. l est le nombre de fichiers à allouer. Les paramètres extension et exit indiquent si les extensions des fichiers sont affichées et si l'utilisateur peut annuler le chargement avec [EXIT].
RETOUR Retourne un pointeur alloué sur les données chargées si l'opération a réussi, NULL si elle a échoué ou si l'utilisateur a quitté avec [EXIT], exit étant non nul.
DEPENDANCES memory_alloc(), malloc(), sprintf(), memory_find(), memory_user_select(), memory_load(), memory_free(), free()
VOIR AUSSI Les motifs de recherche

Autres fonctions

void memory_seterrors(int errors);// Prototype
memory_seterrors(1);//   Exemple
DESCRIPTION Active les erreurs si errors est non nul, les désactive sinon.
RETOUR Ne retourne rien.
void memory_error(char *from, char *function, int val);// Prototype
if(x<0) memory_error("main()","openfile()",x);//   Exemple
DESCRIPTION Si les erreurs ont été activées avec memory_seterrors(), affiche dans une popup les informations passées en paramètres et, pour les valeurs habituelles de i, quelques mots sur la cause de l'erreur.
RETOUR Ne retourne rien.
DEPENDANCES sprintf(), PopUpWin(), Print(), GetKey()
NOTA BENE Cette fonction n'est destinée à être utilisée que par les fonctions internes de memory.
unsigned short *memory_char2font(char *adresse);// Prototype
FONTCHARACTER *adr = memory_char2font("\\\\fls0\\"RECORDS.SAV")//   Exemple
DESCRIPTION Génère une adresse FONTCHARACTER depuis une adresse en char *.
RETOUR Retourne un pointeur alloué sur l'adresse FONTCHARACTER.
DEPENDANCES calloc()
NOTA BENE Cette fonction n'est destinée à être utilisée que par les fonctions internes de memory. Si vous l'utilisez, veillez à libérer le pointeur après utilisation.

Documentation sur la mémoire

Les codes d'erreur standard

Les fonctions de Bfile utilisent des codes d'erreur définis pour indiquer quelle erreur se produit lorsqu'une fonction de manipulation de la mémoire se termine de manière inattendue. memory utilise également des codes d'erreur pour signaler d'autres raisons pour que la fonction ait échouée. Ceux-ci sont positifs alors que ceux de Bfile sont négatifs.
Voici la liste des codes que vous pouvez obtenir ainsi que la raison de l'erreur associée.

CODE D'ERREURRAISON DE L'ERREUR
1Not enough RAM
0No error
-1Entry not found
-2Illegal parameter
-3Illegal path
-4Device full
-5Illegal device
-6Illegal filesystem
-7Illegal system
-8Access denyed
-9Already locked
-10Illegal task ID
-11Permission error
-12Entry full
-13Already exist entrys
-14Read-only file
-15Illegal filter
-16Enumrate end
-17Device changed
-18Not record file (not used)
-19Illegal seek position
-20Illegal block file
-21Device not exist (not used)
-22End of file (not used)
-23Not mount device
-24Not unmount device
-25Cannot lock system
-26Record not found
-27Not dual record file (not used)
-28Not alarm support
-29Cannot add alarm
-30File find used
-31Device error
-32System not locked
-33Device not found
-34File type mismatch
-35Not empty
-36Broken system data
-37Media not ready
-38Too many alarm item
-39Same alarm exist
-40Access SWAP area
-41Multimedia card
-42Copy protection
-43Illegal file data

Les motifs de recherche

Lorsqu'une recherche est effectuée, un motif est utilisé comme modèle pour les noms de fichiers. L'expression régulière peut être composée de différents symboles.

Prenons un exemple. Le motif \\\\fls0\\* provoquera la liste de tous les fichiers du répertoire à la racine de la mémoire de stockage. La recherche n'est pas récursive. En revanche, \\\\crd0\\*.LOG ne génèrera que la liste des fichiers de la racine de la carte SD qui ont LOG pour extension. On peut avoir plusieurs * dans un même motif. Ainsi, \\\\fls0\\MYGAME\\*.M* provoquera la liste de tous les fichiers du sous- répertoire MYGAME de la mémoire de stockage dont l'extension commence par la lettre M.

Les pointeurs de recherche

Lorsque vous effectuez une recherche, vous utilisez un pointeur alloué avec memory_alloc() et libéré avc memory_free(). Ce pointeur pointe sur... des pointeurs. Pour être précis, un tableau de l pointeurs, la variable que vous avez passée en paramètre à memory_alloc(). De même, chacun de ces pointeurs pointe sur une zone de mémoire allouée de 14 octets, pour contenir le nom d'un fichier ainsi que son extension.
C'est pourquoi la recherche ne peut trouver plus de l fichiers, car l'espace mémoire pour inscrire leurs noms est limité. C'est également pour cette raison qu'il est important de passer la même valeur en paramètres de memory_alloc() et memory_free(), sans quoi vous ferez face à des fuites de mémoire. De même, il est conseillé d'utiliser la même valeur pour memory_find(), cela évite les mauvaises surprises.
Puisque le pointeur est de type char ** et qu'il pointe sur des pointeurs alloués, on eut facilement accéder à un des noms de fichiers, d'index i, en utilisant la formule files[i]. Cette expression est de type char *, c'est-à-dire le même que le texte classique, on peut donc l'employer au mêmes fins. Le pointeur n'est pas protégé en écriture, mais il est conseillé de ne pas le modifier à moins d'être sûr(e) de ce que vous faites.

La sécurité avec memory

memory possède également des interfaces de sécurité qui vous signalent les erreurs qui ont lieu à la manière des System ERROR. Bien entendu, elles n'arrêtent pas l'exécution de l'application, mais vous permettent de détecter les erreurs liées à la mémoire dans votre programme. Ces dernières sont présentées par quatre informations :

Tutoriel d'utilisation

Présentation

Cette partie est un tutoriel sur l'utilisation de memory pour la manipulation du système de fichiers.
Si vous lisez ce fichier, c'est probablement que vous l'avez téléchargée (sinon, ici), donc décompressez les fichiers memory.c et memory.h dans le dossier de votre projet. Ensuite dans la fenêtre "Files in Project" du SDK, ajoutez memory.c au projet en tant que fichier source. N'en faites pas de même avec le header memory.h, sous peine de quoi vous auriez une belle erreur du compilateur : "The following dependant files does not exist :...".
N'oubliez pas d'inclure le header (memory.h) dans tous les fichiers où vous utiliser ses fonctions.

Avant tout, sachez que l'émulateur utilise pour carte SD le dossier SDCard des données de votre projet. Vous pourrez ainsi envoyer des fichiers du SDK à l'ordinateur, et cela nous sera utile pour le debuggage.
Pour transférer un fichier entre la mémoire de stockage et la carte SD quel que soit le sens, rendez-vous dans l'application MEMORY de l'émulateur et sélectionnez-le. Validez ensuite la copie avec [F2] dans le dossier où vous souhaitez le copier. Vous pouvez ouvrir tout fichier de la carte SD sur votre ordinateur. Pour les consulter correctement, je vous conseille d'utiliser un éditeur hexadécimal de fichiers. Il en est un excellent nommé HxD.

Les fichiers de sauvegarde

C'est la principale utilisation qui est faite des fichiers. Souvent on sauvegarde les données dans un seul fichier, à une adresse définie. Des fonctions pour sauvegarder et charger les sauvegardes autmatiquement ont donc été créées.

Créer une sauvegarde

Pour créer une sauvegarde, il va falloir utiliser une chaîne de caractères contenant le texte à sauvegarder. Nous allons donc utiliser sprintf() pour écrire ces données dans notre chaîne.

char ch[12];
sprintf(ch,"%3d%3d%3d",vies,niveau,trophees);
memory_save("\\\\fls0\\SAVE.SAV",ch,10);

Le fichier est automatiquement supprimé s'il existait, créé avec juste la taille nécessaire, ouvert, rempli puis fermé. Vous n'avez donc rien à gérer dans votre programme.

Lire une sauvegarde

Lire une sauvegarde est encore plus simple que de l'écrire.

unsigned char *p = memory_load("\\\\fls0\\SAVE.SAV");

Le pointeur renvoyé est alloué dynamiquement si le chargement a réussi, NULL sinon. N'oubliez pas de le libérer.

Rechercher des fichiers

Allouer de la mémoire

Pour effectuer une recherche de fichiers, la première chose à faire est d'allouer de la mémoire. Pour cela, nous allons utiliser memory_alloc() qui prend en paramètre le nombre de fichier maximal que vous voudrez cherchez. Notez que le nombre de fichiers trouvés ne dépassera pas cette valeur.

char **files = memory_alloc(20);

Lancer la recherche

La recherche est effectuée par la fonction memory_find(). Celle-ci prend en argument le pointeur alloué, le motif de recherche et le nombre de fichiers que vous avez alloué. Elle renvoie le nombre de fichiers trouvés.
Les motifs de recherche

int x = memory_find("\\\\crd0\\*E.T*",files,20);

Vous avez alors accès à la liste des noms de fichiers trouvés. Attention, le nom du répertoire est absent des données, il vous faut donc le rajouter.

Libérer les données allouées

Pour effectuer la recherche, vous avez alloué un pointeur, il faut maintenant le libérer. La fonction memory_free() prend en paramètre le pointeur et le nombre de fichiers alloués.

memory_free(files,20);

Une fois ceci fait, n'utilisez plus le pointeur libéré.

Exemple complet

/* Code d'exemple complet d'utilisation de memory_find() */

char **files = memory_alloc(20);
int x = memory_find("\\\\crd0\\*E.T*",files,20);
unsigned char *data;
char ch[20];

sprintf(ch,"\\\\crd0\\%s",files[0]);
data = memory_load(ch);
free(data);
memory_free(files,20);

L'exemple ci-dessus charge dans la mémoire le premier fichier trouvé correspondant au motif défini.

Interfacage

Choix à partir d'une recherche

memory contient également une fonction d'interfacage avec l'utilisateur pour permettre facilement le choix d'un fichier parmi une liste. Dans l'exemple ci-après, nous allons utiliser celle générée par memory_find().
La fonction memory_user_select() prend en paramètres la liste des fichiers, le nombre de fichiers (ici celui trouvé et non alloué), ainsi que deux paramètres qui déterminent respectivement si la fonction affiche (1) ou non (0) les extensions et si l'utilisateur peut (1) ou non (0) annuler le choix en appuyant sur [EXIT].

char **files = memory_alloc(20);
unsigned char *data;
char ch[20];
int x;

x = memory_find("\\\\crd0\\*E.T*",files,20);
x = memory_user_select(files,x,1,0);
sprintf(ch,"\\\\crd0\\%s",files[x]);
data = memory_load(ch);
// Utilisation du contenu...
free(data);
memory_free(files,20);

La fonction retourne l'index dans la liste du fichier chargé, ou -1 si l'utilisateur quitte avec [EXIT].
Vous pouvez également utiliser votre propre liste, dans ce cas veillez à ce qu'elle ait été correctement allouée, et à ce qu'elle ne contienne que les noms des fichiers.
Les pointeurs de recherche

Choix et chargement

Une fonction très complète existe pour cela. Elle effectue la recherche de fichiers dans un dossier donné et génère la liste des fichiers correspondant au motif de recherche. Elle demande ensuite à l'utilisateur de choisir le fichier à charger, et le charge avec memory_load().
memory_user_autoload() prend en paramètres le dossier de travail, le motif de recherche, le nombre de fichiers à allouer, et comme sa cousine les paramètres décidant de l'affichage des extensions et de la sortie avec [EXIT].

unsigned char *p = memory_user_autoload("\\\\crd0\\","*",20,1,0);

Comme vous pouvez le voir, cette fonction est très simple à utiliser. Elle renvoie un pointeur alloué dynamiquement pointant sur le contenu du fichier chargé dans la mémoire si le chargement a réussi (dans ce cas, pensez à le libérer après utilisation), ou un pointeur NULL si le chargement a échoué.