gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Adding a file system? (newlib devoptab)

#107430 - tepples - Sun Oct 29, 2006 4:51 pm

I would like to add GBFS support to devkitARM's implementation of stdio in the same way that Chishm added libfat, in order to provide another way to make no-FAT builds of homebrew apps such as beup without having to change the app's code. What does it take to add a new file system? One would need to implement open(), read(), write() and close(), and somehow register it with newlib. What else? Where should I look for details?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.


Last edited by tepples on Mon Mar 19, 2007 11:36 pm; edited 1 time in total

#107451 - Payk - Sun Oct 29, 2006 7:41 pm

Well there is a simpleway which gpf showed me...
you can first include stdio.h
then undef each stdio command...
and define new ones...

Little example:

Code:

#include <stdio.h>

#undef FILE
#define FILE FAT_FILE

#undef fopen
#define fopen FAT_fopen


Be sure to make that with all fileacces-commands and take care wintermute doesnt see that...

Anotherhing....if u want to use gba-romspace with stido functions:
Try RomdiskFS (by GPF)

if u need a clever method to simply use that system on codes which already exist:
write a file and call it sdt.h

add following code to be able to switch between fat and romdsikfs(kosfs):

Code:

//#define FAT

#include <stdio.h>
#include <nds.h>

//KOS Filesystem
#ifndef FAT
   #include <stdlib.h>
   #include "kos/kos/kosstdio.h"
   #include "kos/kos/fs_romdisk.h"
#endif

#ifdef FAT
   #include <stdlib.h>
   #include "FAT/gba_nds_fat.h"
   
   #define FAT_FILE KOS_FILE
   #define FAT_fopen KOS_fopen
   #define FAT_fwrite KOS_fwrite
   #define FAT_fread KOS_fread
   #define FAT_fclose KOS_fclose
   #define FAT_fseek KOS_fseek
   #define FAT_fputs KOS_fputs
   #define FAT_fgets KOS_fgets
   #define FAT_fputc KOS_fputc
   #define FAT_getc KOS_getc
   #define FAT_putc KOS_putc
   #define FAT_fgetc KOS_fgetc
   #define FAT_fprintf KOS_fprintf
   #define FAT_vfprintf KOS_fprintf
   #define FAT_ftell KOS_ftell
   #define FAT_tmpfile KOS_tmpfile
   //#define FAT_rewind KOS_rewind
   #define FAT_feof KOS_feof
   #define FAT_stdin KOS_stdin
   #define FAT_stdout KOS_stdout
   #define FAT_fscanf KOS_fscanf
   #define FAT_fflush KOS_fflush
#endif


But both systems need to be initialzied one a different way....
i recommand to write a stdio.c!
Code:

#include "sdt.h"

void InitFS(void){
#ifndef FAT
      REG_IME=0;   
      sysSetCartOwner( BUS_OWNER_ARM9 );
      fs_init();
      fs_romdisk_mount("/rd", (uint8*)find_first_romfs_file((uint8*)0x08000000), 0);
#endif
#ifdef FAT
      swiWaitForVBlank();
      swiWaitForVBlank();
      FAT_InitFiles();
      swiWaitForVBlank();
      swiWaitForVBlank();
#endif
}



So if all that was done correctly u call InitFS(void) and u can use the right filesystem...if you are realy lazzy u can #undef FAT_InitFiles and #define InitFS(void) FAT_InitFiles...

#107477 - chishm - Mon Oct 30, 2006 12:16 am

Payk wrote:
Well there is a simpleway which gpf showed me...
you can first include stdio.h
then undef each stdio command...
and define new ones...

Eww, I feel dirty.

The proper way is to create all the required functions, then place pointers to them in a struct, then register this with the underlying calling stubs. Look in <sys/iosupport.h> for the required struct and functions.
_________________
http://chishm.drunkencoders.com
http://dldi.drunkencoders.com

#107486 - tepples - Mon Oct 30, 2006 2:33 am

Chishm's answer is what I was looking for so far. But what is each function specified to do, and what does each argument mean? Specifically:
Code:
   int (*open_r)(struct _reent *r, void *fileStruct, const char *path,int flags,int mode);

What is struct _reent *r, and what is void *fileStruct?

Code:
   int (*link_r)(struct _reent *r,const char *existing, const char  *new);

Isn't 'new' an operator in C++? Or must all file system drivers be written in the C language?

And what are the semantics of each errno value under newlib; specifically, how do they differ from common implementations of POSIX file I/O? For instance, Linux's open() distinguishes EMFILE (this process has opened the maximum number of files for one process) from ENFILE (all processes put together have opened the maximum number of files for one computer).
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#107496 - chishm - Mon Oct 30, 2006 7:16 am

tepples wrote:
Code:
   int (*open_r)(struct _reent *r, void *fileStruct, const char *path,int flags,int mode);

What is struct _reent *r, and what is void *fileStruct?

struct _reent *r is used for re-entrancy. It is defined in <sys/reent.h>. It is used in place of normally global variables, like errno. In fact, you'll really only need it for errno, which is accessed as r->_errno. To user code, these variables are still globals (unless re-entrancy is defined when compiling the tool chain).

void *fileStruct is memory allocated by the calling stub to be used by your filesystem I/O driver for storing the state of the openned file. This is so you don't need to use malloc. The size of the memory allocated is defined by int structSize; in the devoptab struct passed to AddDevice. A pointer to the memory allocated is passed to the other file functions (read, write, close) but cast to an integer (int fd). Cast fd to a pointer to your file struct to access it normally.

Quote:
Code:
   int (*link_r)(struct _reent *r,const char *existing, const char  *new);

Isn't 'new' an operator in C++? Or must all file system drivers be written in the C language?

Yes it is. This is a problem with libc and needs to be fixed in DevkitPro. That being said, all these are function pointers and you'll need to make sure the functions are compiled with the correct number of arguments (eg, no this pointer as the first argument).

Quote:
And what are the semantics of each errno value under newlib; specifically, how do they differ from common implementations of POSIX file I/O? For instance, Linux's open() distinguishes EMFILE (this process has opened the maximum number of files for one process) from ENFILE (all processes put together have opened the maximum number of files for one computer).

All errno values are defined in <sys/errno.h> There are still separate ENFILE and EMFILE values, but use your judgement in choosing the correct one.
_________________
http://chishm.drunkencoders.com
http://dldi.drunkencoders.com

#122518 - Puyo - Mon Mar 19, 2007 10:57 pm

Sorry to bump old topic, but i thought it`s kind of related. It`s about devoptab.
I`m adding functions to it as i create them. Now i`m adding ftell and I couldn`t find this function in devoptab. I was sure that fstat_r is called to fill stat structure (st->st_size?) at that moment, but it`s not. The same with stat_r. So what actually happens? And where should i add this thing?

#122547 - wintermute - Tue Mar 20, 2007 4:40 am

ftell is implemented using seek
_________________
devkitPro - professional toolchains at amateur prices
devkitPro IRC support
Personal Blog

#122590 - sirpoonga - Tue Mar 20, 2007 4:01 pm

tepples, that's a neat idea. However, you can do that with fcsr and dldi if you want too.

#122598 - tepples - Tue Mar 20, 2007 5:12 pm

sirpoonga wrote:
tepples, that's a neat idea. However, you can do that with fcsr and dldi if you want too.

How easy are the FCSR tools to use on the Microsoft Windows operating system?
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#122607 - sirpoonga - Tue Mar 20, 2007 5:32 pm

Check out this thread
http://forum.gbadev.org/viewtopic.php?t=12654%3C/blockquote%3E%3C/div%3E

As for using it, it's pretty simple. Put your files in a folder. Use the the fcsr tool to make the .img file. pad and cat the nds program with the img file. Apply dldi.

I have been using this to test my ds motion maze game. The maze is a text file.