Frustrations With Reading From a File on a DS

Posted by Dean Carlson
Apr 27 2009

According to the PAlib examples, reading from files via FAT is supposedly pretty easy, as depicted by this code (shortened for space):

#include "PA9.h"       // Include for PA_Lib
#include "fat.h"       // Include for FAT read/writes
int main(int argc, char ** argv)
{
...
fatInitDefault(); //Initialise fat library
FILE* testRead = fopen ("FATTest.txt", "rb"); //rb = read
char filetext[30];
fread(filetext, 30, 1, testRead);
fclose(testRead);

PA_OutputSimpleText(1, 1, 7, "FATTest.txt contains:");
PA_OutputText(1, 2, 8, "%s", filetext);
...
return 0;
} // End of main()

(Apologies that the code tags don’t seem to work in this theme…yet)

Well this code seems to appears to work on the emulator, and it’s really hit or miss on the actual DS. So I began to delve into this problem. After about 8-9 hours of trying to debug this problem by myself and with the assistance of Dr. Malloy trying many different things we didn’t really come to any finite conclusions.

Luckily, other students in my class are also reading from files and have found that FAT is no longer supported in this version in PAlib and have been using Embedded File System (EFS) Library to deal with file reading. So, that was a bunch of time wasted.

This is the EFS example that I found (shortened for space):

#include "PA9.h"        // Include for PA_Lib
#include "unistd.h"
#include "efs_lib.h"     // include EFS lib
int main(void) {
// init EFSlib & libfat
if(EFS_Init(EFS_AND_FAT | EFS_DEFAULT_DEVICE, NULL)) {
PA_OutputSimpleText(1, 0, 0, "EFS init ok");
PA_OutputText(1, 0, 1, "found NDS path: %s", efs_path);
struct stat st;
FILE* file;
u8* buffer;
int size;
// open a text file and read its contents
file = fopen("/test.txt", "rb");
if(file != NULL) {
stat("/test.txt", &st);// get file size using stat
size = st.st_size;
buffer = (u8*)malloc(size);
fread(buffer, 1, size, file);
buffer[size-1] = '\0';
PA_OutputText(1, 0, 4, "/test.txt content: '%s'", buffer);
PA_OutputText(1, 10, 5, "size: %d bytes", size);
free(buffer);
fclose(file);
}
} else {
PA_OutputSimpleText(1, 0, 0, "EFS init error!");
}
...
return 0;
}

(Again, apologies that the code tags don’t seem to work in this theme)

This works fine on both the emulator and the DS, except it only seems to work for doing it once, otherwise I get “EFS init error!”. So, at first I thought I would have to read each map and question into separate arrays at the beginning of the program. This, of course, is a horrible idea, not only would it increase load time by a significant amount but it would hog a ton of memory. So I began to try and figure out this problem. After a few more hours of investigation and debugging, I finally find out the problem. It turns out that the statement  “

if(EFS_Init(EFS_AND_FAT | EFS_DEFAULT_DEVICE, NULL))" 

will fail every time after the first call. It will fail because they have already been initialized. So that was a simple fix. I just modified it to this:

EFS_Init(EFS_AND_FAT | EFS_DEFAULT_DEVICE, NULL);
FILE* file = fopen (filename, "rb");
if ( file != NULL){

After more time being spent trying to figure out this new library, I think I finally have it figured out. EFS puts all of the files that you put into the “efsroot” folder in your program is loaded onto the NDS file and needs to be recompiled to have changes made to the file, be included in the NDS to be read. This kind of defeats the purpose of dynamic maps and questions on the files if they don’t have the source to recompile the NDS. Questions and maps will still be read from the files, in hope that reading and writing from files will become more dynamic in the future. Another thing is that EFS read works on the emulator but not EFS write. However, both work on the DS. So, after probably 12ish hours trying to trouble shoot the simple thing of file reading, it is finally solved and reading my maps into a 2d array to be rendered onto the screen.

  • Share/Bookmark

Newer : Fastforward!

Older : Slooowwwwww

8 Responses

  1. Marta says:

    really helped because I was always getting the error initializing EFS. Thank you vey much. My problem is that I don’t know where I have to store the files in the DS. I keep getting the message: sound not found or bg not found.
    It has to be in a directory called efsroot? In the emulator works that way but when I copy:

    /myprogram.nds
    /efsroot/data/bg
    /efsroot/data/sfx

    it fails.. (I’ve a PA_FatSetBasePath(”data”);)

    Do you know what I’m doing wrong?

  2. Dean Carlson says:

    Hi Marta,
    In your project folder (ex. C:/Projects/MyProject) you should make a folder called “efsroot” and put the files within that folder (ex. C:/Projects/MyProject/efsroot/data/sfx). Then when you build the project, EFSlib will put the files directly onto the .nds file. So you can directly open the file like this:
    FILE* file = fopen (”data/sfx/filename”, “rb”);
    You do not need to put the actual files in a directory on the DS. EFSlib handles putting the files directly integrated into your .nds file.
    Hope this helps

  3. Marta says:

    thanks to your post and a review of the Makefile I’m able to use it.
    It’s a pity that all the data should be put during compilation.. it would be great if it can be loaded from a connection with wifi or something like that..more dynamic.
    Anyway, the program runs well in the DS and in the no$gba emulator but it doesn’t work in iDeaS. Which emulator do you use?

  4. Dean Carlson says:

    Glad you got everything worked out. I agree, it is a shame that everything is out in during compilation as it could have so much more potential with dynamic file reading. However, one benefit of the file being compiled on is that it reduces the file sizes. As far as which emulator I use, I prefer DeSmuME.

  5. Marta says:

    thanks.
    I would like to ask you: Do you know the difference between FAT and EFS?
    And: It is possible with FAT to keep the files outside the .nds?

  6. Dean Carlson says:

    As far as I know FAT allows for dynamic reading and writing, to and from files outside of the .nds file. Unfortunately, it appears FAT is no longer supported with the current version of PAlib as seen here (http://www.palib.info/wiki/doku.php?id=day9), and it is recommended to use EFS_Lib. There are other libraries like LibNDS, as an alternative to PAlib, that have more potential but are more complicated to learn and use (or so I hear), but I’m not sure how it handles file read/writes.

  7. Chandrasekhar says:

    Excellent post i am sure that i will come back here soon

  8. Lindsay says:

    I saw many sites but yours is awsome, bookmarked for future referrence.

Trackback URL for this entry