EFS Library

Download
EFS Library v2.0 + example
EFS Patcher v1.0 + source code

EFS Patcher Universal (with OSX binary) + source code (modification by Justin Walsh)

What is the EFS Lib?
EFS (Embedded File System) is a new set of library / tools to manage files embedded within a NDS binary, like graphic / music / sound / config data, for example.
Basically, itโ€™s an appended file system like the old GBFS, but it has many more features and less limitations. It’s also more standard, as it makes use of the NitroFS, using ndstool.

What are the most important features of EFS Lib?
– It works on all slot-1 & 2 cards via DLDI patching, but also on GBA carts
– It also works on emulators without any changes in the code
– The NDS file path in the card is autodetected and stored within NDS, using unique ID generated by the EFS patcher. The file path is searched only on the first launch, and if the file has moved.
– Support reading & writing file support [writing only works using DLDI]. For writing, space must be already allocated.
– It has a complete devoptab integration, so it works the same way as libfat using standard C I/O functions.
– It’s very fast, and opening a file is way faster than with libfat

How can the EFS Lib be useful for me?
– You can store all the data (gfx, sfx, music, texts, scripts..) used by your project inside one tidy .nds
– You can use way more than 4Mo of data in your program because the data stored inside the EFS is not loaded in RAM when your homebrew is loaded.
– You can use it to retrieve the current path of you NDS to avoid the root bloating problem, and write external data in a relative path.
– You can use it to test on emulators your existing programs that use libfat without changing anything and using complicated FCSR method, just init EFS as the default device, put your data in the efsroot folder and you’re done

etc etc ๐Ÿ˜‰

Can you tell me more about the retrieval of current path?
On compile time, space is allocated in your homebrew to store its current path, its unique ID and file size. File size and unique ID is filled by the EFS patcher, usually just after compilation in the makefile.

On the first launch, the file is quickly searched on whole card, for a match of the stored file size and ID. Once the file is found, its current path is written inside the file itself. The next time the homebrew is launched, this path is checked to verify if the file match ID & file size: if it’s the case, to need to search for the file again, we’re good, otherwise it means that the file has moved then we go through the search again.

Q: But as argv is already supported by DKA to provide the current path, isn’t your search method obsolote?

A: Yes, but for now, no existing homebrew loader makes use of that feature. But fortunately, when this will be supported, you’ll just have to provide this path as an argument on EFS init, and instead of searching the card, EFS will check the path provided. So you don’t have to worry of future problems with using EFS lib, it’s already future-proof ๐Ÿ™‚

History:

25/06/2008 – v2.0
+ complete rewrite of the lib (breaks compatibility with old versions!)
+ added full devoptab integration, so it now use standard iolib functions
+ added automatic GBA rom detection (so it works in GBA flash kits & emu without any modifications), based on Eris’ NitroFS driver idea
+ full chdir and unix standard paths (relative/absolute) support
+ great speed improve

______________ EFS Lib v1.x archive ______________
Download:
efs_lib_v1.2.zip
efs_patcher_v1.0.zip
efs_example_libnds_v1.1.zip
efs_example_palib_v1.1.zip

EFS (Embedded File System) is a new set of library / tools to manage files embedded within a NDS binary.

Basically, it’s an appended file system like GBFS, but it has many more features and less limitations:
– use NitroFS via ndstool
– works on slot-1 & 2, via DLDI patch
– autodetection of the NDS file in the card, using unique ID generated by the EFS patcher
– autosaving of the NDS file path in the card inside the NDS file. If the file has moved, then it’s searched again
– read/write file support (for writing, space must be already allocated)
– multiple files can be opened at the same time
– directory listing
– can use real FAT instead of EFS with a simple define (useful for debugging, when you need to change files without changing the code)

It works on emulator by using the fcsr method by GPF and including the .nds (or the .ds.gba, it depends of the emu) itself in the FAT image.

History:
12/05/2007 – v1.0
= Original release

13/05/2007 – v1.1
= cleaned up code a bit
= corrected problems with nds files with loader
= corrected problems with nds files made with standard libnds makefile
– removed header struct
+ optimised variables, now use 505 bytes less in RAM
+ added EFS_Flush() function, to ensure data is written
+ included ASM code for reserved space in efs_lib.c

14/05/2007 – v1.1a
= corrected bug with EFS_fopen() when filename does not begin with “/”
+ added defines for c++ compatibility

28/09/2007 – v1.2
= fixed real fat mode (hopefully)
= corrected a major bug with EFS_fread and EFS_fwrite
= moved some functions tweaks to fix real fat mode
+ added autoflush on file close by default
+ added extension checking when searching the NDS file (improve speed)
+ added some options

Warning:
After a series of writes, make sure you call EFS_Flush(), to ensure data is written (automatically done by default now).
This is due to a libfat limitation (caused by its the cache system, and the way EFS lib use libfat).

16 Comments Add your own

  • 1. LuTHieR  |  March 11, 2008 at 5:22 pm

    Hi Noda,
    and thanks for the EFS project, it looks really great. Unfortunately, I haven’t been able to run it, for whenever I try to compile it it gives me the following error:

    1>c:/devkitPro/PAlib/lib\libpa9.a(PA_IO.o): In function `PA_InitFat’:
    1>PA_IO.c:(.text+0x8): undefined reference to `fatInitDefault’
    1>collect2: ld returned 1 exit status
    1>make[1]: *** [/c/developer/NDS/PruebaEFS/PruebasEFS/PruebaEFS/Release/PruebaEFS.elf] Error 1
    1>make: *** [build] Error 2

    I read somewhere that it can be fixed using

    LIBSPA := -lfat -lpa9

    in the Makefile but it doesn’t work either… can you tell me how to fix it? thank you very much.

    LuTHieR

    Reply
  • 2. Almost A Jump’n’Run | Johannes "jfk" Kuhlmann's Blog  |  August 17, 2008 at 6:15 pm

    […] map is loaded using the EFS library (forum thread at gbadev) which makes it very easy to read data that is actually appended to the […]

    Reply
  • 3. Eduardo Costa  |  March 30, 2009 at 10:36 am

    Have you tested it with devKitARM r25? It changed a lot since r23, and the example does not work in my NDS (using R4DS). With desemume e no$gba, it works…

    Reply
  • 4. Noda  |  April 1, 2009 at 7:45 am

    Sorry, I stopped NDS dev at devKitARM r21-r22, I don’t know if this still works… The example may not works with R4DS if you have a ram pack, a supercard or gba memory in the slot2. That was a bug I was supposed to fix long time ago… ๐Ÿ˜ฆ

    Reply
  • 5. file i/o handling in nds homebrew « console-dev.de  |  May 9, 2009 at 6:46 pm

    […] set for all this, which I won’t share,ย  but there is a free public solution for it called Embedded File System Library as well. I’ve never used EFS, but it should do exactly what we need if we trust its […]

    Reply
  • 6. Yannick Effinger  |  May 11, 2009 at 11:34 am

    Hi, I had a little problem with EFS v2 and my Supercard DSone. I decided to dive into the EFS code and found out my DS hung on the part where EFS was searching the NDS on my SDcard.

    I rewrote the whole function SearchDirectory(), and here is the resulting piece of code below :

    bool SearchDirectory() {
    DIR *pdir;
    struct dirent *pent;
    struct stat statbuf;
    bool found = false;
    char path[EFS_MAXPATHLEN];

    pdir = opendir(".");
    while (((pent=readdir(pdir))!=NULL) && (!found)) {
    stat(pent->d_name, &statbuf);
    if(strcmp(".", pent->d_name) == 0 || strcmp("..", pent->d_name) == 0) continue;

    if(S_ISDIR(statbuf.st_mode)) {
    chdir(pent->d_name);
    found = SearchDirectory();
    chdir("..");
    }
    else if(!(S_ISDIR(statbuf.st_mode))) {
    getcwd(path, EFS_MAXPATHLEN-1);
    strcat(path, pent->d_name);

    if(CheckFile(path, true)) {
    found = true;
    break;
    }
    }
    }
    closedir(pdir);

    return found;
    }

    Now, it works succesfully with devKitARM R25 and my Supercard ๐Ÿ™‚

    Reply
    • 7. Yannick Effinger  |  May 11, 2009 at 12:09 pm

      just for completing my previous post :
      I forgot to mention that the SearchDirectory() function can be found in “efs_lib.c” ๐Ÿ˜‰

      Reply
  • 8. Noda  |  May 12, 2009 at 10:57 am

    Thanks for your patch, it may be helpful since I don’t update EFS anymore ๐Ÿ˜‰

    Reply
  • 9. iBite  |  October 9, 2009 at 7:54 pm

    [latest 2.0 release]
    efs_lib.c:121: warning: initialization from incompatible pointer type
    efs_lib.c:122: warning: initialization from incompatible pointer type
    efs_lib.c:123: warning: initialization from incompatible pointer type
    efs_lib.c:551: warning: array subscript is above array bounds

    Reply
  • 10. Shane Gowda  |  October 14, 2009 at 12:48 pm

    Hello,

    Greetings of the day!!

    I have a couple of questions on the EFSL source code related to FAT16 File system.

    Appreciate if you could provide me the answers.

    I downloaded the code[EFSLv2.0] from the sourceforge web site and was able to build the library in a PC (Windows/DOS) environment. I would like to test this on the DOS environment by using a file as a device. I think this is possible on linux. Is this possible on the DOS/Windows?how?

    I did not find any code that needs to be called to initialise a file system when a new device is inserted โ€“ something like a format for a file system. Isnโ€™t this needed for an uninitialised device? Could you throw light on how to do this?

    Many thanks

    SHANE GOWDA R

    Reply
  • 11. best_guitar  |  November 22, 2009 at 7:21 pm

    Hello Noda, I’m using EFS v2.0 for devkitARM r26. My game works over no$gba, (I haven’t got nds) but some people with a M3 DS real firmware 4.6beta card or a DSTT card cannot run it. Which can be the problem? In the url you can check this problem.
    Many Thanks

    Reply
  • 12. BlackPawn  |  February 5, 2010 at 4:39 pm

    Hi,
    I was just having troubles with DSWiki which uses EFSlib and tracked it down to a conflict between my slot1 card and a slot2 3n1 cart. Turns out its a known bug.

    If you’re not very active with dev these days, do you feel amenable to making it a sourceforge or GoogleCode project and opening it up to other people?

    Reply
  • 13. Enrique Ramos  |  October 12, 2010 at 10:22 am

    Thanks for updating EFS, Iยดm using it since I began programing the nds.
    Can I use it with devkitpro 31 (latest so far) without needing Homebrew menu to launch it???
    Thanks
    Enrique

    Reply
  • 14. PypeBros  |  December 17, 2010 at 10:41 pm

    --- source/efs_lib.c (revision 763)
    +++ source/efs_lib.c (working copy)
    @@ -434,11 +434,13 @@
    {
    DIR_ITER *dir;
    bool found = false;
    - char path[EFS_MAXPATHLEN];
    - char filename[EFS_MAXPATHLEN];
    + static char path[EFS_MAXPATHLEN]; // since there ins't use of these vars accross searchDirectory
    + static char filename[EFS_MAXPATHLEN];// calls, we can make them static and avoid repeating them on stack.
    struct stat st;

    - dir = diropen(".");
    + /** diropen now makes call to GetDeviceOpTab ... which behaviour is sealed in devkitArm .. */
    + dir = diropen("fat1:.");
    + iprintf("@%p",dir);
    while((dirnext(dir, filename, &st) == 0) && (!found))
    {
    if(st.st_mode & S_IFDIR)

    turned out to be helpful with devkitpro-r32 (well, libfat 1.0.7 + libnds 1.4.8)

    Reply
  • 15. info  |  November 24, 2011 at 8:11 am

    I am really keen of reading articles or reviews concerning building up new blog, or even regarding Web optimization.

    Reply
  • 16. Anonymous  |  February 20, 2012 at 11:44 am

    Hello there, just became aware of your blog through Google, and found that it’s really informative. I am going to watch out for brussels. I will be grateful if you continue this in future. Numerous people will be benefited from your writing. Cheers!

    Reply

Leave a comment

Trackback this post  |  Subscribe to the comments via RSS Feed