summaryrefslogtreecommitdiff
path: root/arm9/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/lib')
-rw-r--r--arm9/lib/include/FS_archive.h56
-rw-r--r--arm9/lib/include/FS_command.h9
-rw-r--r--arm9/lib/include/FS_file.h20
-rw-r--r--arm9/lib/include/OS_thread.h1
-rw-r--r--arm9/lib/src/FS_archive.c147
-rw-r--r--arm9/lib/src/FS_file.c10
6 files changed, 233 insertions, 10 deletions
diff --git a/arm9/lib/include/FS_archive.h b/arm9/lib/include/FS_archive.h
index 66840b32..b39e7738 100644
--- a/arm9/lib/include/FS_archive.h
+++ b/arm9/lib/include/FS_archive.h
@@ -47,6 +47,37 @@ typedef enum {
FS_COMMAND_INVALID
} FSCommandType;
+/* Asynchronous commands*/
+#define FS_ARCHIVE_PROC_READFILE (1 << FS_COMMAND_READFILE)
+#define FS_ARCHIVE_PROC_WRITEFILE (1 << FS_COMMAND_WRITEFILE)
+/* All asynchronous commands*/
+#define FS_ARCHIVE_PROC_ASYNC \
+ (FS_ARCHIVE_PROC_READFILE | FS_ARCHIVE_PROC_WRITEFILE)
+
+/* Synchronous commands*/
+#define FS_ARCHIVE_PROC_SEEKDIR (1 << FS_COMMAND_SEEKDIR)
+#define FS_ARCHIVE_PROC_READDIR (1 << FS_COMMAND_READDIR)
+#define FS_ARCHIVE_PROC_FINDPATH (1 << FS_COMMAND_FINDPATH)
+#define FS_ARCHIVE_PROC_GETPATH (1 << FS_COMMAND_GETPATH)
+#define FS_ARCHIVE_PROC_OPENFILEFAST (1 << FS_COMMAND_OPENFILEFAST)
+#define FS_ARCHIVE_PROC_OPENFILEDIRECT (1 << FS_COMMAND_OPENFILEDIRECT)
+#define FS_ARCHIVE_PROC_CLOSEFILE (1 << FS_COMMAND_CLOSEFILE)
+/* All synchronous commands*/
+#define FS_ARCHIVE_PROC_SYNC \
+ (FS_ARCHIVE_PROC_SEEKDIR | FS_ARCHIVE_PROC_READDIR | \
+ FS_ARCHIVE_PROC_FINDPATH | FS_ARCHIVE_PROC_GETPATH | \
+ FS_ARCHIVE_PROC_OPENFILEFAST | FS_ARCHIVE_PROC_OPENFILEDIRECT | FS_ARCHIVE_PROC_CLOSEFILE)
+
+/* Messages when status changes*/
+#define FS_ARCHIVE_PROC_ACTIVATE (1 << FS_COMMAND_ACTIVATE)
+#define FS_ARCHIVE_PROC_IDLE (1 << FS_COMMAND_IDLE)
+#define FS_ARCHIVE_PROC_SUSPENDING (1 << FS_COMMAND_SUSPEND)
+#define FS_ARCHIVE_PROC_RESUME (1 << FS_COMMAND_RESUME)
+/* All messages when status changes*/
+#define FS_ARCHIVE_PROC_STATUS \
+ (FS_ARCHIVE_PROC_ACTIVATE | FS_ARCHIVE_PROC_IDLE | \
+ FS_ARCHIVE_PROC_SUSPENDING | FS_ARCHIVE_PROC_RESUME)
+
typedef enum {
FS_RESULT_SUCCESS = 0,
FS_RESULT_FAILURE,
@@ -107,6 +138,31 @@ static inline BOOL FS_IsArchiveLoaded(volatile const FSArchive * p_arc)
return (p_arc->flag & FS_ARCHIVE_FLAG_LOADED) ? TRUE : FALSE;
}
+static inline u32 FS_GetArchiveOffset(const FSArchive * p_arc, u32 pos)
+{
+ return p_arc->base + pos;
+}
+
+static inline BOOL FSi_IsArchiveCanceling(volatile const FSArchive * p_arc)
+{
+ return (p_arc->flag & FS_ARCHIVE_FLAG_CANCELING) != 0;
+}
+
+static inline BOOL FS_IsArchiveSuspended(volatile const FSArchive * p_arc)
+{
+ return (p_arc->flag & FS_ARCHIVE_FLAG_SUSPEND) ? TRUE : FALSE;
+}
+
+static inline BOOL FSi_IsArchiveSuspending(volatile const FSArchive * p_arc)
+{
+ return (p_arc->flag & FS_ARCHIVE_FLAG_SUSPENDING) != 0;
+}
+
+static inline BOOL FSi_IsArchiveRunning(volatile const FSArchive * p_arc)
+{
+ return (p_arc->flag & FS_ARCHIVE_FLAG_RUNNING) != 0;
+}
+
BOOL FSi_SendCommand(struct FSFile * file, FSCommandType command);
BOOL FSi_ExecuteSyncCommand(struct FSFile * file);
diff --git a/arm9/lib/include/FS_command.h b/arm9/lib/include/FS_command.h
new file mode 100644
index 00000000..db878f3f
--- /dev/null
+++ b/arm9/lib/include/FS_command.h
@@ -0,0 +1,9 @@
+#ifndef NITRO_FS_COMMAND_H_
+#define NITRO_FS_COMMAND_H_
+
+#include "FS_file.h"
+
+void FSi_ReleaseCommand(FSFile * file, FSResult signal);
+FSResult FSi_TranslateCommand(FSFile * file, FSCommandType command);
+
+#endif //NITRO_FS_COMMAND_H_
diff --git a/arm9/lib/include/FS_file.h b/arm9/lib/include/FS_file.h
index 89f69d86..92e2149e 100644
--- a/arm9/lib/include/FS_file.h
+++ b/arm9/lib/include/FS_file.h
@@ -189,4 +189,24 @@ static inline u32 const FS_GetLength(volatile const FSFile * p_file)
return p_file->prop.file.bottom - p_file->prop.file.top;
}
+static inline BOOL FS_IsCanceling(volatile const FSFile * p_file)
+{
+ return (p_file->stat & FS_FILE_STATUS_CANCEL) ? TRUE : FALSE;
+}
+
+static inline BOOL FS_IsFileSyncMode(volatile const FSFile * p_file)
+{
+ return (p_file->stat & FS_FILE_STATUS_SYNC) ? TRUE : FALSE;
+}
+
+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;
+}
+
#endif //NITRO_FS_FILE_H_
diff --git a/arm9/lib/include/OS_thread.h b/arm9/lib/include/OS_thread.h
index 8820a7a0..c5602559 100644
--- a/arm9/lib/include/OS_thread.h
+++ b/arm9/lib/include/OS_thread.h
@@ -29,6 +29,7 @@ struct _OSThread
};
void OS_SleepThread(OSThreadQueue * queue);
+void OS_WakeupThread(OSThreadQueue * queue);
static inline void OS_InitThreadQueue(OSThreadQueue * queue)
{
queue->head = queue->tail = NULL;
diff --git a/arm9/lib/src/FS_archive.c b/arm9/lib/src/FS_archive.c
new file mode 100644
index 00000000..39daa324
--- /dev/null
+++ b/arm9/lib/src/FS_archive.c
@@ -0,0 +1,147 @@
+#include "FS_archive.h"
+#include "FS_file.h"
+#include "FS_command.h"
+#include "MI_memory.h"
+#include "MI_byteAccess.h"
+
+FSArchive * arc_list = NULL;
+FSDirPos current_dir_pos;
+
+u32 FSi_GetPackedName(const char * name, int name_len)
+{
+ u32 ret = 0;
+ if (name_len <= FS_ARCHIVE_NAME_LEN_MAX)
+ {
+ int i = 0;
+ for (; i < name_len; i++)
+ {
+ u32 c = MI_ReadByte(name + i);
+ if (!c)
+ break;
+ c = (u32)(c - 'A');
+ if (c <= (u32)('Z' - 'A'))
+ c = (u32)(c + 'a');
+ else
+ c = (u32)(c + 'A');
+ ret |= (u32)(c << (i * 8));
+ }
+ }
+ return ret;
+}
+
+FSResult FSi_ReadMemCallback(FSArchive * p_arc, u8 * dest, u32 offset, u32 size)
+{
+ MI_CpuCopy8((const void *)FS_GetArchiveOffset(p_arc, offset), dest, size);
+ return FS_RESULT_SUCCESS;
+}
+
+FSResult FSi_WriteMemCallback(FSArchive * p_arc, const u8 * src, u32 offset, u32 size)
+{
+ MI_CpuCopy8(src, (void *)FS_GetArchiveOffset(p_arc, offset), size);
+ return FS_RESULT_SUCCESS;
+}
+
+FSResult FSi_ReadMemoryCore(FSArchive * p_arc, u8 * dest, u32 offset, u32 size)
+{
+ MI_CpuCopy8((const void *)offset, dest, size);
+ return FS_RESULT_SUCCESS;
+}
+
+FSFile * FSi_NextCommand(FSArchive * p_arc)
+{
+ OSIntrMode bak_psr = OS_DisableInterrupts();
+ if (FSi_IsArchiveCanceling(p_arc))
+ {
+ FSFile *p, *q;
+ p_arc->flag &= ~FS_ARCHIVE_FLAG_CANCELING;
+ for (p = p_arc->list.next; p; p = q)
+ {
+ q = p->link.next;
+ if (FS_IsCanceling(p))
+ {
+ if (p_arc->list.next == p)
+ p_arc->list.next = q;
+ FSi_ReleaseCommand(p, FS_RESULT_CANCELED);
+ if (!q)
+ q = p_arc->list.next;
+ }
+ }
+ }
+ if (!FSi_IsArchiveSuspending(p_arc) && !FS_IsArchiveSuspended(p_arc))
+ {
+ FSFile * p_file = p_arc->list.next;
+ if (p_file != NULL)
+ {
+ const BOOL is_start = !FSi_IsArchiveRunning(p_arc);
+ if (is_start)
+ p_arc->flag |= FS_ARCHIVE_FLAG_RUNNING;
+ OS_RestoreInterrupts(bak_psr);
+ if (is_start)
+ {
+ if ((p_arc->proc_flag & FS_ARCHIVE_PROC_ACTIVATE) != 0)
+ (*p_arc->proc) (p_file, FS_COMMAND_ACTIVATE);
+ }
+ bak_psr = OS_DisableInterrupts();
+ p_file->stat |= FS_FILE_STATUS_OPERATING;
+ if (FS_IsFileSyncMode(p_file))
+ {
+ OS_WakeupThread(p_file->queue);
+ OS_RestoreInterrupts(bak_psr);
+ return NULL;
+ }
+ OS_RestoreInterrupts(bak_psr);
+ return p_file;
+ }
+ }
+ if (FSi_IsArchiveRunning(p_arc))
+ {
+ p_arc->flag &= ~FS_ARCHIVE_FLAG_RUNNING;
+ if (p_arc->proc_flag & FS_ARCHIVE_PROC_IDLE)
+ {
+ FSFile tmp;
+ FS_InitFile(&tmp);
+ tmp.arc = p_arc;
+ (*p_arc->proc)(&tmp, FS_COMMAND_IDLE);
+ }
+ }
+ if (FSi_IsArchiveSuspending(p_arc))
+ {
+ p_arc->flag &= ~FS_ARCHIVE_FLAG_SUSPENDING;
+ p_arc->flag |= FS_ARCHIVE_FLAG_SUSPEND;
+ OS_WakeupThread(&p_arc->stat_q);
+ }
+ OS_RestoreInterrupts(bak_psr);
+ return NULL;
+}
+
+void FSi_ExecuteAsyncCommand(FSFile * p_file)
+{
+ FSArchive *const p_arc = p_file->arc;
+ while (p_file)
+ {
+ OSIntrMode bak_psr = OS_DisableInterrupts();
+ p_file->stat |= FS_FILE_STATUS_OPERATING;
+ if (FS_IsFileSyncMode(p_file))
+ {
+ OS_WakeupThread(p_file->queue);
+ OS_RestoreInterrupts(bak_psr);
+ break;
+ }
+ p_file->stat |= FS_FILE_STATUS_ASYNC;
+ OS_RestoreInterrupts(bak_psr);
+ if (FSi_TranslateCommand(p_file, p_file->command) == FS_RESULT_PROC_ASYNC)
+ break;
+ p_file = FSi_NextCommand(p_arc);
+ }
+}
+
+BOOL FSi_ExecuteSyncCommand(FSFile * p_file)
+{
+ FSFile * p_target;
+ FSResult ret = FSi_TranslateCommand(p_file, p_file->command);
+ FSi_ReleaseCommand(p_file, ret);
+ p_target = FSi_NextCommand(p_file->arc);
+ if (p_target)
+ FSi_ExecuteAsyncCommand(p_target);
+ return FS_IsSucceeded(p_file);
+}
diff --git a/arm9/lib/src/FS_file.c b/arm9/lib/src/FS_file.c
index 8ca89af8..479a5085 100644
--- a/arm9/lib/src/FS_file.c
+++ b/arm9/lib/src/FS_file.c
@@ -11,16 +11,6 @@ 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)