summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arm9/Makefile3
-rw-r--r--arm9/asm/FS_file.s448
-rw-r--r--arm9/lib/include/FS_archive.h23
-rw-r--r--arm9/lib/include/FS_file.h19
-rw-r--r--arm9/lib/include/FS_rom.h6
-rw-r--r--arm9/lib/include/MI_byteAccess.h9
-rw-r--r--arm9/lib/include/OS_thread.h6
-rw-r--r--arm9/lib/src/FS_file.c258
-rw-r--r--arm9/undefined_syms.txt2
9 files changed, 323 insertions, 451 deletions
diff --git a/arm9/Makefile b/arm9/Makefile
index aa41512d..bef45759 100644
--- a/arm9/Makefile
+++ b/arm9/Makefile
@@ -91,7 +91,7 @@ OBJCOPY := $(CROSS)objcopy
# ./tools/mwccarm/2.0/base/mwasmarm.exe -proc arm5te asm/arm9_thumb.s -o arm9.o
ASFLAGS = -proc arm5te -i ..
-CFLAGS = -O4,p -proc arm946e -fp soft -lang c99 -Cpp_exceptions off -ir ../include -ir ../include-mw -ir lib/include -interworking
+CFLAGS = -O4,p -proc arm946e -fp soft -lang c99 -Cpp_exceptions off -ir ../include -ir ../include-mw -ir lib/include -interworking -DFS_IMPLEMENT
LDFLAGS = -map -nodead -w off -proc v5te -interworking -map -symtab -m _start
####################### Other Tools #########################
@@ -150,6 +150,7 @@ ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS))
# TODO: Move out to lib/Makefile
build/lib/src/%.o: MWCCVERSION = 1.2/sp2p3
+build/lib/src/%.o: CFLAGS += -enum int
build/src/FUN_020910A4.o: MWCCVERSION = 1.2/sp2p3
####################### Everything Else ######################
diff --git a/arm9/asm/FS_file.s b/arm9/asm/FS_file.s
deleted file mode 100644
index daec0913..00000000
--- a/arm9/asm/FS_file.s
+++ /dev/null
@@ -1,448 +0,0 @@
- .include "asm/macros.inc"
- .include "global.inc"
- .section .text
-
- arm_func_start FS_ChangeDir
-FS_ChangeDir: ; 0x020D174C
- stmdb sp!, {r4,lr}
- sub sp, sp, #0x58
- mov r4, r0
- add r0, sp, #0xc
- bl FS_InitFile
- add r0, sp, #0xc
- add r3, sp, #0x0
- mov r1, r4
- mov r2, #0x0
- bl FSi_FindPath
-_020D1774:
- cmp r0, #0x0
- moveq r0, #0x0
- addne r0, sp, #0x0
- ldrne r3, _020D179C
- ldmneia r0, {r0, r1, r2}
- stmneia r3, {r0, r1, r2}
- movne r0, #0x1
- add sp, sp, #0x58
- ldmia sp!, {r4, lr}
- bx lr
-_020D179C: .word 0x021D53EC
-
- arm_func_start FS_SeekFile
-FS_SeekFile: ; 0x020D17A0
- cmp r2, #0x0
- beq _020D17BC
- cmp r2, #0x1
- beq _020D17C8
- cmp r2, #0x2
- beq _020D17D4
- b _020D17E0
-_020D17BC:
- ldr r2, [r0, #0x24]
- add r1, r1, r2
- b _020D17E8
-_020D17C8:
- ldr r2, [r0, #0x2c]
- add r1, r1, r2
- b _020D17E8
-_020D17D4:
- ldr r2, [r0, #0x28]
- add r1, r1, r2
- b _020D17E8
-_020D17E0:
- mov r0, #0x0
- bx lr
-_020D17E8:
- ldr r2, [r0, #0x24]
- cmp r1, r2
- movlt r1, r2
- ldr r2, [r0, #0x28]
- cmp r1, r2
- movgt r1, r2
- str r1, [r0, #0x2c]
- mov r0, #0x1
- bx lr
-
- arm_func_start FS_ReadFile
-FS_ReadFile: ; 0x020D180C
- ldr ip, _020D1818 ; =FUN_020D1AAC
- mov r3, #0x0
- bx r12
- .balign 4
-_020D1818: .word FUN_020D1AAC
-
- arm_func_start FS_ReadFileAsync
-FS_ReadFileAsync: ; 0x020D181C
- ldr ip, _020D1828 ; =FUN_020D1AAC
- mov r3, #0x1
- bx r12
- .balign 4
-_020D1828: .word FUN_020D1AAC
-
- arm_func_start FS_WaitAsync
-FS_WaitAsync: ; 0x020D182C
- stmdb sp!, {r4-r7,lr}
- sub sp, sp, #0x4
- mov r6, r0
- mov r5, #0x0
- bl OS_DisableInterrupts
- ldr r1, [r6, #0xc]
- mov r4, r0
- ands r0, r1, #0x1
- movne r0, #0x1
- moveq r0, r5
- cmp r0, #0x0
- beq _020D18BC
- ldr r0, [r6, #0xc]
- ands r0, r0, #0x44
- moveq r5, #0x1
- movne r5, #0x0
- cmp r5, #0x0
- beq _020D189C
- ldr r0, [r6, #0xc]
- orr r0, r0, #0x4
- str r0, [r6, #0xc]
- add r7, r6, #0x18
-_020D1884:
- mov r0, r7
- bl OS_SleepThread
- ldr r0, [r6, #0xc]
- ands r0, r0, #0x40
- beq _020D1884
- b _020D18BC
-_020D189C:
- add r0, r6, #0x18
- bl OS_SleepThread
- ldr r0, [r6, #0xc]
- ands r0, r0, #0x1
- movne r0, #0x1
- moveq r0, #0x0
- cmp r0, #0x0
- bne _020D189C
-_020D18BC:
- mov r0, r4
- bl OS_RestoreInterrupts
-_020D18C4:
- cmp r5, #0x0
- beq _020D18E0
- mov r0, r6
- bl FSi_ExecuteSyncCommand
- add sp, sp, #4
- ldmia sp!, {r4-r7,lr}
- bx lr
-_020D18E0:
- ldr r0, [r6, #0x14]
- cmp r0, #0x0
- moveq r0, #0x1
- movne r0, #0x0
- add sp, sp, #0x4
- ldmia sp!, {r4-r7,lr}
- bx lr
-
- arm_func_start FS_CloseFile
-FS_CloseFile: ; 0x020D18FC
- stmdb sp!, {r4,lr}
- mov r1, #0x8
- mov r4, r0
- bl FSi_SendCommand
-_020D190C:
- cmp r0, #0x0
- moveq r0, #0x0
- ldmeqia sp!, {r4,lr}
- bxeq lr
- mov r0, #0x0
- str r0, [r4, #0x8]
- mov r0, #0xE
- str r0, [r4, #0x10]
- ldr r1, [r4, #0xC]
- mov r0, #0x1
- bic r1, r1, #0x30
- str r1, [r4, #0xC]
- ldmia sp!, {r4,lr}
- bx lr
-
- arm_func_start FS_OpenFile
-FS_OpenFile: ; 0x020D1944
- stmdb sp!, {r4,lr}
- sub sp, sp, #0x8
- mov r4, r0
- add r0, sp, #0x0
- bl FS_ConvertPathToFileID
-_020D1958:
- cmp r0, #0x0
- beq _020D1984
- add r1, sp, #0x0
- mov r0, r4
- ldmia r1, {r1, r2}
- bl FS_OpenFileFast
- cmp r0, #0x0
- addne sp, sp, #0x8
- movne r0, #0x1
- ldmneia sp!, {r4, lr}
- bxne lr
-_020D1984:
- mov r0, #0x0
- add sp, sp, #0x8
- ldmia sp!, {r4, lr}
- bx lr
-
- arm_func_start FS_OpenFileFast
-FS_OpenFileFast:
- stmdb sp!, {r0-r3}
- stmdb sp!, {r4,lr}
- ldr r1, [sp, #0xc]
- mov r4, r0
- cmp r1, #0x0
- moveq r0, #0x0
- ldmeqia sp!, {r4,lr}
- addeq sp, sp, #0x10
- bxeq lr
- str r1, [r4, #0x8]
- ldr r3, [sp, #0xc]
- ldr r2, [sp, #0x10]
- mov r1, #0x6
- str r3, [r4, #0x30]
- str r2, [r4, #0x34]
- bl FSi_SendCommand
-_020D19D4:
- cmp r0, #0x0
- moveq r0, #0x0
- ldmeqia sp!, {r4, lr}
- addeq sp, sp, #0x10
- bxeq lr
- ldr r1, [r4, #0xC]
- mov r0, #0x1
- orr r1, r1, #0x10
- str r1, [r4, #0xC]
- ldr r1, [r4, #0xC]
- bic r1, r1, #0x20
- str r1, [r4, #0xC]
- ldmia sp!, {r4, lr}
- add sp, sp, #0x10
- bx lr
-
- arm_func_start FS_OpenFileDirect
-FS_OpenFileDirect:
- stmdb sp!, {r4,lr}
- mov r4, r0
- str r1, [r4, #0x8]
- ldr r12, [sp, #0x8]
- mov r1, #0x7
- str r12, [r4, #0x38]
- str r2, [r4, #0x30]
- str r3, [r4, #0x34]
- bl FSi_SendCommand
-_020D1A34:
- cmp r0, #0x0
- moveq r0, #0x0
- ldmeqia sp!, {r4, lr}
- bxeq lr
- ldr r1, [r4, #0xC]
- mov r0, #0x1
- orr r1, r1, #0x10
- str r1, [r4, #0xC]
- ldr r1, [r4, #0xC]
- bic r1, r1, #0x20
- str r1, [r4, #0xC]
- ldmia sp!, {r4, lr}
- bx lr
-
- arm_func_start FS_ConvertPathToFileID
-FS_ConvertPathToFileID:
- stmdb sp!, {r4-r5,lr}
- sub sp, sp, #0x4c
- mov r5, r0
- add r0, sp, #0x0
- mov r4, r1
- bl FS_InitFile
-_020D1A80:
- add r0, sp, #0x0
- mov r1, r4
- mov r2, r5
- mov r3, #0x0
- bl FSi_FindPath
- cmp r0, #0x0
- movne r0, #0x1
- moveq r0, #0x0
- add sp, sp, #0x4C
- ldmia sp!, {r4-r5, lr}
- bx lr
-
- arm_func_start FUN_020D1AAC
-FUN_020D1AAC: ; 0x020D1AAC
- stmdb sp!, {r4-r7,lr}
- sub sp, sp, #0x4
- mov r7, r0
- ldr r4, [r7, #0x2c]
- ldr r0, [r7, #0x28]
- mov r6, r2
- str r1, [r7, #0x30]
- sub r0, r0, r4
- cmp r6, r0
- movgt r6, r0
- cmp r6, #0x0
- movlt r6, #0x0
- str r2, [r7, #0x34]
- mov r5, r3
- str r6, [r7, #0x38]
- cmp r5, #0x0
- ldreq r0, [r7, #0xc]
- mov r1, #0x0
- orreq r0, r0, #0x4
- streq r0, [r7, #0xc]
- mov r0, r7
- bl FSi_SendCommand
-_020D1B04:
- cmp r5, #0x0
- bne _020D1B24
- mov r0, r7
- bl FS_WaitAsync
- cmp r0, #0x0
- ldrne r0, [r7, #0x2C]
- subne r6, r0, r4
- mvneq r6, #0x0
-_020D1B24:
- mov r0, r6
- add sp, sp, #0x4
- ldmia sp!, {r4-r7, lr}
- bx lr
-
- arm_func_start FSi_FindPath
-FSi_FindPath:
- stmdb sp!, {r4-r8,lr}
- sub sp, sp, #0x10
- mov r7, r1
- ldrb r1, [r7, #0x0]
- mov r8, r0
- mov r6, r2
- mov r5, r3
- cmp r1, #0x2f
- beq _020D1B60
- cmp r1, #0x5c
- bne _020D1B84
-_020D1B60:
- ldr r0, _020D1C90 ; =0x021D53EC
- mov r1, #0x0
- ldr r0, [r0, #0x0]
- strh r1, [sp, #0x4]
- str r0, [sp, #0x0]
- str r1, [sp, #0x8]
- strh r1, [sp, #0x6]
- add r7, r7, #0x1
- b _020D1C40
-_020D1B84:
- ldr r0, _020D1C90 ; =0x021D53EC
- add r3, sp, #0x0
- ldmia r0, {r0-r2}
- stmia r3, {r0-r2}
- mov r4, #0x0
-_020D1B98:
- ldrb r0, [r7, r4]
- cmp r0, #0x0
- beq _020D1C40
- cmp r0, #0x2f
- beq _020D1C40
- cmp r0, #0x5c
- beq _020D1C40
- cmp r0, #0x3a
- bne _020D1C34
- mov r0, r7
- mov r1, r4
- bl FS_FindArchive
-_020D1BC8:
- cmp r0, #0x0
- addeq sp, sp, #0x10
- moveq r0, #0x0
- ldmeqia sp!, {r4-r8,lr}
- bxeq lr
- ldr r1, [r0, #0x1C]
- ands r1, r1, #0x2
- movne r1, #0x1
- moveq r1, #0x0
- cmp r1, #0x0
- addeq sp, sp, #0x10
- moveq r0, #0x0
- ldmeqia sp!, {r4-r8,lr}
- bxeq lr
- mov r1, #0x0
- str r0, [sp]
- str r1, [sp, #0x8]
- strh r1, [sp, #0x6]
- strh r1, [sp, #0x4]
- add r0, r4, #0x1
- ldrb r0, [r7, r0]!
- cmp r0, #0x2f
- beq _020D1C2C
- cmp r0, #0x5c
- bne _020D1C40
-_020D1C2C:
- add r7, r7, #0x1
- b _020D1C40
-_020D1C34:
- add r4, r4, #0x1
- cmp r4, #0x3
- ble _020D1B98
-_020D1C40:
- ldr r1, [sp, #0x0]
- add r0, sp, #0x0
- str r1, [r8, #0x8]
- str r7, [r8, #0x3c]
- add r3, r8, #0x30
- ldmia r0, {r0-r2}
- stmia r3, {r0-r2}
- cmp r5, #0x0
- movne r0, #0x1
- strne r0, [r8, #0x40]
- strne r5, [r8, #0x44]
- moveq r0, #0x0
- streq r0, [r8, #0x40]
- mov r0, r8
- mov r1, #0x4
- streq r6, [r8, #0x44]
- bl FSi_SendCommand
- add sp, sp, #0x10
- ldmia sp!, {r4-r8,lr}
- bx lr
- .balign 4
-_020D1C90: .word 0x021D53EC
-
- arm_func_start FS_InitFile
-FS_InitFile:
- mov r3, #0x0
- str r3, [r0, #0x0]
- ldr r2, [r0, #0x0]
- mov r1, #0xe
- str r2, [r0, #0x4]
- str r3, [r0, #0x1c]
- ldr r2, [r0, #0x1c]
- str r2, [r0, #0x18]
- str r3, [r0, #0x8]
- str r1, [r0, #0x10]
- str r3, [r0, #0xc]
- bx lr
-
- arm_func_start FS_IsAvailable
-FS_IsAvailable: ; 0x020D1CC4
- ldr r0, _020D1CD0 ; =0x021D53F8
- ldr r0, [r0, #0x0]
- bx lr
- .balign 4
-_020D1CD0: .word 0x021D53F8
-
- arm_func_start FS_Init
-FS_Init: ; 0x020D1CD4
- stmdb sp!, {lr}
- sub sp, sp, #0x4
- ldr r1, _020D1D0C ; =0x021D53F8
- ldr r2, [r1, #0x0]
- cmp r2, #0x0
- addne sp, sp, #0x4
- ldmneia sp!, {lr}
- bxne lr
- mov r2, #0x1
- str r2, [r1, #0x0]
- bl FSi_InitRom
- add sp, sp, #0x4
- ldmia sp!, {lr}
- bx lr
- .balign 4
-_020D1D0C: .word 0x021D53F8
diff --git a/arm9/lib/include/FS_archive.h b/arm9/lib/include/FS_archive.h
index 65bb2ea1..66840b32 100644
--- a/arm9/lib/include/FS_archive.h
+++ b/arm9/lib/include/FS_archive.h
@@ -8,6 +8,19 @@
struct FSFile;
struct FSArchive;
+#define FS_ARCHIVE_NAME_LEN_MAX 3
+
+#define FS_ARCHIVE_FLAG_REGISTER 0x00000001
+#define FS_ARCHIVE_FLAG_LOADED 0x00000002
+#define FS_ARCHIVE_FLAG_TABLE_LOAD 0x00000004
+#define FS_ARCHIVE_FLAG_SUSPEND 0x00000008
+#define FS_ARCHIVE_FLAG_RUNNING 0x00000010
+#define FS_ARCHIVE_FLAG_CANCELING 0x00000020
+#define FS_ARCHIVE_FLAG_SUSPENDING 0x00000040
+#define FS_ARCHIVE_FLAG_UNLOADING 0x00000080
+#define FS_ARCHIVE_FLAG_IS_ASYNC 0x00000100
+#define FS_ARCHIVE_FLAG_IS_SYNC 0x00000200
+
typedef enum {
FS_COMMAND_ASYNC_BEGIN = 0,
FS_COMMAND_READFILE = FS_COMMAND_ASYNC_BEGIN,
@@ -87,4 +100,14 @@ typedef struct FSArchive
u32 proc_flag;
} FSArchive;
+FSArchive * const FS_FindArchive(const char * path, int offset);
+
+static inline BOOL FS_IsArchiveLoaded(volatile const FSArchive * p_arc)
+{
+ return (p_arc->flag & FS_ARCHIVE_FLAG_LOADED) ? TRUE : FALSE;
+}
+
+BOOL FSi_SendCommand(struct FSFile * file, FSCommandType command);
+BOOL FSi_ExecuteSyncCommand(struct FSFile * file);
+
#endif //NITRO_FS_ARCHIVE_H_
diff --git a/arm9/lib/include/FS_file.h b/arm9/lib/include/FS_file.h
index 08a698d0..4871b660 100644
--- a/arm9/lib/include/FS_file.h
+++ b/arm9/lib/include/FS_file.h
@@ -5,6 +5,21 @@
#include "FS_archive.h"
+#define FS_FILE_STATUS_BUSY 0x00000001
+#define FS_FILE_STATUS_CANCEL 0x00000002
+#define FS_FILE_STATUS_SYNC 0x00000004
+#define FS_FILE_STATUS_ASYNC 0x00000008
+#define FS_FILE_STATUS_IS_FILE 0x00000010
+#define FS_FILE_STATUS_IS_DIR 0x00000020
+#define FS_FILE_STATUS_OPERATING 0x00000040
+
+typedef enum FSSeekFileMode
+{
+ FS_SEEK_SET = 0,
+ FS_SEEK_CUR,
+ FS_SEEK_END
+} FSSeekFileMode;
+
struct FSFile;
#define FS_DMA_NOT_USE ((u32)~0)
@@ -127,7 +142,6 @@ typedef struct FSFile
FSCommandType command;
FSResult error;
OSThreadQueue queue[1];
- u32 filler; // Figure out what this actually is
union {
struct
{
@@ -154,11 +168,12 @@ typedef struct FSFile
FSOpenFileFastInfo openfilefast;
FSOpenFileDirectInfo openfiledirect;
FSCloseFileInfo closefile;
- };
+ } arg;
}
FSFile;
u32 FS_SetDefaultDMA(u32 dma_no); // returns the previous selection
void FS_InitFile(FSFile * p_file);
+BOOL FS_WaitAsync(FSFile * p_file);
#endif //NITRO_FS_FILE_H_
diff --git a/arm9/lib/include/FS_rom.h b/arm9/lib/include/FS_rom.h
new file mode 100644
index 00000000..fc62b579
--- /dev/null
+++ b/arm9/lib/include/FS_rom.h
@@ -0,0 +1,6 @@
+#ifndef NITRO_FS_ROM_H_
+#define NITRO_FS_ROM_H_
+
+void FSi_InitRom(u32 default_dma_no);
+
+#endif //NITRO_FS_ROM_H_
diff --git a/arm9/lib/include/MI_byteAccess.h b/arm9/lib/include/MI_byteAccess.h
new file mode 100644
index 00000000..10dae4c9
--- /dev/null
+++ b/arm9/lib/include/MI_byteAccess.h
@@ -0,0 +1,9 @@
+#ifndef NITRO_MI_BYTEACCESS_H_
+#define NITRO_MI_BYTEACCESS_H_
+
+static inline u8 MI_ReadByte(const void *address)
+{
+ return *(u8 *)address;
+}
+
+#endif //NITRO_MI_BYTEACCESS_H_
diff --git a/arm9/lib/include/OS_thread.h b/arm9/lib/include/OS_thread.h
index 207dac1b..8820a7a0 100644
--- a/arm9/lib/include/OS_thread.h
+++ b/arm9/lib/include/OS_thread.h
@@ -28,4 +28,10 @@ struct _OSThread
u8 padding[0x80]; //todo: not the correct size but idfk
};
+void OS_SleepThread(OSThreadQueue * queue);
+static inline void OS_InitThreadQueue(OSThreadQueue * queue)
+{
+ queue->head = queue->tail = NULL;
+}
+
#endif //POKEDIAMOND_OS_THREAD_H
diff --git a/arm9/lib/src/FS_file.c b/arm9/lib/src/FS_file.c
new file mode 100644
index 00000000..8ca89af8
--- /dev/null
+++ b/arm9/lib/src/FS_file.c
@@ -0,0 +1,258 @@
+#include "nitro.h"
+#include "MI_byteAccess.h"
+#include "FS_rom.h"
+#include "FS_file.h"
+
+extern FSDirPos current_dir_pos;
+BOOL is_init = FALSE;
+
+static inline BOOL FSi_IsSlash(u32 c)
+{
+ return (c == '/') || (c == '\\');
+}
+
+static inline BOOL FS_IsBusy(volatile const FSFile * p_file)
+{
+ return p_file->stat & FS_FILE_STATUS_BUSY ? TRUE : FALSE;
+}
+
+static inline BOOL FS_IsSucceeded(volatile const FSFile * p_file)
+{
+ return p_file->error == FS_RESULT_SUCCESS ? TRUE : FALSE;
+}
+
+void FS_Init(u32 default_dma_no)
+{
+ if (!is_init)
+ {
+ is_init = TRUE;
+ FSi_InitRom(default_dma_no);
+ }
+}
+
+BOOL FS_IsAvailable(void)
+{
+ return is_init;
+}
+
+void FS_InitFile(FSFile * p_file)
+{
+ p_file->link.next = p_file->link.prev = NULL;
+ OS_InitThreadQueue(p_file->queue);
+ p_file->arc = NULL;
+ p_file->command = FS_COMMAND_INVALID;
+ p_file->stat = 0;
+}
+
+static BOOL FSi_FindPath(FSFile * p_dir, const char * path, FSFileID * p_file_id, FSDirPos * p_dir_pos)
+{
+ FSDirPos pos;
+ if (FSi_IsSlash(MI_ReadByte(path)))
+ {
+ pos.arc = current_dir_pos.arc;
+ pos.own_id = 0;
+ pos.pos = 0;
+ pos.index = 0;
+ path++;
+ }
+ else
+ {
+ int i;
+ pos = current_dir_pos;
+ for (i = 0; i <= FS_ARCHIVE_NAME_LEN_MAX; ++i)
+ {
+ u32 c = MI_ReadByte(path + i);
+ if (!c || FSi_IsSlash(c))
+ break;
+ else if (c == ':')
+ {
+ FSArchive * const p_arc = FS_FindArchive(path, i);
+ if (!p_arc)
+ {
+ return FALSE;
+ }
+ else if (!FS_IsArchiveLoaded(p_arc))
+ {
+ return FALSE;
+ }
+ pos.arc = p_arc;
+ pos.pos = 0;
+ pos.index = 0;
+ pos.own_id = 0;
+ path += i + 1;
+ if (FSi_IsSlash(MI_ReadByte(path)))
+ ++path;
+ break;
+ }
+ }
+ }
+ p_dir->arc = pos.arc;
+ p_dir->arg.findpath.path = path;
+ p_dir->arg.findpath.pos = pos;
+ if (p_dir_pos)
+ {
+ p_dir->arg.findpath.find_directory = TRUE;
+ p_dir->arg.findpath.result.dir = p_dir_pos;
+ }
+ else
+ {
+ p_dir->arg.findpath.find_directory = FALSE;
+ p_dir->arg.findpath.result.file = p_file_id;
+ }
+ return FSi_SendCommand(p_dir, FS_COMMAND_FINDPATH);
+}
+
+int FSi_ReadFileCore(FSFile * p_file, void * dst, s32 len, BOOL async)
+{
+ {
+ const s32 pos = (s32)p_file->prop.file.pos;
+ const s32 rest = (s32)p_file->prop.file.bottom - pos;
+ const u32 org = (u32)len;
+ if (len > rest)
+ len = rest;
+ if (len < 0)
+ len = 0;
+ p_file->arg.readfile.dst = dst;
+ p_file->arg.readfile.len_org = org;
+ p_file->arg.readfile.len = (u32)(len);
+ if (!async)
+ p_file->stat |= FS_FILE_STATUS_SYNC;
+ (void)FSi_SendCommand(p_file, FS_COMMAND_READFILE);
+ if (!async)
+ {
+ if (FS_WaitAsync(p_file))
+ len = (s32)p_file->prop.file.pos - pos;
+ else
+ len = -1;
+ }
+ }
+ return len;
+}
+
+BOOL FS_ConvertPathToFileID(FSFileID * p_file_id, const char * path)
+{
+ FSFile dir;
+ FS_InitFile(&dir);
+ if (!FSi_FindPath(&dir, path, p_file_id, NULL))
+ return FALSE;
+ return TRUE;
+}
+
+BOOL FS_OpenFileDirect(FSFile * p_file, FSArchive * p_arc, u32 image_top, u32 image_bottom, u32 file_index)
+{
+ p_file->arc = p_arc;
+ p_file->arg.openfiledirect.index = file_index;
+ p_file->arg.openfiledirect.top = image_top;
+ p_file->arg.openfiledirect.bottom = image_bottom;
+ if (!FSi_SendCommand(p_file, FS_COMMAND_OPENFILEDIRECT))
+ return FALSE;
+ p_file->stat |= FS_FILE_STATUS_IS_FILE;
+ p_file->stat &= ~FS_FILE_STATUS_IS_DIR;
+ return TRUE;
+}
+
+BOOL FS_OpenFileFast(FSFile * p_file, FSFileID file_id)
+{
+ if (!file_id.arc)
+ return FALSE;
+ p_file->arc = file_id.arc;
+ p_file->arg.openfilefast.id = file_id;
+ if (!FSi_SendCommand(p_file, FS_COMMAND_OPENFILEFAST))
+ return FALSE;
+ p_file->stat |= FS_FILE_STATUS_IS_FILE;
+ p_file->stat &= ~FS_FILE_STATUS_IS_DIR;
+ return TRUE;
+}
+
+BOOL FS_OpenFile(FSFile * p_file, const char * path)
+{
+ FSFileID file_id;
+ return FS_ConvertPathToFileID(&file_id, path) && FS_OpenFileFast(p_file, file_id);
+}
+
+BOOL FS_CloseFile(FSFile * p_file)
+{
+ if (!FSi_SendCommand(p_file, FS_COMMAND_CLOSEFILE))
+ return FALSE;
+ p_file->arc = NULL;
+ p_file->command = FS_COMMAND_INVALID;
+ p_file->stat &= ~(FS_FILE_STATUS_IS_FILE | FS_FILE_STATUS_IS_DIR);
+ return TRUE;
+}
+
+BOOL FS_WaitAsync(FSFile * p_file)
+{
+ BOOL is_owner = FALSE;
+ OSIntrMode bak_par = OS_DisableInterrupts();
+ if (FS_IsBusy(p_file))
+ {
+ is_owner = !(p_file->stat & (FS_FILE_STATUS_SYNC | FS_FILE_STATUS_OPERATING));
+ if (is_owner)
+ {
+ p_file->stat |= FS_FILE_STATUS_SYNC;
+ do
+ {
+ OS_SleepThread(p_file->queue);
+ } while (!(p_file->stat & FS_FILE_STATUS_OPERATING));
+ }
+ else
+ {
+ do
+ {
+ OS_SleepThread(p_file->queue);
+ } while (FS_IsBusy(p_file));
+ }
+ }
+ (void)OS_RestoreInterrupts(bak_par);
+ if (is_owner)
+ {
+ return FSi_ExecuteSyncCommand(p_file);
+ }
+
+ return FS_IsSucceeded(p_file);
+}
+
+int FS_ReadFileAsync(FSFile * p_file, void * dst, s32 len)
+{
+ return FSi_ReadFileCore(p_file, dst, len, TRUE);
+}
+
+int FS_ReadFile(FSFile * p_file, void * dst, s32 len)
+{
+ return FSi_ReadFileCore(p_file, dst, len, FALSE);
+}
+
+BOOL FS_SeekFile(FSFile * p_file, int offset, FSSeekFileMode origin)
+{
+ switch (origin)
+ {
+ case FS_SEEK_SET:
+ offset += p_file->prop.file.top;
+ break;
+ case FS_SEEK_CUR:
+ offset += p_file->prop.file.pos;
+ break;
+ case FS_SEEK_END:
+ offset += p_file->prop.file.bottom;
+ break;
+ default:
+ return FALSE;
+ }
+ if (offset < (s32)p_file->prop.file.top)
+ offset = (s32)p_file->prop.file.top;
+ if (offset > (s32)p_file->prop.file.bottom)
+ offset = (s32)p_file->prop.file.bottom;
+ p_file->prop.file.pos = offset;
+ return TRUE;
+}
+
+BOOL FS_ChangeDir(const char * path)
+{
+ FSDirPos pos;
+ FSFile dir;
+ FS_InitFile(&dir);
+ if (!FSi_FindPath(&dir, path, NULL, &pos))
+ return FALSE;
+ current_dir_pos = pos;
+ return TRUE;
+}
diff --git a/arm9/undefined_syms.txt b/arm9/undefined_syms.txt
index a2f736f8..0b159a51 100644
--- a/arm9/undefined_syms.txt
+++ b/arm9/undefined_syms.txt
@@ -25,6 +25,8 @@ gUnk021C8C70 = 0x021C8C70;
gLoadedOverlays = 0x021C45B0;
OSi_IrqCallbackInfo = 0x021D341C;
isInitialized = 0x021D347C;
+current_dir_pos = 0x021D53EC;
+is_init = 0x021D53F8;
OSi_StackForDestructor = 0x021D3480;
OSi_RescheduleCount = 0x021D3484;
OSi_ThreadIdCount = 0x021D3488;