Jour 8 - DS Hardware ← Précédent
EFS est synonyme de système de fichiers embarqués et cela vous permet de mettre d’autres fichiers “a l’interieur” d’une ROM NDS sans toutefois utilisé la rom comme un endroit de stockage mais seulement d’appel au fichiers. Pour des tutoriaux plus approfondies google est votre ami.
Tout d’abord, qu’est-ce qu’un système de fichiers ? Pourquoi en a-t-on besoin ?
En fait, un système de fichiers, ce n’est pas grand chose, simplement une autre façon d’ajouter des fichiers à votre rom. Vous connaissez déjà la méthode simple : ajouter les fichiers lors de la compilation soit avec un fichier .c, ou en utilisant un fichier dans le dossier data (voir les exemples de gif/jpeg). Il existe une méthode qui consiste à ajouter les fichiers après la compilation. Oui, c’est possible, et ca présente quelques avantages :
Cela signifie aussi que de tels fichiers ne marcheront qu’avec une carte flash gba, mais ne fonctionneront pas avec WMB, CF ou autre... (J’ai fait une version qui marche avec les autres, mais il y a la limite de 4Mo...)
Il y a cependant quelques inconvénients...
Le système de fichiers DS de PAlib s’appelle PAFS (PAlib File System). Vous pouvez aussi utiliser GBFS, qui existait pour PAlib avant que PAFS ne sorte, et qui fonctionne toujours pour des raisons de compatibilité...
A vos marques! Prêts ? Partez ! Comme vous pouviez le deviner, quelques fichiers sont requis pour faire marcher le système de fichiers. Commençons par regarder l’exemple PAFS/PAFS de PAlib, qui est le plus simple. Ouvrez le dossier, vous trouverez plus de fichiers que d’habitude...
PAFS PAFS.ds.gba. Mais à quoi ça sert ? Files/.
Bon, vous voyez le dossier Files ? Il contient plusieurs fichiers texte. Ils ne servent qu’à vérifier que l’ajout de fichiers marche. Si ça marche, vous devriez pouvoir ouvrir ces fichiers depuis votre DS (comme un lecteur de livre !). Allons maintenant voir le code !
Vous pouvez aussi trouver une copie des fichiers PAFS.exe et .bat dans le dossier PAlibTools.
Important!!! Il y a des étapes à suivre pour que le programme ne plante pas au chargement des données:
Voila ça marche!!!.
Restez dans le même exemple, et ouvrez main.c. Voici ce que vous devriez avoir dans votre fonction principale :
PA_InitText(0, 0); // Initialise the text system on the bottom screen PA_InitText(1, 0); // Initialise the text system on the top screen PA_OutputText(1, 0, 0, "Loading PAFS..."); u32 FileNumber = PA_FSInit(); // Inits PA File System, and returns the number of files PA_OutputText(1, 0, 1, " Files : %d ", FileNumber); // For each file, we'll draw it's name on the bottom screen... s32 i; for (i = 0; i < FileNumber; i++){ PA_OutputText(0, 0, i, "%s.%s Size : %d, %d", PA_FSFile[i].Name, PA_FSFile[i].Ext, PA_FSFile[i].Length, PA_FSFile[i].FilePos); } // Output the first file text on the top screen, just to test... PA_OutputText(1, 0, 5, "File 0 : %s", PA_PAFSFile(0)); PA_OutputText(1, 0, 7, "File 1 : %s", PA_PAFSFile(1)); PA_OutputText(1, 0, 9, "File 2 : %s", PA_PAFSFile(2)); // Infinite loop to keep the program running while (1) { PA_WaitForVBL(); }
Nous commençons avec 2 inits des textes, un pour chaque écran, et un texte simple “Loading PAFS...”
Ensuite, vient la partie importante:
u32 FileNumber = PA_FSInit(); PA_FSInit est la fonction qui initialise le système de fichiers. Si vous ne l’employez pas, vous ne pourrez lire aucun de vos fichiers… Pour l’information, il y a des scans fait rapidement par votre ROM pour rechercher le système de fichiers… et alors il lit l’information sur les différents dossiers. Cette fonction renvoie le nombre total de dossiers, et stocke cela dans la variable FileNumber.
Après arrive ce bout de code PA_OutputText(1, 0, 1, " Files : %d “, FileNumber); En esperant que vous avez lu le tutorial a propos du texte ! Il affiche juste le nombre de fichiers donnés par PA_FSInit… Maintenant, la partie intéressante commence :
s32 i; for (i = 0; i < FileNumber; i++){ PA_OutputText(0, 0, i, "%s.%s Size : %d, %d", PA_FSFile[i].Name, PA_FSFile[i].Ext, PA_FSFile[i].Length, PA_FSFile[i].FilePos); }
Qu’est-ce que cela fait ? Pour chaque fichier (le premier étant le fichier 0, et FileNumber indicant le nombre de fichiers), il produira sur l’écran le nom du fichier (sans l’extension, exemple : .txt, .dat, . jpg) et sa position dans le système de fichiers. Vous n’emploierez pas beaucoup ces 2 dernières informations, mais le nom et son extension seront beaucoup utilisés plus tard…
Comme vous pouvez le voir, c’est simple pour obtenir toute cette information. Tout se trouve dans la fonction PA_FSFile, PA_FSFile[n] pour le numéro du fichier (attention, il commence par le fichier0, non 1). .Name, .Ext, .Length et .FilePos sont les 4 variables possibles.
La dernière chose que vous voyez (il n’y a rien dans la boucle infinie !), est PA_OutputText(1, 0, 5, “File 0 : %s”, PA_PAFSFile(0));. C’est la chose la plus importante à se rappeler, alors ouvrez grand vos yeux !
Ok, maintenant que nous avons vu le code, vous pouvez compiler… Avant de mettre la ROM sur Nintendo DS, n’oubliez d’ajouter les fichiers! Pour ce faire, ouvrez PAFS.bat qui se trouve dans le dossier avec build.bat, qui inclura tous les fichiers. Essayez, vous devriez voir les textes sur votre écran de DS !
Yup, ceci est déjà fini ! Mais le tutorial pas encore. Il y a encore quelques trucs à voir, comme lire la structure des fichiers, ou utiliser PAFS avec une carte WMB ou CF… Il y a également quelques exemples de PAFS employé pour charger des dossiers, de la musique ou des images, et vous les trouverez dans C:\devkitPro\PAlibExamples\PAFS.
Je reconnais que ce n’est pas si utile que ça d’avoir des dossiers dans un système de fichiers, mais ça pourra aider pour la lecture des fichiers. Par exemple, on peut demander à l’utilisateur de mettre ses musiques dans Files/Music, et ses images dans Files/Images, etc ...
Vu que ce n’est pas si intuitif (désolé, j’ai fait de mon mieux !), je vais expliquer en détail comment les utiliser.
L’exemple PAlib est PAFS Folders. Je ne vais pas détailler toutes les fonctions PAFS que nous avons vu juste avant, donc j’espère que vous avez déjà mémorisé tout ça! Si ce n’est pas le cas, jetez y un coup d’œil à nouveau et vérifiez quelques détails si vous n’êtes pas sûrs.
Cet exemple est un peu plus compliqué que ce que nous avons vu avant, mais je vais faire de mon mieux pour rendre ça aussi facile que possible. Il contient deux fonctions, la classique fonction main, et WriteFolders. En fait, ce n’est pas vraiment une fonction qu’on va utiliser avec PAFS, mais c’est utilisé ici pour afficher les informations à propos du dossier.
Le code principal est exactement le même que celui qu’on vient de voir, on a juste rajouté WriteFolders(0); à l’intérieur. Cette fonction lit le contenu (sous-dossiers et fichiers) du dossier numéro 0. Si vous ne savez pas combien de dossiers il y a, vérifiez juste la valeur de PA_FSSys→Nfolders, et vous saurez (ça compte les dossiers ET les sous-dossiers ensemble). Le dossier 0 est en fait le dossier Files.
void WriteFolders(u16 N){ // Recursive function to write the number of folders u16 Nfolder = N; // Write the folder's name... PA_OutputText(1, indent, foldery, "%s : %d folders, %d files", PA_FSFolder[Nfolder].Name, PA_FSFolder[Nfolder].NFolders, PA_FSFolder[Nfolder].NFiles); foldery++; if (PA_FSFolder[Nfolder].NFolders > 0){ // For every subfolder, check their subfolders indent+=2; // Indents for the subfolders s32 k; for (k = 0; k < PA_FSFolder[Nfolder].NFolders; k++){ // Note : PA_FSFolder[i].FirstFile stores the number of the first file, //so the files go from //PA_FSFolder[i].FirstFile to PA_FSFolder[i].FirstFile + PA_FSFolder[i].NFiles WriteFolders(PA_FSFolder[Nfolder].FirstFolder + k); // Check the subfolders } indent -= 2; } }
Pour rester aussi simple et clair que possible, je ne vais pas décrire toutes les lignes de code de cette fonction. Il faut juste savoir qu’elle affiche les dossiers et sous-dossiers et différents niveaux sur l’écran, pour montrer quel dossiers contient quels autres...
Tout ce qu’il faut comprendre est ce qui est contenu dans le tableau de structure PA_FSFolder. Il contient les informations sur les différents dossiers, et voila les variables :
Files par exemple.Et voila !
Faites juste comme avant, compilez, utilisez PAFS.bat, et regardez le résultat sur votre DS.
Je ne vais pas donner plus de détails que ça, et on va passer à l’utilisation de PAFS sur émulateur (comme dualis) et WMB.
J’ai dit au début que PAFS stockait les fichiers dans la rom au lieu de la ram, mais vous pouvez forcer le stockage des fichiers dans la ram. Grâce à ça, cela marchera sur les émulateurs, WMB, et n’importe quel type de linker...même si ça a quelques limitations, la première étant la taille maximum de 4MB pour la rom, et la seconde étant que vous devez spécifier dans votre code combien de mémoire vous voulez donner à l’utilisateur. Si vous ne spécifiez pas assez, ça ne marchera pas. Le code est vraiment simple, même s’il y a deux choses de plus que le code PAFS classique. Ouvrez PAFS_Ram et regardez !
// Includes #include <PA9.h> // Include for PA_Lib PA_FSRam(100000); /* Ceci définit la taille de la mémoire que vous allouez au maximum pour les fichiers ... Je l'ai mise à 100ko, ici. Vous pouvez en utiliser plus (comme 2 Mo, mais pas beaucoup plus) ou aussi peu de Ko si vous n'avez pas besoin d'en mettre beaucoup plus ...*/ // Function: main() int main(int argc, char ** argv) { PA_Init(); // Initialisation PA_Lib PA_InitVBL(); // Initialise une norme VBL PA_InitText(0, 0); // Initialise le système de texte sur l'écran du bas PA_InitText(1, 0); // Initialiser le système de texte sur l'écran du haut PA_OutputText(1, 0, 0, "Chargement PAFS..."); PAFSStart = (char*)PA_FileSystem; // Dit l'utilisation du RAM ... u32 FileNumber = PA_FSRamInit(); // Inits PA Ram File System, et retourne le nombre de fichiers
Je n’ai donné que le début du fichier et l’initialisation de PAFS, tout le reste est identique aux autres exemples de PAFS.
Voila, c’est tout ! Nous avons déja vu tout le reste, donc vous pouvez compiler, ajouter les fichiers, et tester sur dualis (c’est ce que je fais) pour voir si ça marche réellement :-p
Le DLDI est un systeme que Chishm a mis en place pour pouvoir utiliser des fichiers qui se trouvent sur le linker. Plus d’infos : ici
Le seul problème de cette méthode est que ça ne marche pas avec certains linkers. Et il faut aussi patcher la rom avec les fichiers *.dldi correspondant à son linker, on peut les trouver sur le site de Chishm. Mais maintenant la majorité des linkers patchent automatiquement la rom donc vous n’aurez pas à vous en soucier pour la plupart d’entre vous.
Voilà maintenant quelques explications sur l’utilisation :
Avant d’utiliser une fonction de la lib fat, vous devez l’initialiser :
fatInitDefault();
Vous pouvez maintenant vous servir des fonctions standard de manipulation de fichier.
Voici un exemple qui charge un fichier jpg dans un buffer:
fatInitDefault(); //Initialise la fat FILE* imgFile = fopen ("Zelda.jpg", "rb");//ouvre le fichier zelda.jpg en mode lecture if(imgFile){//regarde si le fichier c'est bien ouvert //on cherche la taille du fichier, cela sert apres pour le buffer u32 imgSize; fseek (imgFile, 0 , SEEK_END); imgSize = ftell (imgFile); rewind (imgFile);//on retroune au debut du fichier // on alloue suffisamment de mémoire et on stocke l'adresse dans buffer char * buffer; buffer = (char*) malloc (sizeof(char)*imgSize); fread (buffer, 1, imgSize, imgFile); fclose (imgFile);//on ferme le fichier
Il existe d’autres fonctions spécifiques à la fat qui permettent de chercher les fichiers sur la carte et ainsi de permettre à l’utilisateur de choisir un fichier, mais ceci sera mis ici ultérieurement.
Suivant → Jour 10 - Fonctions 3D