diff options
author | red031000 <rubenru09@aol.com> | 2020-05-12 23:12:35 +0100 |
---|---|---|
committer | red031000 <rubenru09@aol.com> | 2020-05-12 23:12:35 +0100 |
commit | 59171916421e659bcb35b1b47eaf748fac2fea6d (patch) | |
tree | fd5886b4a76002766c94a5d33a1a42fd14335e0e /arm9/lib/src | |
parent | 26b7a78d02b261256e420f149bb7bae66e392ee7 (diff) | |
parent | f4ea052ed0b4e3b0d6a3c12bce46ee53228a9bc0 (diff) |
Merge branch 'master' of https://github.com/martmists/pokediamond into overlay69
Diffstat (limited to 'arm9/lib/src')
-rw-r--r-- | arm9/lib/src/FS_archive.c | 445 | ||||
-rw-r--r-- | arm9/lib/src/FS_command.c | 75 | ||||
-rw-r--r-- | arm9/lib/src/FS_command_default.c | 468 | ||||
-rw-r--r-- | arm9/lib/src/FS_file.c | 242 | ||||
-rw-r--r-- | arm9/lib/src/FS_overlay.c | 320 | ||||
-rw-r--r-- | arm9/lib/src/FS_rom.c | 118 | ||||
-rw-r--r-- | arm9/lib/src/FX_cp.c | 48 | ||||
-rw-r--r-- | arm9/lib/src/FX_vec.c | 44 | ||||
-rw-r--r-- | arm9/lib/src/OS_arena.c | 2 | ||||
-rw-r--r-- | arm9/lib/src/OS_emulator.c | 18 | ||||
-rw-r--r-- | arm9/lib/src/OS_init.c | 2 | ||||
-rw-r--r-- | arm9/lib/src/OS_interrupt.c | 89 | ||||
-rw-r--r-- | arm9/lib/src/OS_printf.c | 1248 | ||||
-rw-r--r-- | arm9/lib/src/OS_reset.c | 62 | ||||
-rw-r--r-- | arm9/lib/src/OS_system.c | 1 | ||||
-rw-r--r-- | arm9/lib/src/OS_tcm.c | 13 | ||||
-rw-r--r-- | arm9/lib/src/OS_terminate_proc.c | 21 |
17 files changed, 3166 insertions, 50 deletions
diff --git a/arm9/lib/src/FS_archive.c b/arm9/lib/src/FS_archive.c new file mode 100644 index 00000000..6c0f01f1 --- /dev/null +++ b/arm9/lib/src/FS_archive.c @@ -0,0 +1,445 @@ +#include "FS_archive.h" +#include "FS_file.h" +#include "FS_command.h" +#include "FSi_util.h" +#include "MI_memory.h" +#include "MI_byteAccess.h" +#include "OS_printf.h" + +FSArchive * arc_list = NULL; +FSDirPos current_dir_pos; + +ARM_FUNC 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; +} + +ARM_FUNC FSResult FSi_ReadMemCallback(struct FSArchive * p_arc, void * dest, u32 pos, u32 size) +{ + MI_CpuCopy8((const void *)FS_GetArchiveOffset(p_arc, pos), dest, size); + return FS_RESULT_SUCCESS; +} + +ARM_FUNC FSResult FSi_WriteMemCallback(struct FSArchive * p_arc, const void * src, u32 pos, u32 size) +{ + MI_CpuCopy8(src, (void *)FS_GetArchiveOffset(p_arc, pos), size); + return FS_RESULT_SUCCESS; +} + +ARM_FUNC FSResult FSi_ReadMemoryCore(FSArchive * p_arc, void * dest, u32 pos, u32 size) +{ + MI_CpuCopy8((const void *)pos, dest, size); + return FS_RESULT_SUCCESS; +} + +ARM_FUNC 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; +} + +ARM_FUNC 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); + } +} + +ARM_FUNC 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); +} + +ARM_FUNC BOOL FSi_SendCommand(FSFile * p_file, FSCommandType command) +{ + FSArchive * p_arc = p_file->arc; + const int bit = 1 << command; + p_file->command = command; + p_file->error = FS_RESULT_BUSY; + p_file->stat |= FS_FILE_STATUS_BUSY; + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + if (FSi_IsArchiveUnloading(p_arc)) + { + FSi_ReleaseCommand(p_file, FS_RESULT_CANCELLED); + OS_RestoreInterrupts(bak_psr); + return FALSE; + } + if ((bit & FS_ARCHIVE_PROC_SYNC) != 0) + p_file->stat |= FS_FILE_STATUS_SYNC; + FSi_AppendToList(p_file, (FSFile *)&p_arc->list); + if (!FS_IsArchiveSuspended(p_arc) && !FSi_IsArchiveRunning(p_arc)) + { + p_arc->flag |= FS_ARCHIVE_FLAG_RUNNING; + OS_RestoreInterrupts(bak_psr); + if ((p_arc->proc_flag & FS_ARCHIVE_PROC_ACTIVATE)) + (*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_RestoreInterrupts(bak_psr); + FSi_ExecuteAsyncCommand(p_file); + return TRUE; + } + OS_RestoreInterrupts(bak_psr); + } + else if (!FS_IsFileSyncMode(p_file)) + { + OS_RestoreInterrupts(bak_psr); + return TRUE; + } + else + { + do + { + OS_SleepThread(p_file->queue); + } while (!(p_file->stat & FS_FILE_STATUS_OPERATING)); + OS_RestoreInterrupts(bak_psr); + } + } + return FSi_ExecuteSyncCommand(p_file); +} + +ARM_FUNC void FS_InitArchive(FSArchive * p_arc) +{ + MI_CpuClear8(p_arc, sizeof(FSArchive)); + p_arc->sync_q.head = p_arc->sync_q.tail = NULL; + p_arc->stat_q.head = p_arc->stat_q.tail = NULL; +} + +ARM_FUNC FSArchive * const FS_FindArchive(const char * name, int name_len) +{ + u32 pack = FSi_GetPackedName(name, name_len); + OSIntrMode bak_psr = OS_DisableInterrupts(); + FSArchive * p_arc = arc_list; + while (p_arc && (p_arc->name.pack != pack)) + p_arc = p_arc->next; + OS_RestoreInterrupts(bak_psr); + return p_arc; +} + +ARM_FUNC BOOL FS_RegisterArchiveName(FSArchive * p_arc, const char * name, int name_len) +{ + BOOL ret = FALSE; + OSIntrMode bak_psr = OS_DisableInterrupts(); + if (!FS_FindArchive(name, name_len)) + { + FSArchive * p_tail = arc_list; + if (!p_tail) + { + arc_list = p_arc; + current_dir_pos.arc = p_arc; + current_dir_pos.pos = 0; + current_dir_pos.index = 0; + current_dir_pos.own_id = 0; + } + else + { + while (p_tail->next) + p_tail = p_tail->next; + p_tail->next = p_arc; + p_arc->prev = p_tail; + } + p_arc->name.pack = FSi_GetPackedName(name, name_len); + p_arc->flag |= FS_ARCHIVE_FLAG_REGISTER; + ret = TRUE; + } + OS_RestoreInterrupts(bak_psr); + return ret; +} + +ARM_FUNC void FS_ReleaseArchiveName(FSArchive * p_arc) +{ + if (p_arc->name.pack) + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + if (p_arc->next) + p_arc->next->prev = p_arc->prev; + if (p_arc->prev) + p_arc->prev->next = p_arc->next; + p_arc->name.pack = 0; + p_arc->next = p_arc->prev = NULL; + p_arc->flag &= ~FS_ARCHIVE_FLAG_REGISTER; + if (current_dir_pos.arc == p_arc) + { + current_dir_pos.arc = arc_list; + current_dir_pos.pos = 0; + current_dir_pos.index = 0; + current_dir_pos.own_id = 0; + } + OS_RestoreInterrupts(bak_psr); + } +} + +ARM_FUNC BOOL FS_LoadArchive(FSArchive * p_arc, u32 base, u32 fat, u32 fat_size, u32 fnt, u32 fnt_size, FS_ARCHIVE_READ_FUNC read_func, FS_ARCHIVE_WRITE_FUNC write_func) +{ + p_arc->base = base; + p_arc->fat_size = fat_size; + p_arc->fat = p_arc->fat_bak = fat; + p_arc->fnt_size = fnt_size; + p_arc->fnt = p_arc->fnt_bak = fnt; + p_arc->read_func = (read_func != NULL) ? read_func : FSi_ReadMemCallback; + p_arc->write_func = (write_func != NULL) ? write_func : FSi_WriteMemCallback; + p_arc->table_func = p_arc->read_func; + p_arc->load_mem = NULL; + p_arc->flag |= FS_ARCHIVE_FLAG_LOADED; + return TRUE; +} + +ARM_FUNC BOOL FS_UnloadArchive(FSArchive * p_arc) +{ + OSIntrMode bak_psr = OS_DisableInterrupts(); + if (FS_IsArchiveLoaded(p_arc)) + { + if (FS_IsArchiveTableLoaded(p_arc)) + { + OS_TWarning("memory may leak. preloaded-table of archive \"%s\" (0x%08X)", p_arc->name.ptr, p_arc->load_mem); + } + { + FSFile *p, *q; + BOOL bak_state = FS_SuspendArchive(p_arc); + p_arc->flag |= FS_ARCHIVE_FLAG_UNLOADING; + for (p = p_arc->list.next; p; p = q) + { + q = p->link.next; + FSi_ReleaseCommand(p, FS_RESULT_CANCELED); + } + p_arc->list.next = NULL; + if (bak_state) + FS_ResumeArchive(p_arc); + } + p_arc->base = 0; + p_arc->fat = 0; + p_arc->fat_size = 0; + p_arc->fnt = 0; + p_arc->fnt_size = 0; + p_arc->fat_bak = p_arc->fnt_bak = 0; + p_arc->flag &= ~(FS_ARCHIVE_FLAG_CANCELING | FS_ARCHIVE_FLAG_LOADED | FS_ARCHIVE_FLAG_UNLOADING); + } + OS_RestoreInterrupts(bak_psr); + return TRUE; +} + +ARM_FUNC u32 FS_LoadArchiveTables(FSArchive *p_arc, void *p_mem, u32 max_size) +{ + u32 total_size = ALIGN_BYTE(p_arc->fat_size + p_arc->fnt_size + 32, 32); + if (total_size <= max_size) + { + u8 *p_cache = (u8 *)ALIGN_BYTE((u32)p_mem, 32); + FSFile tmp; + FS_InitFile(&tmp); + if (FS_OpenFileDirect(&tmp, p_arc, p_arc->fat, p_arc->fat + p_arc->fat_size, (u32)~0)) + { + if (FS_ReadFile(&tmp, p_cache, (s32)p_arc->fat_size) < 0) + { + MI_CpuFill8(p_cache, 0x00, p_arc->fat_size); + } + FS_CloseFile(&tmp); + } + p_arc->fat = (u32)p_cache; + p_cache += p_arc->fat_size; + if (FS_OpenFileDirect(&tmp, p_arc, p_arc->fnt, p_arc->fnt + p_arc->fnt_size, (u32)~0)) + { + if (FS_ReadFile(&tmp, p_cache, (s32)p_arc->fnt_size) < 0) + { + MI_CpuFill8(p_cache, 0x00, p_arc->fnt_size); + } + FS_CloseFile(&tmp); + } + p_arc->fnt = (u32)p_cache; + p_arc->load_mem = p_mem; + p_arc->table_func = FSi_ReadMemoryCore; + p_arc->flag |= FS_ARCHIVE_FLAG_TABLE_LOAD; + } + return total_size; +} + +ARM_FUNC void * FS_UnloadArchiveTables(FSArchive * p_arc) +{ + void *ret = NULL; + if (FS_IsArchiveLoaded(p_arc)) + { + BOOL bak_stat = FS_SuspendArchive(p_arc); + if (FS_IsArchiveTableLoaded(p_arc)) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_TABLE_LOAD; + ret = p_arc->load_mem; + p_arc->load_mem = NULL; + p_arc->fat = p_arc->fat_bak; + p_arc->fnt = p_arc->fnt_bak; + p_arc->table_func = p_arc->read_func; + } + if (bak_stat) + FS_ResumeArchive(p_arc); + } + return ret; +} + +ARM_FUNC BOOL FS_SuspendArchive(FSArchive * p_arc) +{ + OSIntrMode bak_psr = OS_DisableInterrupts(); + const BOOL bak_stat = !FS_IsArchiveSuspended(p_arc); + if (bak_stat) + { + if (FSi_IsArchiveRunning(p_arc)) + { + p_arc->flag |= FS_ARCHIVE_FLAG_SUSPENDING; + do { + OS_SleepThread(&p_arc->stat_q); + } while (FSi_IsArchiveSuspending(p_arc)); + } + else + { + p_arc->flag |= FS_ARCHIVE_FLAG_SUSPEND; + } + } + OS_RestoreInterrupts(bak_psr); + return bak_stat; +} + +ARM_FUNC BOOL FS_ResumeArchive(FSArchive * p_arc) +{ + FSFile * p_target = NULL; + OSIntrMode bak_psr = OS_DisableInterrupts(); + const BOOL bak_stat = !FS_IsArchiveSuspended(p_arc); + if (!bak_stat) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_SUSPEND; + p_target = FSi_NextCommand(p_arc); + } + OS_RestoreInterrupts(bak_psr); + if (p_target) + FSi_ExecuteAsyncCommand(p_target); + return bak_stat; +} + +ARM_FUNC void FS_SetArchiveProc(struct FSArchive * p_arc, FS_ARCHIVE_PROC_FUNC proc, u32 flags) +{ + if (!flags) + proc = NULL; + else if (!proc) + flags = 0; + p_arc->proc = proc; + p_arc->proc_flag = flags; +} + +ARM_FUNC void FS_NotifyArchiveAsyncEnd(FSArchive *p_arc, FSResult ret) +{ + if (FSi_IsArchiveAsync(p_arc)) + { + FSFile *p_file = p_arc->list.next; + p_arc->flag &= ~FS_ARCHIVE_FLAG_IS_ASYNC; + FSi_ReleaseCommand(p_file, ret); + p_file = FSi_NextCommand(p_arc); + if (p_file) + FSi_ExecuteAsyncCommand(p_file); + } + else + { + FSFile *p_file = p_arc->list.next; + OSIntrMode bak_psr = OS_DisableInterrupts(); + p_file->error = ret; + p_arc->flag &= ~FS_ARCHIVE_FLAG_IS_SYNC; + OS_WakeupThread(&p_arc->sync_q); + (void)OS_RestoreInterrupts(bak_psr); + } +} diff --git a/arm9/lib/src/FS_command.c b/arm9/lib/src/FS_command.c new file mode 100644 index 00000000..818a65ea --- /dev/null +++ b/arm9/lib/src/FS_command.c @@ -0,0 +1,75 @@ +#include "FS_file.h" +#include "FS_archive.h" +#include "FSi_util.h" +#include "FS_command.h" + +ARM_FUNC void FSi_ReleaseCommand(FSFile * p_file, FSResult ret) +{ + OSIntrMode bak_psr = OS_DisableInterrupts(); + FSi_CutFromList(p_file); + p_file->stat &= ~(FS_FILE_STATUS_CANCEL | FS_FILE_STATUS_BUSY | FS_FILE_STATUS_SYNC | FS_FILE_STATUS_ASYNC | FS_FILE_STATUS_OPERATING); + p_file->error = ret; + OS_WakeupThread(p_file->queue); + OS_RestoreInterrupts(bak_psr); +} + +ARM_FUNC FSResult FSi_TranslateCommand(FSFile *p_file, FSCommandType command) +{ + FSResult ret; + + FSArchive *const p_arc = p_file->arc; + const int bit = (1 << command); + + if (FS_IsFileSyncMode(p_file)) + p_arc->flag |= FS_ARCHIVE_FLAG_IS_SYNC; + else + p_arc->flag |= FS_ARCHIVE_FLAG_IS_ASYNC; + + if ((p_arc->proc_flag & bit) != 0) + { + switch (ret = (*p_arc->proc) (p_file, command)) + { + case FS_RESULT_SUCCESS: + case FS_RESULT_FAILURE: + case FS_RESULT_UNSUPPORTED: + p_file->error = ret; + break; + case FS_RESULT_PROC_ASYNC: + break; + case FS_RESULT_PROC_UNKNOWN: + ret = FS_RESULT_PROC_DEFAULT; + p_arc->proc_flag &= ~bit; + break; + } + } + else + { + ret = FS_RESULT_PROC_DEFAULT; + } + if (ret == FS_RESULT_PROC_DEFAULT) + { + ret = (*fsi_default_command[command]) (p_file); + } + if (ret == FS_RESULT_PROC_ASYNC) + { + if (FS_IsFileSyncMode(p_file)) + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + while (FSi_IsArchiveSync(p_arc)) + OS_SleepThread(&p_arc->sync_q); + ret = p_file->error; + OS_RestoreInterrupts(bak_psr); + } + } + else if (!FS_IsFileSyncMode(p_file)) + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_IS_ASYNC; + FSi_ReleaseCommand(p_file, ret); + } + else + { + p_arc->flag &= ~FS_ARCHIVE_FLAG_IS_SYNC; + p_file->error = ret; + } + return ret; +} diff --git a/arm9/lib/src/FS_command_default.c b/arm9/lib/src/FS_command_default.c new file mode 100644 index 00000000..002e1d53 --- /dev/null +++ b/arm9/lib/src/FS_command_default.c @@ -0,0 +1,468 @@ +#include "nitro.h" +#include "FS_file.h" +#include "FS_command.h" +#include "FS_archive.h" +#include "MI_byteAccess.h" +#include "MI_memory.h" +#include "FSi_util.h" + +typedef struct +{ + FSArchive *arc; + u32 pos; +} +FSiSyncReadParam; + +ARM_FUNC FSResult FSi_ReadFileCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_WriteFileCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_SeekDirCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_ReadDirCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_FindPathCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_GetPathCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_OpenFileFastCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_OpenFileDirectCommand(FSFile * p_file); +ARM_FUNC FSResult FSi_CloseFileCommand(FSFile * p_file); + +FSResult (*const fsi_default_command[])(FSFile *) = { + [FS_COMMAND_READFILE] = FSi_ReadFileCommand, + [FS_COMMAND_WRITEFILE] = FSi_WriteFileCommand, + [FS_COMMAND_SEEKDIR] = FSi_SeekDirCommand, + [FS_COMMAND_READDIR] = FSi_ReadDirCommand, + [FS_COMMAND_FINDPATH] = FSi_FindPathCommand, + [FS_COMMAND_GETPATH] = FSi_GetPathCommand, + [FS_COMMAND_OPENFILEFAST] = FSi_OpenFileFastCommand, + [FS_COMMAND_OPENFILEDIRECT] = FSi_OpenFileDirectCommand, + [FS_COMMAND_CLOSEFILE] = FSi_CloseFileCommand, +}; + +// Case-insensitive string comparison +ARM_FUNC u32 FSi_StrNICmp(const char * str1, const char * str2, u32 len) +{ + int i; + for (i = 0; i < len; i++) + { + u32 c = MI_ReadByte(str1 + i) - 'A'; + u32 d = MI_ReadByte(str2 + i) - 'A'; + if (c <= 'Z' - 'A') + c += 'a' - 'A'; + if (d <= 'Z' - 'A') + d += 'a' - 'A'; + if (c != d) + return c - d; + } + return 0; +} + +ARM_FUNC FSResult FSi_ReadTable(FSiSyncReadParam * p, void * dst, u32 len) +{ + FSResult ret; + FSArchive * const p_arc = p->arc; + p_arc->flag |= FS_ARCHIVE_FLAG_IS_SYNC; + switch (ret = (*p_arc->table_func)(p_arc, dst, p->pos, len)) + { + case FS_RESULT_SUCCESS: + case FS_RESULT_FAILURE: + p_arc->flag &= ~FS_ARCHIVE_FLAG_IS_SYNC; + break; + case FS_RESULT_PROC_ASYNC: + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + while (FSi_IsArchiveSync(p_arc)) + OS_SleepThread(&p_arc->sync_q); + OS_RestoreInterrupts(bak_psr); + ret = p_arc->list.next->error; + } + break; + } + p->pos += len; + return ret; +} + +ARM_FUNC FSResult FSi_SeekDirDirect(FSFile * p_dir, u32 id) +{ + p_dir->stat |= FS_FILE_STATUS_SYNC; + p_dir->arg.seekdir.pos.arc = p_dir->arc; + p_dir->arg.seekdir.pos.pos = 0; + p_dir->arg.seekdir.pos.index = 0; + p_dir->arg.seekdir.pos.own_id = (u16)id; + return FSi_TranslateCommand(p_dir, FS_COMMAND_SEEKDIR); +} + +// The actual commands +ARM_FUNC FSResult FSi_ReadFileCommand(FSFile * p_file) +{ + FSArchive *const p_arc = p_file->arc; + const u32 pos = p_file->prop.file.pos; + const u32 len = p_file->arg.readfile.len; + void *const dst = p_file->arg.readfile.dst; + p_file->prop.file.pos += len; + return (*p_arc->read_func)(p_arc, dst, pos, len); +} + +ARM_FUNC FSResult FSi_WriteFileCommand(FSFile * p_file) +{ + FSArchive *const p_arc = p_file->arc; + const u32 pos = p_file->prop.file.pos; + const u32 len = p_file->arg.writefile.len; + const void *const src = p_file->arg.writefile.src; + p_file->prop.file.pos += len; + return (*p_arc->write_func)(p_arc, src, pos, len); +} + +ARM_FUNC FSResult FSi_SeekDirCommand(FSFile * p_dir) +{ + FSResult ret; + FSArchive *const p_arc = p_dir->arc; + const FSDirPos *const arg = &p_dir->arg.seekdir.pos; + + FSArchiveFNT fnt_entry; + FSiSyncReadParam param; + param.arc = p_arc; + param.pos = p_arc->fnt + arg->own_id * sizeof(fnt_entry); + ret = FSi_ReadTable(¶m, &fnt_entry, sizeof(fnt_entry)); + if (ret == FS_RESULT_SUCCESS) + { + p_dir->prop.dir.pos = *arg; + if ((arg->index == 0) && (arg->pos == 0)) + { + p_dir->prop.dir.pos.index = fnt_entry.index; + p_dir->prop.dir.pos.pos = p_arc->fnt + fnt_entry.start; + } + p_dir->prop.dir.parent = (u32) (fnt_entry.parent & BIT_MASK(12)); + } + return ret; +} + +ARM_FUNC FSResult FSi_ReadDirCommand(FSFile *p_dir) +{ + FSDirEntry *p_entry = p_dir->arg.readdir.p_entry; + FSResult ret; + + FSiSyncReadParam param; + param.arc = p_dir->arc; + param.pos = p_dir->prop.dir.pos.pos; + + { + u8 len; + ret = FSi_ReadTable(¶m, &len, sizeof(len)); + if (ret != FS_RESULT_SUCCESS) + return ret; + p_entry->name_len = (u32)(len & BIT_MASK(7)); + p_entry->is_directory = (u32)((len >> 7) & 1); + } + if (p_entry->name_len == 0) + return FS_RESULT_FAILURE; + + if (!p_dir->arg.readdir.skip_string) + { + ret = FSi_ReadTable(¶m, p_entry->name, p_entry->name_len); + if (ret != FS_RESULT_SUCCESS) + return ret; + MI_WriteByte((u8 *)p_entry->name + p_entry->name_len, (u8)'\0'); + } + else + { + param.pos += p_entry->name_len; + } + + if (p_entry->is_directory) + { + u16 id; + ret = FSi_ReadTable(¶m, &id, sizeof(id)); + if (ret != FS_RESULT_SUCCESS) + return ret; + p_entry->dir_id.arc = p_dir->arc; + p_entry->dir_id.own_id = (u16)(id & BIT_MASK(12)); + p_entry->dir_id.index = 0; + p_entry->dir_id.pos = 0; + } + else + { + p_entry->file_id.arc = p_dir->arc; + p_entry->file_id.file_id = p_dir->prop.dir.pos.index; + ++p_dir->prop.dir.pos.index; + } + p_dir->prop.dir.pos.pos = param.pos; + + return ret; +} + +ARM_FUNC FSResult FSi_FindPathCommand(FSFile *p_dir) +{ + const char *path = p_dir->arg.findpath.path; + const BOOL is_dir = p_dir->arg.findpath.find_directory; + p_dir->arg.seekdir.pos = p_dir->arg.findpath.pos; + (void)FSi_TranslateCommand(p_dir, FS_COMMAND_SEEKDIR); + for (; MI_ReadByte(path); path += (MI_ReadByte(path) ? 1 : 0)) + { + u32 is_directory; + int name_len = 0; + while ((is_directory = MI_ReadByte(path + name_len)), + (is_directory && !FSi_IsSlash(is_directory))) + ++name_len; + if (is_directory || is_dir) + is_directory = 1; + if (name_len == 0) + { + return FS_RESULT_FAILURE; + } + else if (MI_ReadByte(path) == '.') + { + if (name_len == 1) + { + path += 1; + continue; + } + else if ((name_len == 2) & (MI_ReadByte(path + 1) == '.')) + { + if (p_dir->prop.dir.pos.own_id != 0) + FSi_SeekDirDirect(p_dir, p_dir->prop.dir.parent); + path += 2; + continue; + } + } + if (name_len > FS_FILE_NAME_MAX) + { + return FS_RESULT_FAILURE; + } + else + { + FSDirEntry etr; + p_dir->arg.readdir.p_entry = &etr; + p_dir->arg.readdir.skip_string = FALSE; + for (;;) + { + if (FSi_TranslateCommand(p_dir, FS_COMMAND_READDIR) != FS_RESULT_SUCCESS) + return FS_RESULT_FAILURE; + if ((is_directory != etr.is_directory) || + (name_len != etr.name_len) || FSi_StrNICmp(path, etr.name, (u32)name_len)) + continue; + if (is_directory) + { + path += name_len; + p_dir->arg.seekdir.pos = etr.dir_id; + (void)FSi_TranslateCommand(p_dir, FS_COMMAND_SEEKDIR); + break; + } + else if (is_dir) + { + return FS_RESULT_FAILURE; + } + else + { + *p_dir->arg.findpath.result.file = etr.file_id; + return FS_RESULT_SUCCESS; + } + } + } + } + if (!is_dir) + return FS_RESULT_FAILURE; + *p_dir->arg.findpath.result.dir = p_dir->prop.dir.pos; + return FS_RESULT_SUCCESS; +} + +ARM_FUNC FSResult FSi_GetPathCommand(FSFile *p_file) +{ + FSArchive *const p_arc = p_file->arc; + + FSGetPathInfo *p_info = &p_file->arg.getpath; + + FSDirEntry entry; + FSFile tmp; + u32 dir_id; + u32 file_id; + u32 id; + u32 len; + + enum + { INVALID_ID = 0x10000 }; + + FS_InitFile(&tmp); + tmp.arc = p_file->arc; + + if (FS_IsDir(p_file)) + { + dir_id = p_file->prop.dir.pos.own_id; + file_id = INVALID_ID; + } + else + { + file_id = p_file->prop.file.own_id; + if (p_info->total_len != 0) + { + dir_id = p_info->dir_id; + } + else + { + u32 pos = 0; + u32 num_dir = 0; + dir_id = INVALID_ID; + do + { + FSi_SeekDirDirect(&tmp, pos); + if (!pos) + num_dir = tmp.prop.dir.parent; + tmp.arg.readdir.p_entry = &entry; + tmp.arg.readdir.skip_string = TRUE; + while (FSi_TranslateCommand(&tmp, FS_COMMAND_READDIR) == FS_RESULT_SUCCESS) + { + if (!entry.is_directory && (entry.file_id.file_id == file_id)) + { + dir_id = tmp.prop.dir.pos.own_id; + break; + } + } + } + while ((dir_id == INVALID_ID) && (++pos < num_dir)); + } + } + if (dir_id == INVALID_ID) + { + p_info->total_len = 0; + return FS_RESULT_FAILURE; + } + if (p_info->total_len == 0) + { + len = 0; + if (p_arc->name.pack <= 0x000000FF) + len += 1; + else if (p_arc->name.pack <= 0x0000FF00) + len += 2; + else + len += 3; + len += 1 + 1; + if (file_id != INVALID_ID) + len += entry.name_len; + id = dir_id; + if (id != 0) + { + FSi_SeekDirDirect(&tmp, id); + do + { + FSi_SeekDirDirect(&tmp, tmp.prop.dir.parent); + tmp.arg.readdir.p_entry = &entry; + tmp.arg.readdir.skip_string = TRUE; + while (FSi_TranslateCommand(&tmp, FS_COMMAND_READDIR) == FS_RESULT_SUCCESS) + { + if (entry.is_directory && (entry.dir_id.own_id == id)) + { + len += entry.name_len + 1; + break; + } + } + id = tmp.prop.dir.pos.own_id; + } + while (id != 0); + } + p_info->total_len = (u16)(len + 1); + p_info->dir_id = (u16)dir_id; + } + if (!p_info->buf) + return FS_RESULT_SUCCESS; + if (p_info->buf_len < p_info->total_len) + return FS_RESULT_FAILURE; + else + { + u8 *dst = p_info->buf; + u32 total = p_info->total_len; + u32 pos = 0; + if (p_arc->name.pack <= 0x000000FF) + len = 1; + else if (p_arc->name.pack <= 0x0000FF00) + len = 2; + else + len = 3; + MI_CpuCopy8(p_arc->name.ptr, dst + pos, len); + pos += len; + MI_CpuCopy8(":/", dst + pos, 2); + pos += 2; + id = dir_id; + FSi_SeekDirDirect(&tmp, id); + if (file_id != INVALID_ID) + { + tmp.arg.readdir.p_entry = &entry; + tmp.arg.readdir.skip_string = FALSE; + while (FSi_TranslateCommand(&tmp, FS_COMMAND_READDIR) == FS_RESULT_SUCCESS) + { + if (!entry.is_directory && (entry.file_id.file_id == file_id)) + break; + } + len = entry.name_len + 1; + MI_CpuCopy8(entry.name, dst + total - len, len); + total -= len; + } + else + { + MI_WriteByte(dst + total - 1, '\0'); + total -= 1; + } + if (id != 0) + { + do + { + FSi_SeekDirDirect(&tmp, tmp.prop.dir.parent); + tmp.arg.readdir.p_entry = &entry; + tmp.arg.readdir.skip_string = FALSE; + MI_WriteByte(dst + total - 1, '/'); + total -= 1; + while (FSi_TranslateCommand(&tmp, FS_COMMAND_READDIR) == FS_RESULT_SUCCESS) + { + if (entry.is_directory && (entry.dir_id.own_id == id)) + { + len = entry.name_len; + MI_CpuCopy8(entry.name, dst + total - len, len); + total -= len; + break; + } + } + id = tmp.prop.dir.pos.own_id; + } + while (id != 0); + } + } + + return FS_RESULT_SUCCESS; +} + +ARM_FUNC FSResult FSi_OpenFileFastCommand(FSFile * p_file) +{ + FSArchive *const p_arc = p_file->arc; + const FSFileID *p_id = &p_file->arg.openfilefast.id; + const u32 index = p_id->file_id; + FSResult ret; + + { + u32 pos = (u32)(index * sizeof(FSArchiveFAT)); + if (pos >= p_arc->fat_size) + return FS_RESULT_FAILURE; + else + { + FSArchiveFAT fat; + FSiSyncReadParam param; + param.arc = p_arc; + param.pos = p_arc->fat + pos; + ret = FSi_ReadTable(¶m, &fat, sizeof(fat)); + if (ret != FS_RESULT_SUCCESS) + return ret; + p_file->arg.openfiledirect.top = fat.top; + p_file->arg.openfiledirect.bottom = fat.bottom; + p_file->arg.openfiledirect.index = index; + return FSi_TranslateCommand(p_file, FS_COMMAND_OPENFILEDIRECT); + } + } +} + +ARM_FUNC FSResult FSi_OpenFileDirectCommand(FSFile * p_file) +{ + p_file->prop.file.top = p_file->arg.openfiledirect.top; + p_file->prop.file.pos = p_file->arg.openfiledirect.top; + p_file->prop.file.bottom = p_file->arg.openfiledirect.bottom; + p_file->prop.file.own_id = p_file->arg.openfiledirect.index; + return FS_RESULT_SUCCESS; +} + +ARM_FUNC FSResult FSi_CloseFileCommand(FSFile * p_file) +{ + return FS_RESULT_SUCCESS; +} diff --git a/arm9/lib/src/FS_file.c b/arm9/lib/src/FS_file.c new file mode 100644 index 00000000..8bca5c8e --- /dev/null +++ b/arm9/lib/src/FS_file.c @@ -0,0 +1,242 @@ +#include "nitro.h" +#include "MI_byteAccess.h" +#include "FS_rom.h" +#include "FS_file.h" +#include "FSi_util.h" + +extern FSDirPos current_dir_pos; +BOOL is_init = FALSE; + +ARM_FUNC void FS_Init(u32 default_dma_no) +{ + if (!is_init) + { + is_init = TRUE; + FSi_InitRom(default_dma_no); + } +} + +ARM_FUNC BOOL FS_IsAvailable(void) +{ + return is_init; +} + +ARM_FUNC 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); +} + +ARM_FUNC int FSi_ReadFileCore(FSFile * p_file, void * dst, s32 len, BOOL async) +{ + const s32 pos = p_file->prop.file.pos; + const s32 rest = p_file->prop.file.bottom - pos; + const u32 org = 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 = len; + if (!async) + p_file->stat |= FS_FILE_STATUS_SYNC; + FSi_SendCommand(p_file, FS_COMMAND_READFILE); + if (!async) + { + if (FS_WaitAsync(p_file)) + len = p_file->prop.file.pos - pos; + else + len = -1; + } + return len; +} + +ARM_FUNC 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; +} + +ARM_FUNC 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; +} + +ARM_FUNC 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; +} + +ARM_FUNC BOOL FS_OpenFile(FSFile * p_file, const char * path) +{ + FSFileID file_id; + return FS_ConvertPathToFileID(&file_id, path) && FS_OpenFileFast(p_file, file_id); +} + +ARM_FUNC 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; +} + +ARM_FUNC 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); +} + +ARM_FUNC int FS_ReadFileAsync(FSFile * p_file, void * dst, s32 len) +{ + return FSi_ReadFileCore(p_file, dst, len, TRUE); +} + +ARM_FUNC int FS_ReadFile(FSFile * p_file, void * dst, s32 len) +{ + return FSi_ReadFileCore(p_file, dst, len, FALSE); +} + +ARM_FUNC 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; +} + +ARM_FUNC 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/lib/src/FS_overlay.c b/arm9/lib/src/FS_overlay.c new file mode 100644 index 00000000..79a3b43e --- /dev/null +++ b/arm9/lib/src/FS_overlay.c @@ -0,0 +1,320 @@ +#include "nitro.h" +#include "DGT_common.h" +#include "DGT_dgt.h" +#include "OS_cache.h" +#include "OS_system.h" +#include "OS_printf.h" +#include "MI_memory.h" +#include "MI_uncompress.h" +#include "FS_rom.h" +#include "FS_overlay.h" +#include "FS_mw_dtor.h" +#include "MB_mb.h" + +#define FS_OVERLAY_FLAG_COMP 0x0001 +#define FS_OVERLAY_FLAG_AUTH 0x0002 +#define FS_OVERLAY_DIGEST_SIZE DGT_HASH2_DIGEST_SIZE + +ARM_FUNC u32 FSi_GetOverlayBinarySize(FSOverlayInfo * p_ovi) +{ + u32 size = (p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) + ? p_ovi->header.compressed + : p_ovi->header.ram_size; + return size; +} + +ARM_FUNC void FS_ClearOverlayImage(FSOverlayInfo * p_ovi) +{ + u8 * const im_start = FS_GetOverlayAddress(p_ovi); + u32 const ram_size = FS_GetOverlayImageSize(p_ovi); + u32 const total_size = FS_GetOverlayTotalSize(p_ovi); + + IC_InvalidateRange(im_start, total_size); + DC_InvalidateRange(im_start, total_size); + MI_CpuFill8(im_start + ram_size, 0, total_size - ram_size); +} + +ARM_FUNC FSFileID FS_GetOverlayFileID(FSOverlayInfo * p_ovi) +{ + FSFileID ret; + ret.arc = &fsi_arc_rom; + ret.file_id = p_ovi->header.file_id; + return ret; +} + +ARM_FUNC BOOL FSi_LoadOverlayInfoCore(FSOverlayInfo * p_ovi, MIProcessor target, FSOverlayID id, FSArchive * arc, u32 offset_arm9, u32 len_arm9, u32 offset_arm7, u32 len_arm7) +{ + CARDRomRegion pr[1]; + u32 pos; + if (target == MI_PROCESSOR_ARM9) + { + pr->offset = offset_arm9; + pr->length = len_arm9; + } + else + { + pr->offset = offset_arm7; + pr->length = len_arm7; + } + pos = (u32) id * sizeof(FSOverlayInfoHeader); + if (pos >= pr->length) + return FALSE; + + FSFile file[1]; + FS_InitFile(file); + // BOOL FS_OpenFileDirect(FSFile * p_file, FSArchive * p_arc, u32 image_top, u32 image_bottom, u32 file_index) + if (!FS_OpenFileDirect(file, arc, pr->offset + pos, pr->offset + pr->length, (u32)~0)) + return FALSE; + if (FS_ReadFile(file, p_ovi, sizeof(FSOverlayInfoHeader)) != sizeof(FSOverlayInfoHeader)) + { + FS_CloseFile(file); + return FALSE; + } + FS_CloseFile(file); + p_ovi->target = target; + if (!FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + p_ovi->file_pos.offset = FS_GetFileImageTop(file); + p_ovi->file_pos.length = FS_GetLength(file); + FS_CloseFile(file); + return TRUE; +} + +ARM_FUNC BOOL FS_LoadOverlayInfo(FSOverlayInfo * p_ovi, MIProcessor target, FSOverlayID id) +{ + CARDRomRegion * const pr = (target == MI_PROCESSOR_ARM9) ? &fsi_ovt9 : &fsi_ovt7; + if (pr->offset) + { + FSFile file[1]; + const u32 pos = id * sizeof(FSOverlayInfoHeader); + if (pos >= pr->length) + return FALSE; + MI_CpuCopy8((const void *)(pr->offset + pos), p_ovi, sizeof(FSOverlayInfoHeader)); + p_ovi->target = target; + FS_InitFile(file); + if (!FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + p_ovi->file_pos.offset = FS_GetFileImageTop(file); + p_ovi->file_pos.length = FS_GetLength(file); + FS_CloseFile(file); + return TRUE; + } + else + { + const CARDRomRegion * const p_ovt9 = CARD_GetRomRegionOVT(MI_PROCESSOR_ARM9); + const CARDRomRegion * const p_ovt7 = CARD_GetRomRegionOVT(MI_PROCESSOR_ARM7); + return FSi_LoadOverlayInfoCore(p_ovi, target, id, &fsi_arc_rom, p_ovt9->offset, p_ovt9->length, p_ovt7->offset, p_ovt7->length); + } +} + +ARM_FUNC BOOL FS_LoadOverlayImageAsync(FSOverlayInfo * p_ovi, FSFile * p_file) +{ + FS_InitFile(p_file); + if (!FS_OpenFileFast(p_file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + else + { + s32 size = FSi_GetOverlayBinarySize(p_ovi); + FS_ClearOverlayImage(p_ovi); + if (FS_ReadFileAsync(p_file, FS_GetOverlayAddress(p_ovi), size) != size) + { + FS_CloseFile(p_file); + return FALSE; + } + return TRUE; + } +} + +ARM_FUNC BOOL FS_LoadOverlayImage(FSOverlayInfo * p_ovi) +{ + FSFile file[1]; + FS_InitFile(file); + if (!FS_OpenFileFast(file, FS_GetOverlayFileID(p_ovi))) + return FALSE; + else + { + s32 size = FSi_GetOverlayBinarySize(p_ovi); + FS_ClearOverlayImage(p_ovi); + if (FS_ReadFile(file, FS_GetOverlayAddress(p_ovi), size) != size) + { + FS_CloseFile(file); + return FALSE; + } + FS_CloseFile(file); + return TRUE; + } +} + +static const u8 fsi_def_digest_key[64] = { + 0x21, 0x06, 0xc0, 0xde, + 0xba, 0x98, 0xce, 0x3f, + 0xa6, 0x92, 0xe3, 0x9d, + 0x46, 0xf2, 0xed, 0x01, + + 0x76, 0xe3, 0xcc, 0x08, + 0x56, 0x23, 0x63, 0xfa, + 0xca, 0xd4, 0xec, 0xdf, + 0x9a, 0x62, 0x78, 0x34, + + 0x8f, 0x6d, 0x63, 0x3c, + 0xfe, 0x22, 0xca, 0x92, + 0x20, 0x88, 0x97, 0x23, + 0xd2, 0xcf, 0xae, 0xc2, + + 0x32, 0x67, 0x8d, 0xfe, + 0xca, 0x83, 0x64, 0x98, + 0xac, 0xfd, 0x3e, 0x37, + 0x87, 0x46, 0x58, 0x24, +}; + +static const void *fsi_digest_key_ptr = fsi_def_digest_key; +static int fsi_digest_key_len = sizeof(fsi_def_digest_key); + +ARM_FUNC BOOL FSi_CompareDigest(const u8 *spec_digest, void *src, int len) +{ + int i; + u8 digest[FS_OVERLAY_DIGEST_SIZE]; + u8 digest_key[64]; + + MI_CpuClear8(digest, sizeof(digest)); + MI_CpuCopy8(fsi_digest_key_ptr, digest_key, fsi_digest_key_len); + DGT_Hash2CalcHmac(digest, src, len, digest_key, fsi_digest_key_len); + for (i = 0; i < sizeof(digest); i += sizeof(u32)) + { + if (*(const u32 *)(digest + i) != *(const u32 *)(spec_digest + i)) + break; + } + return i == sizeof(digest); +} + +extern u8 SDK_OVERLAY_DIGEST[]; +extern u8 SDK_OVERLAY_DIGEST_END[]; + +ARM_FUNC void FS_StartOverlay(FSOverlayInfo * p_ovi) +{ + u32 rare_size = FSi_GetOverlayBinarySize(p_ovi); + if (MB_IsMultiBootChild()) + { + BOOL ret = FALSE; + + if (p_ovi->header.flag & FS_OVERLAY_FLAG_AUTH) + { + const u32 odt_max = (u32)((SDK_OVERLAY_DIGEST_END - SDK_OVERLAY_DIGEST) / FS_OVERLAY_DIGEST_SIZE); + if (p_ovi->header.id < odt_max) + { + const u8 * spec_digest = SDK_OVERLAY_DIGEST + FS_OVERLAY_DIGEST_SIZE * p_ovi->header.id; + ret = FSi_CompareDigest(spec_digest, p_ovi->header.ram_address, (int)rare_size); + } + } + if (!ret) + { + MI_CpuClear8(p_ovi->header.ram_address, rare_size); + OS_TPanic("FS_StartOverlay() failed! (invalid overlay-segment data)"); + return; + } + } + if (p_ovi->header.flag & FS_OVERLAY_FLAG_COMP) + { + MIi_UncompressBackward(p_ovi->header.ram_address + rare_size); + } + DC_FlushRange(p_ovi->header.ram_address, p_ovi->header.ram_size); + + { + FSOverlayInitFunc *p = p_ovi->header.sinit_init; + FSOverlayInitFunc *q = p_ovi->header.sinit_init_end; + for (; p < q; ++p) + { + if (*p) + (**p)(); + } + } +} + +ARM_FUNC void FS_EndOverlay(FSOverlayInfo *p_ovi) +{ + for (;;) + { + MWiDestructorChain *head = NULL, *tail = NULL; + const u32 region_top = (u32)FS_GetOverlayAddress(p_ovi); + const u32 region_bottom = region_top + FS_GetOverlayTotalSize(p_ovi); + + { + OSIntrMode bak_psr = OS_DisableInterrupts(); + MWiDestructorChain *prev = NULL; + MWiDestructorChain *base = __global_destructor_chain; + MWiDestructorChain *p = base; + while (p) + { + MWiDestructorChain *next = p->next; + const u32 dtor = (u32)p->dtor; + const u32 obj = (u32)p->obj; + if (((obj == 0) && (dtor >= region_top) && (dtor < region_bottom)) || + ((obj >= region_top) && (obj < region_bottom))) + { + /* If appropriate, extract*/ + if (!tail) + { + head = p; + } + else + { + tail->next = p; + } + if (base == p) + { + base = __global_destructor_chain = next; + } + tail = p, p->next = NULL; + if (prev) + { + prev->next = next; + } + } + else + { + prev = p; + } + p = next; + } + OS_RestoreInterrupts(bak_psr); + } + + if (!head) + { + break; + } + do + { + MWiDestructorChain *next = head->next; + if (head->dtor) + { + (*head->dtor) (head->obj); + } + head = next; + } + while (head); + } +} + +ARM_FUNC BOOL FS_UnloadOverlayImage(FSOverlayInfo * p_ovi) +{ + FS_EndOverlay(p_ovi); + return TRUE; +} + +ARM_FUNC BOOL FS_LoadOverlay(MIProcessor target, FSOverlayID id) +{ + FSOverlayInfo ovi; + if (!FS_LoadOverlayInfo(&ovi, target, id) || !FS_LoadOverlayImage(&ovi)) + return FALSE; + FS_StartOverlay(&ovi); + return TRUE; +} + +ARM_FUNC BOOL FS_UnloadOverlay(MIProcessor target, FSOverlayID id) +{ + FSOverlayInfo ovi; + if (!FS_LoadOverlayInfo(&ovi, target, id) || !FS_UnloadOverlayImage(&ovi)) + return FALSE; + return TRUE; +} diff --git a/arm9/lib/src/FS_rom.c b/arm9/lib/src/FS_rom.c new file mode 100644 index 00000000..32f66c10 --- /dev/null +++ b/arm9/lib/src/FS_rom.c @@ -0,0 +1,118 @@ +#include "FS_rom.h" +#include "FS_archive.h" +#include "FS_file.h" +#include "CARD_pullOut.h" +#include "CARD_rom.h" +#include "CARD_common.h" +#include "MB_mb.h" +#include "OS_printf.h" + +u32 fsi_default_dma_no; + +ARM_FUNC void FSi_OnRomReadDone(void * p_arc) +{ + FS_NotifyArchiveAsyncEnd(p_arc, CARD_IsPulledOut() ? FS_RESULT_ERROR : FS_RESULT_SUCCESS); +} + +ARM_FUNC FSResult FSi_ReadRomCallback(FSArchive * p_arc, void * dst, u32 src, u32 len) +{ + CARD_ReadRomAsync(fsi_default_dma_no, (const void *)src, dst, len, FSi_OnRomReadDone, p_arc); + return FS_RESULT_PROC_ASYNC; +} + +ARM_FUNC FSResult FSi_WriteDummyCallback(FSArchive * p_arc, const void *src, u32 dst, u32 len) +{ + return FS_RESULT_FAILURE; +} + +ARM_FUNC FSResult FSi_RomArchiveProc(FSFile * p_arc, FSCommandType cmd) +{ + switch (cmd) + { + case FS_COMMAND_ACTIVATE: + CARD_LockRom(fsi_card_lock_id); + return FS_RESULT_SUCCESS; + case FS_COMMAND_IDLE: + CARD_UnlockRom(fsi_card_lock_id); + return FS_RESULT_SUCCESS; + case FS_COMMAND_WRITEFILE: + return FS_RESULT_UNSUPPORTED; + default: + return FS_RESULT_PROC_UNKNOWN; + } +} + +ARM_FUNC FSResult FSi_ReadDummyCallback(FSArchive *p_arc, void *dst, u32 src, u32 len) +{ + return FS_RESULT_FAILURE; +} + +ARM_FUNC FSResult FSi_EmptyArchiveProc(FSFile *p_file, FSCommandType cmd) +{ + return FS_RESULT_UNSUPPORTED; +} + +ARM_FUNC void FSi_InitRom(u32 default_dma_no) +{ + fsi_default_dma_no = default_dma_no; + fsi_card_lock_id = OS_GetLockID(); + fsi_ovt9.offset = 0; + fsi_ovt9.length = 0; + fsi_ovt7.offset = 0; + fsi_ovt7.length = 0; + + CARD_Init(); + + FS_InitArchive(&fsi_arc_rom); + FS_RegisterArchiveName(&fsi_arc_rom, "rom", 3); + + if (MB_IsMultiBootChild()) + { + fsi_ovt9.offset = (u32)~0; + fsi_ovt9.length = 0; + fsi_ovt7.offset = (u32)~0; + fsi_ovt7.length = 0; + FS_SetArchiveProc(&fsi_arc_rom, FSi_EmptyArchiveProc, (u32)FS_ARCHIVE_PROC_ALL); + FS_LoadArchive(&fsi_arc_rom, 0x00000000, 0, 0, 0, 0, FSi_ReadDummyCallback, FSi_WriteDummyCallback); + } + else + { + const CARDRomRegion *const fnt = CARD_GetRomRegionFNT(); + const CARDRomRegion *const fat = CARD_GetRomRegionFAT(); + + FS_SetArchiveProc(&fsi_arc_rom, FSi_RomArchiveProc, + FS_ARCHIVE_PROC_WRITEFILE | + FS_ARCHIVE_PROC_ACTIVATE | FS_ARCHIVE_PROC_IDLE); + + if ((fnt->offset == 0xFFFFFFFF) || (fnt->offset == 0x00000000) || + (fat->offset == 0xFFFFFFFF) || (fat->offset == 0x00000000)) + { + OS_Warning("file-system : no MAKEROM-information in rom header."); + } + else + { + FS_LoadArchive(&fsi_arc_rom, 0x00000000, + fat->offset, fat->length, + fnt->offset, fnt->length, + FSi_ReadRomCallback, FSi_WriteDummyCallback); + } + } +} + +ARM_FUNC u32 FS_SetDefaultDMA(u32 dma_no) +{ + OSIntrMode bak_psr = OS_DisableInterrupts(); + u32 bak_dma_no = fsi_default_dma_no; + BOOL bak_stat = FS_SuspendArchive(&fsi_arc_rom); + fsi_default_dma_no = dma_no; + if (bak_stat) + FS_ResumeArchive(&fsi_arc_rom); + OS_RestoreInterrupts(bak_psr); + return bak_dma_no; +} + +ARM_FUNC u32 FS_TryLoadTable(void * p_mem, u32 size) +{ + return FS_LoadArchiveTables(&fsi_arc_rom, p_mem, size); +} + diff --git a/arm9/lib/src/FX_cp.c b/arm9/lib/src/FX_cp.c index 2ca9d720..3b6e6c96 100644 --- a/arm9/lib/src/FX_cp.c +++ b/arm9/lib/src/FX_cp.c @@ -16,8 +16,8 @@ ARM_FUNC fx32 FX_Inv(fx32 x){ ARM_FUNC fx32 FX_Sqrt(fx32 x){ if (x > 0) { - SETREG16(HW_REG_SQRTCNT, 0x1); - SETREG64(HW_REG_SQRT_PARAM, (fx64)x << 32); + reg_CP_SQRTCNT = 0x1; + reg_CP_SQRT_PARAM = (fx64)x << 32; return FX_GetSqrtResult(); } else @@ -27,44 +27,44 @@ ARM_FUNC fx32 FX_Sqrt(fx32 x){ } ARM_FUNC fx64c FX_GetDivResultFx64c(){ - while (READREG16(HW_REG_DIVCNT) & 0x8000); - return READREG64(HW_REG_DIV_RESULT); + while (reg_CP_DIVCNT & 0x8000); + return reg_CP_DIV_RESULT; } ARM_FUNC fx32 FX_GetDivResult(){ - while (READREG16(HW_REG_DIVCNT) & 0x8000); - return (READREG64(HW_REG_DIV_RESULT) + (1 << (0x14 - 1))) >> 0x14; + while (reg_CP_DIVCNT & 0x8000); + return (reg_CP_DIV_RESULT + (1 << (0x14 - 1))) >> 0x14; } ARM_FUNC void FX_InvAsync(fx32 x){ - SETREG16(HW_REG_DIVCNT, 0x1); - SETREG64(HW_REG_DIV_NUMER, (fx64)0x00001000 << 32); - SETREG64(HW_REG_DIV_DENOM, (u32)x); + reg_CP_DIVCNT = 0x1; + reg_CP_DIV_NUMER = (fx64)0x00001000 << 32; + reg_CP_DIV_DENOM = (u32)x; } ARM_FUNC fx32 FX_GetSqrtResult(){ - while (READREG16(HW_REG_SQRTCNT) & 0x8000); - return (READREG32(HW_REG_SQRT_RESULT) + (1 << (0xA - 1))) >> 0xA; + while (reg_CP_SQRTCNT & 0x8000); + return (reg_CP_SQRT_RESULT + (1 << (0xA - 1))) >> 0xA; } ARM_FUNC void FX_DivAsync(fx32 numerator, fx32 denominator){ - SETREG16(HW_REG_DIVCNT, 0x1); - SETREG64(HW_REG_DIV_NUMER, (fx64)numerator << 32); - SETREG64(HW_REG_DIV_DENOM, (u32)denominator); + reg_CP_DIVCNT = 0x1; + reg_CP_DIV_NUMER = (fx64)numerator << 32; + reg_CP_DIV_DENOM = (u32)denominator; } ARM_FUNC fx32 FX_DivS32(fx32 numerator, fx32 denominator){ - SETREG16(HW_REG_DIVCNT, 0x0); - SETREG32(HW_REG_DIV_NUMER, (u32)numerator); //32bit write for some reason - SETREG64(HW_REG_DIV_DENOM, (u32)denominator); - while (READREG16(HW_REG_DIVCNT) & 0x8000); - return READREG32(HW_REG_DIV_RESULT); + reg_CP_DIVCNT = 0x0; + *(REGType32v *)®_CP_DIV_NUMER = (u32)numerator; //32bit write for some reason + reg_CP_DIV_DENOM = (u32)denominator; + while (reg_CP_DIVCNT & 0x8000); + return *(REGType32v *)®_CP_DIV_RESULT; } ARM_FUNC fx32 FX_ModS32(fx32 num, fx32 mod){ - SETREG16(HW_REG_DIVCNT, 0x0); - SETREG32(HW_REG_DIV_NUMER, (u32)num); //32bit write for some reason - SETREG64(HW_REG_DIV_DENOM, (u32)mod); - while (READREG16(HW_REG_DIVCNT) & 0x8000); - return READREG32(HW_REG_DIVREM_RESULT); + reg_CP_DIVCNT = 0x0; + *(REGType32v *)®_CP_DIV_NUMER = (u32)num; //32bit write for some reason + reg_CP_DIV_DENOM = (u32)mod; + while (reg_CP_DIVCNT & 0x8000); + return *(REGType32v *)®_CP_DIVREM_RESULT; } diff --git a/arm9/lib/src/FX_vec.c b/arm9/lib/src/FX_vec.c index af36fe89..95805f33 100644 --- a/arm9/lib/src/FX_vec.c +++ b/arm9/lib/src/FX_vec.c @@ -55,10 +55,10 @@ ARM_FUNC fx32 VEC_Mag(struct Vecx32 *a){ fx64 l2 = (fx64)a->x * a->x; l2 += (fx64)a->y * a->y; l2 += (fx64)a->z * a->z; - SETREG16(HW_REG_SQRTCNT, 0x1); - SETREG64(HW_REG_SQRT_PARAM, l2 * 4); - while (READREG16(HW_REG_SQRTCNT) & 0x8000); //wait for coprocessor to finish - return ((fx32)READREG32(HW_REG_SQRT_RESULT) + 1) >> 1; + reg_CP_SQRTCNT = 0x1; + reg_CP_SQRT_PARAM = l2 * 4; + while (reg_CP_SQRTCNT & 0x8000); //wait for coprocessor to finish + return ((fx32)reg_CP_SQRT_RESULT + 1) >> 1; } ARM_FUNC void VEC_Normalize(struct Vecx32 *a, struct Vecx32 *dst){ @@ -66,15 +66,15 @@ ARM_FUNC void VEC_Normalize(struct Vecx32 *a, struct Vecx32 *dst){ l2 += (fx64)a->y * a->y; l2 += (fx64)a->z * a->z; //1/sqrt(l) is computed by calculating sqrt(l)*(1/l) - SETREG16(HW_REG_DIVCNT, 0x2); - SETREG64(HW_REG_DIV_NUMER, 0x0100000000000000); - SETREG64(HW_REG_DIV_DENOM, l2); - SETREG16(HW_REG_SQRTCNT, 0x1); - SETREG64(HW_REG_SQRT_PARAM, l2 * 4); - while (READREG16(HW_REG_SQRTCNT) & 0x8000); //wait for sqrt to finish - fx32 sqrtresult = READREG32(HW_REG_SQRT_RESULT); - while (READREG16(HW_REG_DIVCNT) & 0x8000); //wait for division to finish - l2 = READREG64(HW_REG_DIV_RESULT); + reg_CP_DIVCNT = 0x2; + reg_CP_DIV_NUMER = 0x0100000000000000; + reg_CP_DIV_DENOM = l2; + reg_CP_SQRTCNT = 0x1; + reg_CP_SQRT_PARAM = l2 * 4; + while (reg_CP_SQRTCNT & 0x8000); //wait for sqrt to finish + fx32 sqrtresult = reg_CP_SQRT_RESULT; + while (reg_CP_DIVCNT & 0x8000); //wait for division to finish + l2 = reg_CP_DIV_RESULT; l2 = sqrtresult * l2; dst->x = (l2 * a->x + (1LL << (0x2D - 1))) >> 0x2D; dst->y = (l2 * a->y + (1LL << (0x2D - 1))) >> 0x2D; @@ -86,15 +86,15 @@ ARM_FUNC void VEC_Fx16Normalize(struct Vecx16 *a, struct Vecx16 *dst){ l2 += a->y * a->y; l2 += a->z * a->z; //1/sqrt(l) is computed by calculating sqrt(l)*(1/l) - SETREG16(HW_REG_DIVCNT, 0x2); - SETREG64(HW_REG_DIV_NUMER, 0x0100000000000000); - SETREG64(HW_REG_DIV_DENOM, l2); - SETREG16(HW_REG_SQRTCNT, 0x1); - SETREG64(HW_REG_SQRT_PARAM, l2 * 4); - while (READREG16(HW_REG_SQRTCNT) & 0x8000); //wait for sqrt to finish - fx32 sqrtresult = READREG32(HW_REG_SQRT_RESULT); - while (READREG16(HW_REG_DIVCNT) & 0x8000); //wait for division to finish - l2 = READREG64(HW_REG_DIV_RESULT); + reg_CP_DIVCNT = 0x2; + reg_CP_DIV_NUMER = 0x0100000000000000; + reg_CP_DIV_DENOM = l2; + reg_CP_SQRTCNT = 0x1; + reg_CP_SQRT_PARAM = l2 * 4; + while (reg_CP_SQRTCNT & 0x8000); //wait for sqrt to finish + fx32 sqrtresult = reg_CP_SQRT_RESULT; + while (reg_CP_DIVCNT & 0x8000); //wait for division to finish + l2 = reg_CP_DIV_RESULT; l2 = sqrtresult * l2; dst->x = (l2 * a->x + (1LL << (0x2D - 1))) >> 0x2D; dst->y = (l2 * a->y + (1LL << (0x2D - 1))) >> 0x2D; diff --git a/arm9/lib/src/OS_arena.c b/arm9/lib/src/OS_arena.c index eb04e60b..ae05b49c 100644 --- a/arm9/lib/src/OS_arena.c +++ b/arm9/lib/src/OS_arena.c @@ -5,8 +5,8 @@ #include "consts.h"
#include "OS_arena.h"
#include "OS_protectionRegion.h"
+#include "OS_emulator.h"
-extern u32 OS_GetConsoleType();
extern BOOL OSi_MainExArenaEnabled;
extern BOOL OSi_Initialized; // TODO: located at 0x021d36f0
void SDK_MAIN_ARENA_LO(); // TODO: technically this should be defined in the lcf
diff --git a/arm9/lib/src/OS_emulator.c b/arm9/lib/src/OS_emulator.c new file mode 100644 index 00000000..1be0e163 --- /dev/null +++ b/arm9/lib/src/OS_emulator.c @@ -0,0 +1,18 @@ +// +// Created by red031000 on 2020-05-05. +// + +#include "OS_emulator.h" +#include "function_target.h" + +extern u32 OSi_ConsoleTypeCache; //todo fix bss + +ARM_FUNC BOOL OS_IsRunOnEmulator() { + return FALSE; +} + +ARM_FUNC u32 OS_GetConsoleType() { + OSi_ConsoleTypeCache = OS_CONSOLE_NITRO | OS_CONSOLE_DEV_CARD | OS_CONSOLE_SIZE_4MB; + + return OSi_ConsoleTypeCache; +} diff --git a/arm9/lib/src/OS_init.c b/arm9/lib/src/OS_init.c index 90b01ffa..7467c672 100644 --- a/arm9/lib/src/OS_init.c +++ b/arm9/lib/src/OS_init.c @@ -7,14 +7,12 @@ extern void PXI_Init(); extern void OS_InitLock(); -extern void OS_InitIrqTable(); extern void OS_SetIrqStackChecker(); extern void OS_InitException(); extern void MI_Init(); extern void OS_InitVAlarm(); extern void OSi_InitVramExclusive(); extern void OS_InitThread(); -extern void OS_InitReset(); extern void CTRDG_Init(); extern void CARD_Init(); extern void PM_Init(); diff --git a/arm9/lib/src/OS_interrupt.c b/arm9/lib/src/OS_interrupt.c new file mode 100644 index 00000000..1fb43821 --- /dev/null +++ b/arm9/lib/src/OS_interrupt.c @@ -0,0 +1,89 @@ +// +// Created by red031000 on 2020-05-07. +// + +#include "consts.h" +#include "function_target.h" +#include "OS_interrupt.h" +#include "OS_thread.h" + +#pragma optimize_for_size on + +extern OSThreadQueue OSi_IrqThreadQueue; +extern OSIrqMask OS_EnableIrqMask(OSIrqMask intr); + +ARM_FUNC void OS_InitIrqTable() { + OS_InitThreadQueue(&OSi_IrqThreadQueue); +} + +ARM_FUNC void OS_SetIrqFunction(OSIrqMask intrBit, OSIrqFunction function) { + s32 i; + OSIrqCallbackInfo *info; + + for (i = 0; i < 0x16; i++) { + if (intrBit & 1) { + info = NULL; + + if (8 <= i && i <= 11) { + info = &OSi_IrqCallbackInfo[i - 8]; + } + else if (3 <= i && i <= 6) { + info = &OSi_IrqCallbackInfo[i - 3 + 4]; + } + else { + OS_IRQTable[i] = function; + } + + if (info) { + info->func = (void (*)(void *))function; + info->arg = 0; + info->enable = TRUE; + } + } + intrBit >>= 1; + } +} + +ARM_FUNC OSIrqFunction OS_GetIrqFunction(OSIrqMask intrBit) { + s32 i = 0; + OSIrqFunction *funcPtr = &OS_IRQTable[0]; + + do { + if (intrBit & 1) + { + if (8 <= i && i <= 11) { + i = i - 8; + return (void (*)(void))OSi_IrqCallbackInfo[i].func; + } + else if (3 <= i && i <= 6) { + i++; + return (void (*)(void))OSi_IrqCallbackInfo[i].func; + } + + return *funcPtr; + } + intrBit >>= 1; + funcPtr++; + i++; + } while (i < 0x16); + return 0; +} + +ARM_FUNC void OSi_EnterDmaCallback(u32 dmaNo, void (*callback) (void *), void *arg) +{ + OSIrqMask mask = 1UL << (dmaNo + 8); + OSi_IrqCallbackInfo[dmaNo].func = callback; + OSi_IrqCallbackInfo[dmaNo].arg = arg; + + OSi_IrqCallbackInfo[dmaNo].enable = OS_EnableIrqMask(mask) & mask; +} + +ARM_FUNC void OSi_EnterTimerCallback(u32 timerNo, void (*callback) (void *), void *arg) +{ + OSIrqMask mask = 1UL << (timerNo + 3); + OSi_IrqCallbackInfo[timerNo + 4].func = callback; + OSi_IrqCallbackInfo[timerNo + 4].arg = arg; + + (void)OS_EnableIrqMask(mask); + OSi_IrqCallbackInfo[timerNo + 4].enable = TRUE; +} diff --git a/arm9/lib/src/OS_printf.c b/arm9/lib/src/OS_printf.c new file mode 100644 index 00000000..ba484df8 --- /dev/null +++ b/arm9/lib/src/OS_printf.c @@ -0,0 +1,1248 @@ +#include "global.h" +#include "OS_printf.h" + +struct printfStr +{ + s32 spaceLeft; + s8 *stringEnd; + s8 *stringStart; +}; + +void string_put_char(struct printfStr *dest, s8 value); +void string_fill_char(struct printfStr *dest, s8 value, s32 count); +void string_put_string(struct printfStr *dest, const s8 *src, s32 count); + + +#ifndef NONMATCHING +// c definition is at the bottom of the file +u64 _ll_udiv(u64 a, u64 b); + +ARM_FUNC asm s32 OS_VSNPrintf(s8 *buffer, s32 bufsz, const s8 *format, void *args) +{ + stmdb sp!, {r4-r11,lr} + sub sp, sp, #0x64 + mov r9, r2 + str r1, [sp, #0x54] + str r0, [sp, #0x5c] + str r0, [sp, #0x58] + ldrsb r0, [r9, #0x0] + str r1, [sp, #0x0] + mov r11, r3 + cmp r0, #0x0 + beq _020CAD18 + mov r0, #0xa + str r0, [sp, #0xc] + mov r0, #0x0 + str r0, [sp, #0x4] + mov r0, #0x20 + str r0, [sp, #0x1c] + mov r0, #0x30 + str r0, [sp, #0x20] + mvn r0, #0x0 + str r0, [sp, #0x8] + mov r0, #0x57 + str r0, [sp, #0x10] + mov r0, #0x8 + str r0, [sp, #0x14] + mov r0, #0x37 + str r0, [sp, #0x18] + mov r0, #0x10 + str r0, [sp, #0x24] + mov r0, #0x1 + str r0, [sp, #0x28] + mov r0, #0x2b + str r0, [sp, #0x34] + mov r0, #0x2d + str r0, [sp, #0x30] + mov r0, #0x2 + str r0, [sp, #0x2c] +_020CA530: + ldrsb r1, [r9, #0x0] + and r0, r1, #0xff + eor r0, r0, #0x20 + sub r0, r0, #0xa1 + cmp r0, #0x3c + bhs _020CA56C + add r0, sp, #0x54 + bl string_put_char + ldrsb r1, [r9, #0x1]! + cmp r1, #0x0 + beq _020CAD0C + add r0, sp, #0x54 + add r9, r9, #0x1 + bl string_put_char + b _020CAD0C +_020CA56C: + cmp r1, #0x25 + beq _020CA584 + add r0, sp, #0x54 + add r9, r9, #0x1 + bl string_put_char + b _020CAD0C +_020CA584: + ldr r6, [sp, #0x4] + ldr r5, [sp, #0x8] + ldr r2, [sp, #0xc] + ldr r0, [sp, #0x10] + mov r10, r6 + mov r3, r9 +_020CA59C: + ldrsb r4, [r9, #0x1]! + cmp r4, #0x20 + bgt _020CA5B4 + cmp r4, #0x20 + beq _020CA5F4 + b _020CA60C +_020CA5B4: + cmp r4, #0x30 + bgt _020CA60C + cmp r4, #0x2b + blt _020CA60C + cmp r4, #0x2b + beq _020CA5E0 + cmp r4, #0x2d + beq _020CA5FC + cmp r4, #0x30 + beq _020CA604 + b _020CA60C +_020CA5E0: + ldrsb r1, [r9, #-0x1] + cmp r1, #0x20 + bne _020CA60C + orr r6, r6, #0x2 + b _020CA59C +_020CA5F4: + orr r6, r6, #0x1 + b _020CA59C +_020CA5FC: + orr r6, r6, #0x8 + b _020CA59C +_020CA604: + orr r6, r6, #0x10 + b _020CA59C +_020CA60C: + cmp r4, #0x2a + bne _020CA640 + add r11, r11, #0x4 + ldr r10, [r11, #-0x4] + add r9, r9, #0x1 + cmp r10, #0x0 + rsblt r10, r10, #0x0 + orrlt r6, r6, #0x8 + b _020CA654 +_020CA630: + ldrsb r4, [r9], #0x1 + mov r1, #0xa + mla r1, r10, r1, r4 + sub r10, r1, #0x30 +_020CA640: + ldrsb r1, [r9, #0x0] + cmp r1, #0x30 + blt _020CA654 + cmp r1, #0x39 + ble _020CA630 +_020CA654: + ldrsb r1, [r9, #0x0] + cmp r1, #0x2e + bne _020CA6AC + ldrsb r1, [r9, #0x1]! + ldr r5, [sp, #0x4] + cmp r1, #0x2a + bne _020CA698 + add r11, r11, #0x4 + ldr r5, [r11, #-0x4] + add r9, r9, #0x1 + cmp r5, #0x0 + ldrlt r5, [sp, #0x8] + b _020CA6AC +_020CA688: + ldrsb r4, [r9], #0x1 + mov r1, #0xa + mla r1, r5, r1, r4 + sub r5, r1, #0x30 +_020CA698: + ldrsb r1, [r9, #0x0] + cmp r1, #0x30 + blt _020CA6AC + cmp r1, #0x39 + ble _020CA688 +_020CA6AC: + ldrsb r1, [r9, #0x0] + cmp r1, #0x68 + beq _020CA6C4 + cmp r1, #0x6c + beq _020CA6DC + b _020CA6F0 +_020CA6C4: // h + ldrsb r1, [r9, #0x1]! + cmp r1, #0x68 + orrne r6, r6, #0x40 + addeq r9, r9, #0x1 + orreq r6, r6, #0x100 + b _020CA6F0 +_020CA6DC: // l + ldrsb r1, [r9, #0x1]! + cmp r1, #0x6c + orrne r6, r6, #0x20 + addeq r9, r9, #0x1 + orreq r6, r6, #0x80 +_020CA6F0: + ldrsb r1, [r9, #0x0] + cmp r1, #0x69 + bgt _020CA740 + cmp r1, #0x63 + blt _020CA720 + cmp r1, #0x63 + beq _020CA7B4 + cmp r1, #0x64 + beq _020CA96C + cmp r1, #0x69 + beq _020CA96C + b _020CA950 +_020CA720: + cmp r1, #0x25 + bgt _020CA734 + cmp r1, #0x25 + beq _020CA934 + b _020CA950 +_020CA734: + cmp r1, #0x58 + beq _020CA7A0 + b _020CA950 +_020CA740: + cmp r1, #0x6e + bgt _020CA754 + cmp r1, #0x6e + beq _020CA8DC + b _020CA950 +_020CA754: + sub r1, r1, #0x6f + cmp r1, #0x9 + addls pc, pc, r1, lsl #0x2 + b _020CA950 +_020CA764: + b _020CA78C + b _020CA7A8 + b _020CA950 + b _020CA950 + b _020CA828 + b _020CA950 + b _020CA798 + b _020CA950 + b _020CA950 + b _020CA964 +_020CA78C: + ldr r2, [sp, #0x14] + orr r6, r6, #0x1000 + b _020CA96C +_020CA798: + orr r6, r6, #0x1000 + b _020CA96C +_020CA7A0: + ldr r0, [sp, #0x18] + b _020CA964 +_020CA7A8: + orr r6, r6, #0x4 + ldr r5, [sp, #0x14] + b _020CA964 +_020CA7B4: + cmp r5, #0x0 + bge _020CA950 + ands r0, r6, #0x8 + add r11, r11, #0x4 + ldr r4, [r11, #-0x4] + beq _020CA7F0 + mov r0, r4, lsl #0x18 + mov r1, r0, asr #0x18 + add r0, sp, #0x54 + bl string_put_char + ldr r1, [sp, #0x1c] + sub r2, r10, #0x1 + add r0, sp, #0x54 + bl string_fill_char + b _020CA820 +_020CA7F0: + ands r0, r6, #0x10 + ldrne r0, [sp, #0x20] + sub r2, r10, #0x1 + ldreq r0, [sp, #0x1c] + mov r0, r0, lsl #0x18 + mov r1, r0, asr #0x18 + add r0, sp, #0x54 + bl string_fill_char + mov r0, r4, lsl #0x18 + mov r1, r0, asr #0x18 + add r0, sp, #0x54 + bl string_put_char +_020CA820: + add r9, r9, #0x1 + b _020CAD0C +_020CA828: + add r11, r11, #0x4 + cmp r5, #0x0 + ldr r7, [sp, #0x4] + ldr r4, [r11, #-0x4] + bge _020CA860 + ldrsb r0, [r4] + cmp r0, #0x0 + beq _020CA874 +_020CA848: + add r7, r7, #0x1 + ldrsb r0, [r4, r7] + cmp r0, #0x0 + bne _020CA848 + b _020CA874 +_020CA85C: + add r7, r7, #0x1 +_020CA860: + cmp r7, r5 + bge _020CA874 + ldrsb r0, [r4, r7] + cmp r0, #0x0 + bne _020CA85C +_020CA874: + ands r0, r6, #0x8 + sub r10, r10, r7 + beq _020CA8A4 + mov r1, r4 + mov r2, r7 + add r0, sp, #0x54 + bl string_put_string + ldr r1, [sp, #0x1C] + mov r2, r10 + add r0, sp, #0x54 + bl string_fill_char + b _020CA8D4 +_020CA8A4: + ands r0, r6, #0x10 + ldrne r0, [sp, #0x20] + mov r2, r10 + ldreq r0, [sp, #0x1C] + mov r0, r0, lsl #0x18 + mov r1, r0, asr #0x18 + add r0, sp, #0x54 + bl string_fill_char + mov r1, r4 + mov r2, r7 + add r0, sp, #0x54 + bl string_put_string +_020CA8D4: + add r9, r9, #0x1 + b _020CAD0C +_020CA8DC: + ands r0, r6, #0x100 + ldr r1, [sp, #0x58] + ldr r0, [sp, #0x5c] + sub r2, r1, r0 + bne _020CA92C + ands r0, r6, #0x40 + addne r11, r11, #0x4 + ldrne r0, [r11, #-0x4] + strneh r2, [r0, #0x0] + bne _020CA92C + ands r0, r6, #0x80 + addeq r11, r11, #0x4 + ldreq r0, [r11, #-0x4] + streq r2, [r0, #0x0] + beq _020CA92C + add r11, r11, #0x4 + ldr r0, [r11, #-0x4] + mov r1, r2, asr #0x1f + str r2, [r0, #0x0] + str r1, [r0, #0x4] +_020CA92C: + add r9, r9, #0x1 + b _020CAD0C +_020CA934: + add r0, r3, #0x1 + cmp r0, r9 + bne _020CA950 + add r0, sp, #0x54 + add r9, r9, #0x1 + bl string_put_char + b _020CAD0C +_020CA950: + add r0, sp, #0x54 + mov r1, r3 + sub r2, r9, r3 + bl string_put_string + b _020CAD0C +_020CA964: + ldr r2, [sp, #0x24] + orr r6, r6, #0x1000 +_020CA96C: + ands r1, r6, #0x8 + bicne r6, r6, #0x10 + cmp r5, #0x0 + bicge r6, r6, #0x10 + ldrlt r5, [sp, #0x28] + ldr r7, [sp, #0x4] + ands r1, r6, #0x1000 + beq _020CAA20 + ands r1, r6, #0x100 + addne r11, r11, #0x4 + ldrneb r4, [r11, #-0x4] + movne r1, #0x0 + bne _020CA9D0 + ands r1, r6, #0x40 + addne r11, r11, #0x4 + ldrneh r4, [r11, #-0x4] + movne r1, #0x0 + bne _020CA9D0 + ands r1, r6, #0x80 + addne r11, r11, #0x8 + ldrne r1, [r11, #-0x4] + ldrne r4, [r11, #-0x8] + addeq r11, r11, #0x4 + ldreq r4, [r11, #-0x4] + moveq r1, #0x0 +_020CA9D0: + bic r6, r6, #0x3 + ands r3, r6, #0x4 + beq _020CAAD8 + cmp r2, #0x10 + bne _020CAA0C + mov r3, #0x0 + cmp r1, r3 + cmpeq r4, r3 + beq _020CAAD8 + ldr r3, [sp, #0x20] + ldr r7, [sp, #0x2c] + strb r3, [sp, #0x39] + add r3, r0, #0x21 + strb r3, [sp, #0x38] + b _020CAAD8 +_020CAA0C: + cmp r2, #0x8 + ldreq r3, [sp, #0x20] + ldreq r7, [sp, #0x28] + streqb r3, [sp, #0x38] + b _020CAAD8 +_020CAA20: + ands r1, r6, #0x100 + addne r11, r11, #0x4 + ldrnesb r4, [r11, #-0x4] + movne r1, r4, asr #0x1f + bne _020CAA64 + ands r1, r6, #0x40 + addne r11, r11, #0x4 + ldrnesh r4, [r11, #-0x4] + movne r1, r4, asr #0x1f + bne _020CAA64 + ands r1, r6, #0x80 + addne r11, r11, #0x8 + ldrne r4, [r11, #-0x8] + ldrne r1, [r11, #-0x4] + addeq r11, r11, #0x4 + ldreq r4, [r11, #-0x4] + moveq r1, r4, asr #0x1f +_020CAA64: + mov r3, #0x0 + and r8, r3, #0x0 + cmp r8, r3 + and r8, r1, #0x80000000 + cmpeq r8, r3 + beq _020CAAA0 + ldr r7, [sp, #0x30] + mvn r4, r4 + strb r7, [sp, #0x38] + mvn r7, r1 + mov r1, #0x1 + adds r4, r4, r1 + adc r1, r7, r3 + ldr r7, [sp, #0x28] + b _020CAAD8 +_020CAAA0: + cmp r1, r3 + cmpeq r4, r3 + bne _020CAAB4 + cmp r5, #0x0 + beq _020CAAD8 +_020CAAB4: + ands r3, r6, #0x2 + ldrne r3, [sp, #0x34] + ldrne r7, [sp, #0x28] + strneb r3, [sp, #0x38] + bne _020CAAD8 + ands r3, r6, #0x1 + ldrne r3, [sp, #0x1c] + ldrne r7, [sp, #0x28] + strneb r3, [sp, #0x38] +_020CAAD8: + cmp r2, #0x8 + ldr r8, [sp, #0x4] + beq _020CAAF8 + cmp r2, #0xa + beq _020CAB40 + cmp r2, #0x10 + beq _020CABDC + b _020CAC28 +_020CAAF8: + mov r0, #0x0 + cmp r1, r0 + cmpeq r4, r0 + beq _020CAC28 +_020CAB08: + and r0, r4, #0x7 + add r3, r0, #0x30 + add r0, sp, #0x3a + strb r3, [r0, r8] + mov r4, r4, lsr #0x3 + mov r2, #0x0 + mov r0, r1, lsr #0x3 + orr r4, r4, r1, lsl #0x1d + cmp r0, r2 + cmpeq r4, r2 + mov r1, r0 + add r8, r8, #0x1 + bne _020CAB08 + b _020CAC28 +_020CAB40: + mov r0, #0x0 + cmp r0, r0 + cmpeq r1, r0 + bne _020CAB8C + cmp r4, #0x0 + beq _020CAC28 +_020CAB58: + ldr r0, =0xCCCCCCCD + umull r1, r0, r4, r0 + movs r0, r0, lsr #0x3 + mov r1, #0xa + mul r1, r0, r1 + sub r1, r4, r1 + mov r4, r0 + add r1, r1, #0x30 + add r0, sp, #0x3a + strb r1, [r0, r8] + add r8, r8, #0x1 + bne _020CAB58 + b _020CAC28 +_020CAB8C: + cmp r1, r0 + cmpeq r4, r0 + beq _020CAC28 +_020CAB98: + ldr r2, [sp, #0xc] + ldr r3, [sp, #0x4] + mov r0, r4 + bl _ll_udiv + mov r3, #0xa + umull r3, r12, r0, r3 + subs r3, r4, r3 + mov r2, #0x0 + add r4, r3, #0x30 + add r3, sp, #0x3a + strb r4, [r3, r8] + cmp r1, r2 + cmpeq r0, r2 + mov r4, r0 + add r8, r8, #0x1 + bne _020CAB98 + b _020CAC28 +_020CABDC: + mov r2, #0x0 + cmp r1, r2 + cmpeq r4, r2 + beq _020CAC28 +_020CABEC: + and r3, r4, #0xf + cmp r3, #0xa + mov r4, r4, lsr #0x4 + addlt r3, r3, #0x30 + mov r2, r1, lsr #0x4 + orr r4, r4, r1, lsl #0x1c + mov r1, r2 + addge r3, r3, r0 + add r2, sp, #0x3a + strb r3, [r2, r8] + mov r2, #0x0 + cmp r1, r2 + add r8, r8, #0x1 + cmpeq r4, r2 + bne _020CABEC +_020CAC28: + cmp r7, #0x0 + ble _020CAC4C + ldrsb r0, [sp, #0x38] + cmp r0, #0x30 + ldreq r1, [sp, #0x20] + addeq r0, sp, #0x3a + streqb r1, [r0, r8] + ldreq r7, [sp, #0x4] + addeq r8, r8, #0x1 +_020CAC4C: + sub r5, r5, r8 + ands r0, r6, #0x10 + beq _020CAC68 + sub r0, r10, r8 + sub r0, r0, r7 + cmp r5, r0 + movlt r5, r0 +_020CAC68: + cmp r5, #0x0 + subgt r10, r10, r5 + add r0, r7, r8 + ands r6, r6, #0x8 + sub r10, r10, r0 + bne _020CAC90 + ldr r1, [sp, #0x1c] + add r0, sp, #0x54 + mov r2, r10 + bl string_fill_char +_020CAC90: + cmp r7, #0x0 + ble _020CACB8 + add r0, sp, #0x38 + add r4, r0, r7 +_020CACA0: + ldrsb r1, [r4, #-0x1]! + sub r7, r7, #0x1 + add r0, sp, #0x54 + bl string_put_char +_020CACB0: + cmp r7, #0x0 + bgt _020CACA0 +_020CACB8: + ldr r1, [sp, #0x20] + mov r2, r5 + add r0, sp, #0x54 + bl string_fill_char + cmp r8, #0x0 + ble _020CACF0 + add r0, sp, #0x3A + add r4, r0, r8 +_020CACD8: + ldrsb r1, [r4, #-0x1]! + sub r8, r8, #0x1 + add r0, sp, #0x54 + bl string_put_char + cmp r8, #0x0 + bgt _020CACD8 +_020CACF0: + cmp r6, #0x0 + beq _020CAD08 + ldr r1, [sp, #0x1C] + mov r2, r10 + add r0, sp, #0x54 + bl string_fill_char +_020CAD08: + add r9, r9, #0x1 +_020CAD0C: + ldrsb r0, [r9, #0x0] + cmp r0, #0x0 + bne _020CA530 +_020CAD18: + ldr r0, [sp, #0x54] + cmp r0, #0x0 + ldrne r0, [sp, #0x58] + movne r1, #0x0 + strneb r1, [r0, #0x0] + bne _020CAD48 + ldr r0, [sp, #0x0] + cmp r0, #0x0 + ldrne r1, [sp, #0x5c] + movne r2, #0x0 + addne r0, r1, r0 + strneb r2, [r0, #-0x1] +_020CAD48: + ldr r1, [sp, #0x58] + ldr r0, [sp, #0x5c] + sub r0, r1, r0 + add sp, sp, #0x64 + ldmia sp!, {r4-r11,lr} + bx lr +} +#endif + +ARM_FUNC void string_put_char(struct printfStr *dest, s8 value) +{ + if (dest->spaceLeft != 0) + { + dest->stringEnd[0] = value; + dest->spaceLeft--; + } + dest->stringEnd++; +} + +ARM_FUNC void string_fill_char(struct printfStr *dest, s8 value, s32 count) +{ + if (count <= 0) + return; + + u32 written = 0; + u32 spaceLeft = (u32)dest->spaceLeft; + u32 toWrite = spaceLeft > (u32)count ? count : spaceLeft; + + while (written < toWrite) + { + dest->stringEnd[written] = value; + written++; + } + + dest->spaceLeft -= toWrite; + dest->stringEnd += count; // this is wrong but matching... +} + +ARM_FUNC void string_put_string(struct printfStr *dest, const s8 *src, s32 count) +{ + if (count <= 0) + return; + + u32 written = 0; + u32 spaceLeft = (u32)dest->spaceLeft; + u32 toWrite = spaceLeft > (u32)count ? count : spaceLeft; + + while (written < toWrite) + { + dest->stringEnd[written] = src[written]; + written++; + } + + dest->spaceLeft -= toWrite; + dest->stringEnd += count; // this is wrong but matching... +} + +ARM_FUNC s32 OS_SPrintf(s8 *buffer, const s8 *format, ...) +{ + void *args = (void *)((u32 *)((u32)&format & ~0x3) + 1); // hack since mwccarm doesn't have <stdarg.h> apparently + return OS_VSPrintf(buffer, format, args); +} + +ARM_FUNC s32 OS_VSPrintf(s8 *buffer, const s8 *format, void *args) +{ + return OS_VSNPrintf(buffer, 0x7FFFFFFF, format, args); +} + +ARM_FUNC s32 OS_SNPrintf(s8 *buffer, s32 bufsz, const s8 *format, ...) +{ + void *args = (void *)((u32 *)((u32)&format & ~0x3) + 1); // hack since mwccarm doesn't have <stdarg.h> apparently + return OS_VSNPrintf(buffer, bufsz, format, args); +} + +#ifdef NONMATCHING + +struct Unk +{ + s32 unk00; + s32 unk04; + s32 unk08; + s32 unk0C; + s32 unk10; + s32 unk14; + s32 unk18; + s32 unk1C; + s32 unk20; + s32 unk24; + s32 unk28; + s32 unk2C; + s32 unk30; + s32 unk34; + s8 unk38; + s8 unk39; + s8 unk3A; + // not sure about this struct's size or even if it's a single struct +}; + +#define va_arg(list, ty) *(ty *)((u32 *)(list = (void *)((u32 *)(list) + 1)) - 1) +#define va_arg_64(list, sgn) *((sgn##64 *)(list = (void *)((sgn##64 *)(list) + 1)) - 1) + +ARM_FUNC s32 OS_VSNPrintf(s8 *buffer, s32 bufsz, const s8 *format, void *args) +{ + struct printfStr str; + struct Unk unk; + str.spaceLeft = bufsz; + str.stringStart = buffer; + str.stringEnd = buffer; + + if (*format != 0) + { + // these assignments are likely wrong + unk.unk04 = 0; + unk.unk0C = 10; + unk.unk1C = 32; + unk.unk20 = 48; + unk.unk08 = 0; + unk.unk10 = 87; + unk.unk14 = 8; + unk.unk18 = 55; + unk.unk24 = 16; + unk.unk28 = 1; + unk.unk34 = 43; + unk.unk30 = 45; + unk.unk2C = 2; + + + do + { + s8 c = *format; + u32 x = (u8)c; + + // matches: + // binary range (hex range) [dec range] + // 1000 0001-1001 1111 (0x81-0x9F) [129-159] + // 1110 0000-1111 1100 (0xE0-0xFC) [224-252] + if ((x ^ 0x20) - 0xa1 < 0x3c) + { + string_put_char(&str, c); + c = *(++format); + if (c != 0) + { + format++; + string_put_char(&str, c); + } + } + else if (c != '%') + { + format++; + string_put_char(&str, c); + } + else + { + s32 flags = unk.unk04; + s32 r5 = unk.unk08; + s32 r2 = unk.unk0C; + s32 r0 = unk.unk10; + s32 r10 = flags; + const s8 *r3 = format; + s8 r4; + while (1) + { + r4 = *(++format); + switch (r4) + { + case '+': + c = *(format - 1); + if (c == ' ') + goto post_padding; + flags |= 0x2; + break; + case ' ': + flags |= 0x1; + break; + case '-': + flags |= 0x8; + break; + case '0': + flags |= 0x10; + break; + default: + goto post_padding; + } + } + post_padding: + if (r4 == '*') + { + u32 v = va_arg(args, u32); + format++; + if (v < 0) + { + r10 = -r10; + flags |= 0x8; + } + } + else + { + for (c = *format; c >= '0' && c <= '9'; c = *format) + { + s8 d = *(format++); + r10 = (r10 * 10 + d) - '0'; + } + } + + c = *format; + if (c == '.') + { + c = *(++format); + r5 = unk.unk04; + if (c == '*') + { + u32 v = va_arg(args, u32); + format++; + if (v < 0) + { + r5 = unk.unk08; + } + } + for (c = *format; c >= '0' && c <= '9'; c = *format) + { + s8 d = *(format++); + r5 = (r5 * 10 + d) - '0'; + } + } + + c = *format; + switch (c) + { + case 'h': + c = *format++; + if (c != 'h') + { + flags |= 0x40; + format++; + flags |= 0x100; + } + break; + case 'l': + c = *format++; + if (c != 'l') + { + flags |= 0x20; + format++; + flags |= 0x80; + } + break; + } + + c = *format; + switch (c) + { + case 'o': + r2 = unk.unk14; + flags |= 0x1000; + break; + case 'u': + flags |= 0x1000; + break; + case 'X': + r0 = unk.unk18; + goto case_x; + case 'p': + flags |= 0x4; + r5 = unk.unk14; + case 'c': + if ((s32)r5 < 0) + { + r0 = flags & 0x8; + u32 v = va_arg(args, u32); + if (r0) + { + string_put_char(&str, (s8)v); + string_fill_char(&str, (s8)unk.unk1C, r10 - 1); + } + else + { + r0 = flags & 0x10; + if (r0) + r0 = unk.unk20; + else + r0 = unk.unk1C; + string_fill_char(&str, (s8)r0, r10 - 1); + string_put_char(&str, (s8)v); + } + format++; + } + break; + case 's': + { + s8 *v = *(((s8 **)args)++); + s32 count = unk.unk04; + if (r5 < 0) + { + while (v[count] != 0) + { + count++; + } + } + else + { + while (count < r5 && v[count] != 0) + { + count++; + } + } + r0 = flags & 0x8; + r10 = r10 - count; + if (r0) + { + string_put_string(&str, v, count); + string_fill_char(&str, (s8)unk.unk1C, r10); + } + else + { + r0 = flags & 0x10; + if (r0) + r0 = unk.unk20; + else + r0 = unk.unk1C; + string_fill_char(&str, (s8)r0, r10 - 1); + string_put_string(&str, v, count); + } + format++; + break; + } + case 'n': + { + r0 = flags & 0x100; + s32 count = str.stringEnd - str.stringStart; + if (!r0) + { + if (flags & 0x40) + { + s16 *v = va_arg(args, s16 *); + *v = (s16)count; + } + else if (flags & 0x80) + { + s64 *v = va_arg(args, s64 *); + *v = count; + } + else + { + s64 *v = va_arg(args, s64 *); + *v = count; + } + } + format++; + } + case '%': + if (r3 + 1 == format) + { + format++; + string_put_char(&str, c); + break; + } + else + { + string_put_string(&str, r3, format - r3); + break; + } + case 'x': + case_x: + r2 = unk.unk24; + flags |= 0x1000; + case 'd': + case 'i': + if (flags & 0x8) + { + flags = flags & ~0x10; + } + if (r5 >= 0) + { + flags = flags & ~0x10; + } + else + { + r5 = unk.unk28; + } + s32 r7 = unk.unk04; + u64 value; + if (flags & 0x1000) + { + if (flags & 0x100) + { + value = va_arg(args, u8); + } + else if (flags & 0x40) + { + value = va_arg(args, u16); + } + else if (flags & 0x80) + { + value = va_arg_64(args, u); + } + else + { + value = va_arg(args, u32); + } + flags = flags & ~0x3; + if (flags & 0x4) + { + if (r2 == 0x10) + { + if (value != 0) + { + s32 something = unk.unk20; + s32 somethingElse = unk.unk2C; + unk.unk39 = (s8)something; + unk.unk38 = (s8)(something + 0x21); + // 0x21 could be 'a'-'A'+1 + } + } + else + { + if (r2 == 0x8) + { + s32 something = unk.unk20; + r7 = unk.unk28; + unk.unk38 = (s8)(something); + } + } + } + } + else + { + if (flags & 0x100) + { + s32 x = (s32)va_arg(args, s8); + value = (u64)x; + } + else if (flags & 0x40) + { + s32 x = (s32)va_arg(args, s16); + value = (u64)x; + } + else if (flags & 0x80) + { + s64 dWord = va_arg_64(args, s); + value = (u64)dWord; + } + else + { + s32 x = va_arg(args, s32); + value = (u64)value; + } + + if (value & 0x8000000000000000) + { + unk.unk38 = (s8)unk.unk30; + value = ~value + 1; + r7 = unk.unk28; + } + else + { + if (value || r5) + { + if (flags & 0x2) + { + r7 = unk.unk28; + unk.unk38 = (s8)unk.unk34; + } + else if (flags & 0x1) + { + r7 = unk.unk28; + unk.unk38 = (s8)unk.unk1C; + } + } + } + s32 r8 = flags; + switch (r2) + { + case 8: + while (value != 0) + { + u32 octDig = ((u32)value & 0x7) + '0'; + s8 *p = &unk.unk3A; + p[r8] = (s8)octDig; + value = value >> 3; + r8++; + } + break; + case 10: + if (value >> 32 == 0) + { + u32 v = (u32)value; + while (v) + { + u32 div10 = v / 10; + u32 dig = v - div10; + v = div10; + s8 *p = &unk.unk3A; + p[r8] = (s8)dig; + r8++; + } + } + else + { + while (value) + { + u64 div10 = value / 10; + u32 dig = (u32)(value - div10); + value = div10; + s8 *p = &unk.unk3A; + p[r8] = (s8)dig; + r8++; + } + } + break; + case 16: + while (value != 0) + { + u32 hexDig = ((u32)value & 0xf); + value = value >> 4; + if (hexDig < 10) + hexDig = hexDig + '0'; + else + hexDig = hexDig + r0; + s8 *p = &unk.unk3A; + p[r8] = (s8)hexDig; + r8++; + } + break; + } + if (r7 > 0) + { + if (unk.unk38 == '0') + { + s8 *p = &unk.unk3A; + p[r8] = (s8)unk.unk20; + r7 = flags; + r8++; + } + r5 = r5 - r8; + if (flags & 0x10) + { + if (r5 < r10 - r8 - r7) + { + r5 = r10 - r8 - r7; + } + } + if (r5 > 0) + { + r10 = r10 - r5; + } + + r10 = r10 - (r7 + r8); + flags = flags & 0x8; + if (!flags) + { + string_fill_char(&str, (s8)unk.unk1C, r10); + } + s8 *x = &unk.unk38 + r7; + while (r7 > 0) + { + s8 ch = *(x--); + r7--; + string_put_char(&str, ch); + } + string_fill_char(&str, (s8)unk.unk20, r5); + x = &unk.unk3A + r8; + while (r8 > 0) + { + s8 ch = *(x--); + r8--; + string_put_char(&str, ch); + } + if (flags) + { + string_fill_char(&str, (s8)unk.unk1C, r10); + } + } + } + format++; + break; + } + if (str.spaceLeft != 0) + { + *str.stringEnd = 0; + } + else if (unk.unk00 != 0) + { + *(str.stringStart + unk.unk00 - 1) = 0; + } + } + } while (*format != 0); + } + + if (str.spaceLeft != 0) + { + *str.stringEnd = 0; + } + else if (unk.unk00 != 0) + { + str.stringStart[unk.unk00] = 0; + } + return str.stringEnd - str.stringStart; +} + +#endif diff --git a/arm9/lib/src/OS_reset.c b/arm9/lib/src/OS_reset.c new file mode 100644 index 00000000..c21d20ab --- /dev/null +++ b/arm9/lib/src/OS_reset.c @@ -0,0 +1,62 @@ +// +// Created by red031000 on 2020-05-06. +// + +#include "function_target.h" +#include "OS_reset.h" +#include "MB_mb.h" +#include "OS_terminate_proc.h" + +extern u16 OSi_IsInitReset; +extern vu16 OSi_IsResetOccurred; +extern void PXI_Init(); +extern u32 PXI_IsCallbackReady(u32 param1, u32 param2); +extern void PXI_SetFifoRecvCallback(u32 param1, void* callback); +extern u32 PXI_SendWordByFifo(u32 param1, u32 data, u32 param2); +extern void CARD_LockRom(u16 lockId); +extern void MI_StopDma(u32 dma); +extern void OS_SetIrqMask(u32 mask); +extern void OS_ResetRequestIrqMask(u32 mask); +extern void OSi_DoResetSystem(); //in itcm, should technically be in this file + +ARM_FUNC void OS_InitReset() { + if (OSi_IsInitReset) { + return; + } + OSi_IsInitReset = TRUE; + PXI_Init(); + while (!PXI_IsCallbackReady(PXI_FIFO_TAG_OS, PXI_PROC_ARM7)) { } + + PXI_SetFifoRecvCallback(PXI_FIFO_TAG_OS, OSi_CommonCallback); +} + +ARM_FUNC static void OSi_CommonCallback(PXIFifoTag tag, u32 data, BOOL err) { +#pragma unused(tag, err) //needed because otherwise -W all errors + u16 command = (u16)((data & OS_PXI_COMMAND_MASK) >> OS_PXI_COMMAND_SHIFT); + if (command == OS_PXI_COMMAND_RESET) + { + OSi_IsResetOccurred = TRUE; + return; + } + OS_Terminate(); +} + +ARM_FUNC static void OSi_SendToPxi(u16 data) { + while (PXI_SendWordByFifo(PXI_FIFO_TAG_OS, (u32)data << 0x8, FALSE)) {} +} + +ARM_FUNC void OS_ResetSystem(u32 parameter) { + if (MB_IsMultiBootChild()) { + OS_Terminate(); + } + CARD_LockRom((u16)OS_GetLockID()); + MI_StopDma(0); + MI_StopDma(1); + MI_StopDma(2); + MI_StopDma(3); + OS_SetIrqMask(0x40000); + OS_ResetRequestIrqMask((u32)~0); + *(u32 *)HW_RESET_PARAMETER_BUF = parameter; + OSi_SendToPxi(OS_PXI_COMMAND_RESET); + OSi_DoResetSystem(); //oh boy this is in itcm, that's gonna be fun to deal with Kappa +} diff --git a/arm9/lib/src/OS_system.c b/arm9/lib/src/OS_system.c index c2b08681..e5dfcb47 100644 --- a/arm9/lib/src/OS_system.c +++ b/arm9/lib/src/OS_system.c @@ -2,7 +2,6 @@ // Created by mart on 4/23/20. // -#include "function_target.h" #include "OS_system.h" ARM_FUNC asm OSIntrMode OS_EnableInterrupts() { diff --git a/arm9/lib/src/OS_tcm.c b/arm9/lib/src/OS_tcm.c new file mode 100644 index 00000000..5a168c58 --- /dev/null +++ b/arm9/lib/src/OS_tcm.c @@ -0,0 +1,13 @@ +// +// Created by red031000 on 2020-05-05. +// + +#include "OS_tcm.h" +#include "function_target.h" + +ARM_FUNC asm u32 OS_GetDTCMAddress() { + mrc p15, 0x0, r0, c9, c1, 0x0 + ldr r1, =OSi_TCM_REGION_BASE_MASK + and r0, r0, r1 + bx lr +} diff --git a/arm9/lib/src/OS_terminate_proc.c b/arm9/lib/src/OS_terminate_proc.c new file mode 100644 index 00000000..eb267c6b --- /dev/null +++ b/arm9/lib/src/OS_terminate_proc.c @@ -0,0 +1,21 @@ +// +// Created by red031000 on 2020-05-07. +// + +#include "types.h" +#include "OS_terminate_proc.h" +#include "function_target.h" +#include "OS_system.h" + +ARM_FUNC void OS_Terminate() { + while (TRUE) { + (void)OS_DisableInterrupts(); + OS_Halt(); + } +} + +ARM_FUNC asm void OS_Halt() { + mov r0, #0x0 + mcr p15, 0x0, r0, c7, c0, 0x4 + bx lr +} |