Any way to include resources inside 3ds, 3dsx or CIA files?

Discussion in '3DS - Homebrew Development and Emulators' started by cebolleto, Apr 27, 2015.

  1. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
    So right now the only way I've seen on the 3ds to include the resources inside a binary is to turn then into arrays (using bin2cpp or similars). This has several problems like taking a lot of memory and being hard to maintain as the project grows

    The current solution seems to be placing the files into a folder on the SD and then read from there. That's better and seems to work perfect for .3dsx (because the 3dsx must be placed in a specific directory for the homebrew launcher to list it). But for .3ds and .cias it is very annoying having to copy some files to the SD and the install the game from the microSD (on the gateway)

    Isn't there anything like nitrofs for the DS?

    Or just the address to place the resource file system will be enought (we could use zlib for example to read from a zip file)
     


  2. Technicmaster0

    Technicmaster0 GBAtemp Addict

    Member
    2,998
    603
    Oct 22, 2011
    Gambia, The
    Well, you can transfer the files with FTBrony to the SD.
     
  3. AtlanticBit

    AtlanticBit Yeh, fuck this

    Member
    365
    189
    Jan 15, 2015
    Poland
    DEEP IN SPACE
    Most apps enclose their stuff in romfs. I have no idea how it works tho. Read some official SDK docs(I'm looking for romfs in them now).
     
    Margen67 likes this.
  4. Cyan

    Cyan GBATemp's lurking knight

    Global Moderator
    17,651
    8,240
    Oct 27, 2002
    France
    Engine room, learning
    I've read there's a way to append data at the end of the .3ds file.
    You pack all your resources in zip and append it to the executable.

    I just don't know how you access them from the sources.
    You should ask in the main/stickied 3DS Homebrew development thread.
     
    Margen67 likes this.
  5. AtlanticBit

    AtlanticBit Yeh, fuck this

    Member
    365
    189
    Jan 15, 2015
    Poland
    DEEP IN SPACE
    i have a file called zeroes.bin with just zeroes so i append my stuff like 3dsx+zeroes+rsrc1.jpg+zeroes+stuff.lua
     
    Margen67 likes this.
  6. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
    What do you do with the zeroes file?

    Someone here appends a zip file at the end of the 3ds
    http://4dsdev.org/thread.php?pid=79
    problem is, how do I get the address of the zip file... and isn't that loaded into memory?
     
  7. AtlanticBit

    AtlanticBit Yeh, fuck this

    Member
    365
    189
    Jan 15, 2015
    Poland
    DEEP IN SPACE
    append
     
  8. The Real Jdbye

    The Real Jdbye Always Remember 30/07/08

    Member
    GBAtemp Patron
    The Real Jdbye is a Patron of GBAtemp and is helping us stay independent!

    Our Patreon
    11,440
    4,753
    Mar 17, 2010
    Norway
    Alola
    The easy way is to append the zip file, then append the size of the zip file. That way you can simply seek to the end, read the int containing the size, then seek back that number of bytes + 4 for the int.
    No it obviously doesn't load the entire ROM into memory :P ROMs are normally much larger than the RAM of the 3DS can hold.
    The best solution would be using RomFS, they can be generated but I don't know if there's anything in ctrulib to read them.
     
    Cyan likes this.
  9. Technicmaster0

    Technicmaster0 GBAtemp Addict

    Member
    2,998
    603
    Oct 22, 2011
    Gambia, The
    I think that the problem is that makerom doesn't handle ROMFS properly.
     
  10. AtlanticBit

    AtlanticBit Yeh, fuck this

    Member
    365
    189
    Jan 15, 2015
    Poland
    DEEP IN SPACE
    it does: everytime you make a game cia region free or fw spoof it you use makerom to rebuild the whole game(and ROMFS)
     
  11. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
    The problem is that the 3ds is placed inside the micro SD on the Flashcard. I don't know if there is a way to access it so I can search for the .3ds that has been loaded and then locate the .zip inside.
    But the approach you are suggesting is interesting.
     
  12. The Real Jdbye

    The Real Jdbye Always Remember 30/07/08

    Member
    GBAtemp Patron
    The Real Jdbye is a Patron of GBAtemp and is helping us stay independent!

    Our Patreon
    11,440
    4,753
    Mar 17, 2010
    Norway
    Alola
    Yeah, you're right, that might be a problem. I didn't think of that.

    There's definitely a way, since the 3DS loads the game as normal, not sure if it can be read like a regular cartridge though but it's worth a try.
    Edit: SaveDataFiler seems able to read the cart like normal (apart from saves) so I think that should work.
     
  13. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
    So, after reading the documentation here http://3dbrew.org/wiki/FS:OpenFile I found that actually the functions for accessing the romfs are already implemented on libctru (services/fs.h)
    I have created a very simple romfs with 3 files just to see if I can get access to it ( I have tried using -romfs with makerom and also using the field HostRoot inside the .rsf)
    The code is very simple:

    Code:
    void romfsTest()
    {
        FS_archive romfsArchive    = { ARCH_ROMFS, { PATH_EMPTY, 1, (u8*)"" } };
     
        Result rc = 0;
        rc = FSUSER_OpenArchive(NULL, &romfsArchive);
        if(rc == 0) {
            Handle fd;
            FS_path fs_path = { PATH_BINARY, 20, (u8*)"00000000000000000000" };
            rc = FSUSER_OpenFileDirectly(NULL, &fd, romfsArchive, fs_path, FS_OPEN_READ, FS_ATTRIBUTE_READONLY);
            if(rc == 0) {
                char data[1024];
                u32 bytesRead;
                rc = FSFILE_Read(fd, &bytesRead, 0, (u32*)data, (u32)1024);
                if(rc == 0) {
                    printf("Data read:\n");
                    printf("%s\n", data);
                } else {
                    printf("FSFILE_Read failed(%x)\n", (int)rc);
                }
            } else {
                printf("FSUSER_OpenFile failed(%x)\n", (int)rc);
            }
        } else {
            printf("FSUSER_OpenArchive failed(%x)\n", (int)rc);
        }
    }

    But no matter what I try I am always getting 0xE0E046BE (EINVAL) when FSUSER_OpenFileDirectly is called
    Could anyone give me a hand here? If we can make this work we could even implement a devoptab for romfs and access it using stdio functions
     
  14. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    762
    284
    Jul 28, 2008
    United States
    PATH_BINARY looks wrong. Shouldn't it be PATH_CHAR with a length of 21?
     
  15. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
  16. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    762
    284
    Jul 28, 2008
    United States
  17. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
    What is the difference?
    Code:
    u8        file_binary_lowpath[20]  = {};
        FS_path    romfs_path              = { PATH_BINARY, 20, file_binary_lowpath };
     
  18. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    762
    284
    Jul 28, 2008
    United States
    For one file_binary_lowpath in your code is filled with ascii 0 chars rather than an empty string.
     
  19. cebolleto
    OP

    cebolleto GBAtemp Regular

    Member
    148
    206
    Mar 5, 2010
  20. elhobbs

    elhobbs GBAtemp Advanced Fan

    Member
    762
    284
    Jul 28, 2008
    United States
    Also romfsArchive is very different your code and does not appear to specify a file name.