diff options
author | PikalaxALT <pikalaxalt@gmail.com> | 2020-05-07 17:53:16 -0400 |
---|---|---|
committer | PikalaxALT <pikalaxalt@gmail.com> | 2020-05-07 17:53:16 -0400 |
commit | 34ec05f983cec0517765640d084f58e86aa20d79 (patch) | |
tree | e07f5b2f882f1c498093d4fc936975f9e90ed5f6 /arm9/lib/src | |
parent | 13ecb2f5cb0bbfee814508f6d05d05074d426807 (diff) |
Finish FS_archive.c
Diffstat (limited to 'arm9/lib/src')
-rw-r--r-- | arm9/lib/src/FS_archive.c | 163 |
1 files changed, 161 insertions, 2 deletions
diff --git a/arm9/lib/src/FS_archive.c b/arm9/lib/src/FS_archive.c index c8404144..44a4e451 100644 --- a/arm9/lib/src/FS_archive.c +++ b/arm9/lib/src/FS_archive.c @@ -42,9 +42,9 @@ FSResult FSi_WriteMemCallback(struct FSArchive * p_arc, const void * src, u32 po return FS_RESULT_SUCCESS; } -FSResult FSi_ReadMemoryCore(FSArchive * p_arc, u8 * dest, u32 offset, u32 size) +FSResult FSi_ReadMemoryCore(FSArchive * p_arc, void * dest, u32 pos, u32 size) { - MI_CpuCopy8((const void *)offset, dest, size); + MI_CpuCopy8((const void *)pos, dest, size); return FS_RESULT_SUCCESS; } @@ -283,3 +283,162 @@ BOOL FS_LoadArchive(FSArchive * p_arc, u32 base, u32 fat, u32 fat_size, u32 fnt, p_arc->flag |= FS_ARCHIVE_FLAG_LOADED; return TRUE; } + +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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +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; +} + +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); + } +} |