diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 5dbd2c35..c4892f16 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -338,6 +338,13 @@ nw4r/db/db_directPrint.cpp: .sbss start:0x805765E8 end:0x805765EC .bss start:0x80636B80 end:0x80636BA4 +nw4r/db/db_mapFile.cpp: + .text start:0x80436A50 end:0x804373B4 + .data start:0x8056C5F0 end:0x8056C600 + .sdata start:0x80574E10 end:0x80574E24 + .sbss start:0x80576600 end:0x8057660C + .bss start:0x8063B320 end:0x8063B560 + nw4r/db/db_assert.cpp: .text start:0x804373C0 end:0x804373D0 .sbss start:0x80576610 end:0x80576618 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 30c5841e..430c679a 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -21975,7 +21975,7 @@ OSLinkFixed = .text:0x803A9AF0; // type:function size:0x1C fn_803A9B10 = .text:0x803A9B10; // type:function size:0x240 OSUnlink = .text:0x803A9D50; // type:function size:0x1D4 __OSModuleInit = .text:0x803A9F30; // type:function size:0x18 scope:global -fn_803A9F50 = .text:0x803A9F50; // type:function size:0xA4 +OSSearchModule = .text:0x803A9F50; // type:function size:0xA4 OSInitMessageQueue = .text:0x803AA000; // type:function size:0x60 OSSendMessage = .text:0x803AA060; // type:function size:0xC8 OSReceiveMessage = .text:0x803AA130; // type:function size:0xDC @@ -24179,10 +24179,10 @@ GetCharOnMem___Q24nw4r2dbFPCUc = .text:0x80436B40; // type:function size:0x8 GetCharOnDvd___Q24nw4r2dbFPCUc = .text:0x80436B50; // type:function size:0xFC SearchParam___Q24nw4r2dbFPUcUlUc = .text:0x80436C50; // type:function size:0xC4 XStrToU32___Q24nw4r2dbFPCUc = .text:0x80436D20; // type:function size:0xCC -CopySymbol___Q24nw4r2dbFPCUcPUcUlUc = .text:0x80436DF0; // type:function size:0x2DC -QuerySymbolToMapFile___Q24nw4r2dbFPUcPC12OSModuleInfoUlPUcUl = .text:0x804370D0; // type:function size:0xD8 +QuerySymbolToMapFile___Q24nw4r2dbFPUcPC12OSModuleInfoUlPUcUl = .text:0x80436DF0; // type:function size:0x2DC +UnkFunction___Q24nw4r2dbFPC12OSModuleInfoUlPUcUl = .text:0x804370D0; // type:function size:0xD8 QuerySymbolToSingleMapFile___Q24nw4r2dbFPQ34nw4r2db7MapFileUlPUcUl = .text:0x804371B0; // type:function size:0xF8 -MapFile_QuerySymbol__Q24nw4r2dbFPvPcUl = .text:0x804372B0; // type:function size:0x104 +MapFile_QuerySymbol__Q24nw4r2dbFUlPUcUl = .text:0x804372B0; // type:function size:0x104 Assertion_SetConsole__Q24nw4r2dbFPQ44nw4r2db6detail11ConsoleHead = .text:0x804373C0; // type:function size:0x10 FExp__Q34nw4r4math6detailFf = .text:0x804373D0; // type:function size:0xAC FLog__Q34nw4r4math6detailFf = .text:0x80437480; // type:function size:0xA4 @@ -36971,7 +36971,7 @@ lbl_8056C0B4 = .data:0x8056C0B4; // type:object size:0xC data:string lbl_8056C0C0 = .data:0x8056C0C0; // type:object size:0x14 lbl_8056C0D4 = .data:0x8056C0D4; // type:object size:0x14 lbl_8056C0E8 = .data:0x8056C0E8; // type:object size:0x508 -lbl_8056C5F0 = .data:0x8056C5F0; // type:object size:0x10 +lbl_8056C5F0 = .data:0x8056C5F0; // type:object size:0xD data:string lbl_8056C600 = .data:0x8056C600; // type:object size:0x108 lbl_8056C708 = .data:0x8056C708; // type:object size:0x808 lbl_8056CF10 = .data:0x8056CF10; // type:object size:0x110 @@ -39563,7 +39563,7 @@ lbl_80574E08 = .sdata:0x80574E08; // type:object size:0x8 lbl_80574E10 = .sdata:0x80574E10; // type:object size:0x4 data:4byte lbl_80574E14 = .sdata:0x80574E14; // type:object size:0x4 data:4byte lbl_80574E18 = .sdata:0x80574E18; // type:object size:0x4 data:4byte -lbl_80574E1C = .sdata:0x80574E1C; // type:object size:0xC +lbl_80574E1C = .sdata:0x80574E1C; // type:object size:0x5 data:string lbl_80574E28 = .sdata:0x80574E28; // type:object size:0x8 data:float lbl_80574E30 = .sdata:0x80574E30; // type:object size:0x8 data:string lbl_80574E38 = .sdata:0x80574E38; // type:object size:0x8 @@ -40835,9 +40835,9 @@ sInitialized__Q24nw4r2db = .sbss:0x805765E8; // type:object size:0x4 scope:local lbl_805765F0 = .sbss:0x805765F0; // type:object size:0x4 data:4byte lbl_805765F4 = .sbss:0x805765F4; // type:object size:0x1 data:byte lbl_805765F8 = .sbss:0x805765F8; // type:object size:0x8 -lbl_80576600 = .sbss:0x80576600; // type:object size:0x4 data:4byte -lbl_80576604 = .sbss:0x80576604; // type:object size:0x4 data:4byte -lbl_80576608 = .sbss:0x80576608; // type:object size:0x8 data:4byte +sFileLength__Q24nw4r2db = .sbss:0x80576600; // type:object size:0x4 scope:local data:4byte +sMapFileList__Q24nw4r2db = .sbss:0x80576604; // type:object size:0x4 scope:local data:4byte +GetCharPtr___Q24nw4r2db = .sbss:0x80576608; // type:object size:0x4 scope:local data:4byte sConsoleHandle__Q24nw4r2db = .sbss:0x80576610; // type:object size:0x4 scope:local data:4byte lbl_80576618 = .sbss:0x80576618; // type:object size:0x4 data:4byte lbl_8057661C = .sbss:0x8057661C; // type:object size:0x4 data:4byte @@ -49311,7 +49311,7 @@ lbl_80636BC0 = .bss:0x80636BC0; // type:object size:0x400 lbl_80636FC0 = .bss:0x80636FC0; // type:object size:0x360 lbl_80637320 = .bss:0x80637320; // type:object size:0x4000 lbl_8063B320 = .bss:0x8063B320; // type:object size:0x200 -lbl_8063B520 = .bss:0x8063B520; // type:object size:0x40 +lbl_8063B520 = .bss:0x8063B520; // type:object size:0x3C lbl_8063B560 = .bss:0x8063B560; // type:object size:0x300 lbl_8063B860 = .bss:0x8063B860; // type:object size:0x140 lbl_8063B9A0 = .bss:0x8063B9A0; // type:object size:0xC data:byte diff --git a/configure.py b/configure.py index 8ee3f7e1..7a62a83e 100644 --- a/configure.py +++ b/configure.py @@ -329,6 +329,7 @@ config.libs = [ [ Object(Matching, "nw4r/db/db_assert.cpp"), Object(Matching, "nw4r/db/db_directPrint.cpp"), + Object(Matching, "nw4r/db/db_mapFile.cpp"), ], ), nw4rLib( diff --git a/include/DynamicLink.h b/include/DynamicLink.h index 1e9e3319..da4a5a21 100644 --- a/include/DynamicLink.h +++ b/include/DynamicLink.h @@ -3,17 +3,19 @@ #include #include +#include #include class DbMapFile { public: - DbMapFile(): unk_0(0) {} + DbMapFile(): mMapFileHandle(nullptr) {} ~DbMapFile(); void RegisterOnDvd(const char *, const OSModuleInfo *); void Unregister(); private: - UNKWORD unk_0; + nw4r::db::MapFileHandle mMapFileHandle; + nw4r::db::MapFile mMapFile; }; // https://github.com/zeldaret/tp/blob/main/include/DynamicLink.h @@ -75,11 +77,6 @@ struct DynamicModuleControl : DynamicModuleControlBase { /* 0x2C */ mDvd_callback_c *mDvdCallbackRequest; /* 0x30 */ EGG::ExpHeap *mHeap; /* 0x34 */ DbMapFile mpRelMapFile; - // Some of these might be members of DbMapFile - UNKWORD unk1; - UNKWORD unk2; - UNKWORD unk3; - UNKWORD unk4; static u32 sAllocBytes; static mDvd_toMainRam_base_c *sDvdFile; diff --git a/include/MSL_C/MSL_Common/Src/printf.h b/include/MSL_C/MSL_Common/Src/printf.h index 5b1a7ccd..5e35c0f4 100644 --- a/include/MSL_C/MSL_Common/Src/printf.h +++ b/include/MSL_C/MSL_Common/Src/printf.h @@ -10,8 +10,8 @@ extern "C" { int fprintf(FILE* stream, const char* format, ...); int printf(const char* format, ...); -int sprintf(const char* str, const char* format, ...); -int snprintf(const char* str, size_t n, const char* format, ...); +int sprintf(char* str, const char* format, ...); +int snprintf(char* str, size_t n, const char* format, ...); int vsnprintf(char* str, size_t n, const char* format, va_list arg); int vprintf(const char* format, va_list arg); diff --git a/include/nw4r/db/db_mapFile.h b/include/nw4r/db/db_mapFile.h new file mode 100644 index 00000000..2eb2aac6 --- /dev/null +++ b/include/nw4r/db/db_mapFile.h @@ -0,0 +1,26 @@ +#ifndef DB_MAPFILE_H +#define DB_MAPFILE_H + +#include + +namespace nw4r { +namespace db { + +typedef struct MapFile { + u8 *mapBuf; + const OSModuleInfo *moduleInfo; + s32 fileEntry; + MapFile *next; +} MapFile; + +typedef MapFile* MapFileHandle; + +MapFileHandle MapFile_RegistOnDvd(void*, const char*, const OSModuleInfo*); +void MapFile_Unregist(MapFileHandle); +void MapFile_UnregistAll(); +bool MapFile_QuerySymbol(u32 address, u8 *strBuf, u32 strBufSize); + +} // namespace db +} // namespace nw4r + +#endif diff --git a/include/rvl/OS/OSLink.h b/include/rvl/OS/OSLink.h index 8f6df8b0..0bc13dc3 100644 --- a/include/rvl/OS/OSLink.h +++ b/include/rvl/OS/OSLink.h @@ -105,6 +105,7 @@ BOOL OSLinkFixed(OSModuleInfo* newModule, void* bss); BOOL OSUnlink(OSModuleInfo* module); void OSSetStringTable(void* string_table); void __OSModuleInit(void); +OSModuleInfo* OSSearchModule(void* ptr, u32* section, u32* offset); #ifdef __cplusplus }; diff --git a/src/DynamicLink.cpp b/src/DynamicLink.cpp index 2c7947c0..ec9fd045 100644 --- a/src/DynamicLink.cpp +++ b/src/DynamicLink.cpp @@ -320,35 +320,25 @@ const char *DynamicModuleControl::getModuleTypeString() const { } DbMapFile::~DbMapFile() { - if (unk_0) { + if (mMapFileHandle != nullptr) { Unregister(); } } -namespace nw4r { -namespace db { -// TODO -typedef struct MapFile { -} MapFile; -extern MapFile *MapFile_RegistOnDvd(void *arg, const char *buf, const OSModuleInfo *info); -extern void *MapFile_Unregist(MapFile *); -} // namespace db -} // namespace nw4r - void DbMapFile::RegisterOnDvd(const char *path, const OSModuleInfo *info) { if (mDvd::IsExistPath(path)) { - unk_0 = (UNKWORD)nw4r::db::MapFile_RegistOnDvd(((int *)this) + 1, path, info); + mMapFileHandle = nw4r::db::MapFile_RegistOnDvd(&mMapFile, path, info); } else { - unk_0 = 0xffffffff; + mMapFileHandle = (nw4r::db::MapFileHandle)0xffffffff; } } void DbMapFile::Unregister() { - if (unk_0 != 0) { - if (unk_0 != 0xffffffff) { - nw4r::db::MapFile_Unregist((nw4r::db::MapFile *)unk_0); + if (mMapFileHandle != nullptr) { + if ((u32)mMapFileHandle != 0xffffffff) { + nw4r::db::MapFile_Unregist(mMapFileHandle); } - unk_0 = 0; + mMapFileHandle = nullptr; } } diff --git a/src/egg/prim/eggAssert.cpp b/src/egg/prim/eggAssert.cpp index dc9e44a3..bde46ca9 100644 --- a/src/egg/prim/eggAssert.cpp +++ b/src/egg/prim/eggAssert.cpp @@ -3,18 +3,11 @@ #include #include #include +#include #include #include #include - -namespace nw4r { -namespace db { -// TODO -extern s32 MapFile_QuerySymbol(void *arg, char *buf, u32 buf_size); -} // namespace db -} // namespace nw4r - namespace EGG { namespace Assert { @@ -62,7 +55,7 @@ bool sAssertOccurred; /* 80674c60 */ char buf[260]; /* 8049c100 */ const char *getMapSymbol(void *arg) { - u32 success = nw4r::db::MapFile_QuerySymbol(arg, buf, sizeof(buf)); + bool success = nw4r::db::MapFile_QuerySymbol((u32)arg, (u8*)buf, sizeof(buf)); return success ? buf : nullptr; } diff --git a/src/nw4r/db/db_mapFile.cpp b/src/nw4r/db/db_mapFile.cpp new file mode 100644 index 00000000..d8e0e24b --- /dev/null +++ b/src/nw4r/db/db_mapFile.cpp @@ -0,0 +1,343 @@ +#include +#include +#include +#include + +namespace nw4r { +namespace db { + +static u32 sFileLength; +static MapFile *sMapFileList = nullptr; +static u8 (*GetCharPtr_)(const u8 *) = nullptr; + +static u8 dvdReadBuf[512] ALIGN(32); +static DVDFileInfo sFileInfo; + +s32 unk_80574e10 = 0x200; +u8 *dvdReadPtr = dvdReadBuf; +s32 unk_80574e18 = -1; + +static void MapFile_Append(MapFile *file) { + if (sMapFileList == nullptr) { + sMapFileList = file; + return; + } + + if (file->moduleInfo != nullptr) { + file->next = sMapFileList->next; + sMapFileList->next = file; + } else { + file->next = sMapFileList; + sMapFileList = file; + } +} + +/** 80436a50 */ +MapFileHandle MapFile_RegistOnDvd(void *buf, const char *path, const OSModuleInfo *info) { + MapFile *file = (MapFile *)buf; + file->mapBuf = nullptr; + file->moduleInfo = info; + file->fileEntry = DVDConvertPathToEntrynum(path); + file->next = nullptr; + + MapFile_Append(file); + return file; +} + +/** 80436ae0 */ +void MapFile_Unregist(MapFileHandle file) { + if (file == sMapFileList) { + sMapFileList = sMapFileList->next; + return; + } + + MapFile *cursor = sMapFileList; + for (; cursor != nullptr; cursor = cursor->next) { + if (cursor->next == file) { + cursor->next = file->next; + return; + } + } +} + +/** 80436b30 */ +void MapFile_UnregistAll() { + sMapFileList = nullptr; +} + +/** 80436b40 */ +static u8 GetCharOnMem_(const u8 *arg) { + return *arg; +} + +/** 80436b50 */ +static u8 GetCharOnDvd_(const u8 *arg) { + s32 cleared = (s32)arg & 0x7fffffff; + s32 unoffset = cleared - unk_80574e18; + if (cleared >= sFileLength) { + return 0; + } + + if (unk_80574e18 < 0 || unoffset < 0 || unoffset >= unk_80574e10) { + unk_80574e18 = ROUND_DOWN(cleared, 32); + unoffset = cleared - unk_80574e18; + cleared = unk_80574e10; + if (unk_80574e18 + unk_80574e10 >= sFileLength) { + cleared = ROUND_UP(sFileLength - unk_80574e18, 32); + } + BOOL interrupts = OSEnableInterrupts(); + BOOL read = DVDReadAsyncPrio(&sFileInfo, dvdReadPtr, cleared, unk_80574e18, nullptr, 2); + while (DVDGetCommandBlockStatus(&sFileInfo.block)) {} + + OSRestoreInterrupts(interrupts); + if (read <= 0) { + return 0; + } + } + return *(dvdReadPtr + unoffset); +} + +static u8 *SearchNextLine_(u8 *buf, s32 lines) { + u8 c; + + if (buf == nullptr) { + return nullptr; + } + + while ((c = (GetCharPtr_)(buf)) != '\0') { + if (c == '\n') { + if (--lines <= 0) { + return buf + 1; + } + } + buf++; + } + + return nullptr; +} + +static u8 *SearchNextSection_(u8 *buf) { + do { + buf = SearchNextLine_(buf, 1); + if (buf == nullptr) { + return nullptr; + } + } while ((GetCharPtr_)(buf) != '.'); + return buf; +} + +static u8 *SearchParam_(u8 *lineTop, u32 argNum, u8 splitter) { + bool inArg = false; + u8 *buf = lineTop; + + if (buf == nullptr) { + return nullptr; + } + while (true) { + u8 c = (GetCharPtr_)(buf); + if (c == '\0' || c == '\n') { + return 0; + } + if (inArg) { + if (c == splitter) { + inArg = false; + } + } else if (c != splitter) { + if (argNum-- == 0) { + return buf; + } + inArg = true; + } + buf += 1; + } +} + +static u32 XStrToU32_(const u8 *str) { + u32 val = 0; + + while (true) { + u32 num; + u8 c = (GetCharPtr_)(str); + if ('0' <= c && c <= '9') { + num = c - '0'; + } else if ('a' <= c && c <= 'z') { + num = c - 'a' + 10; + } else if ('A' <= c && c <= 'Z') { + num = c - 'A' + 10; + } else { + return val; + } + + if (val >= 0x10000000) { + return 0; + } + val = num + val * 16; + str++; + } +} + +static u32 CopySymbol_(const u8 *buf, u8 *str, u32 strLenMax, u8 splitter) { + u32 cnt = 0; + + while (true) { + u8 c = (GetCharPtr_)(buf++); + if (c == splitter || c == '\0' || c == '\n') { + *str = '\0'; + return cnt; + } + *str++ = c; + if (++cnt >= strLenMax - 1) { + *str = '\0'; + return cnt; + } + } +} + +bool QuerySymbolToMapFile_(u8 *buf, const OSModuleInfo *moduleInfo, u32 address, u8 *strBuf, u32 strBufSize) { + OSSectionInfo *sectionInfo = nullptr; + u32 sectionCnt; + + if (moduleInfo != nullptr) { + sectionInfo = OSGetSectionInfo(moduleInfo); + sectionCnt = moduleInfo->numSections; + } + + while (true) { + u32 offset = 0; + buf = SearchNextSection_(buf); + buf = SearchNextLine_(buf, 3); + if (sectionInfo != nullptr) { + offset = ROUND_DOWN(sectionInfo->offset, 2); + if (address < offset || address >= offset + sectionInfo->size) { + goto next; + } + } + + while (true) { + u8 *param; + u32 startAddr; + u32 size; + buf = SearchNextLine_(buf, 1); + if (buf == nullptr) { + return false; + } + param = SearchParam_(buf, 1, ' '); + if (param == nullptr) { + goto next; + } + size = XStrToU32_(param); + param = SearchParam_(buf, 2, ' '); + if (param == nullptr) { + goto next; + } + startAddr = XStrToU32_(param); + if (startAddr == 0) { + continue; + } + startAddr += offset; + if (address < startAddr || startAddr + size <= address) { + continue; + } + + param = SearchParam_(buf, 5, ' '); + if (param == nullptr) { + strBuf[0] = '\0'; + return true; + } + if ((GetCharPtr_)(param) == '.') { + continue; + } + + CopySymbol_(param, strBuf, strBufSize, '\t'); + return true; + } + next: + if (sectionInfo != nullptr) { + if (--sectionCnt == 0) { + return 0; + } + sectionInfo++; + } + } +} + +// No idea, doesn't appear in the DWARF +/** 804370d0 */ +bool UnkFunction_(const OSModuleInfo *moduleInfo, u32 address, u8 *strBuf, u32 strBufSize) { + if (moduleInfo == nullptr) { + if (address < (u32)_stack_end) { + snprintf((char *)strBuf, strBufSize, "[%p]", address); + return true; + } else { + return false; + } + } else { + u32 sectionIdx = 0; + OSSectionInfo *sectionInfo = OSGetSectionInfo(moduleInfo); + for (u32 sectionCnt = 0; sectionCnt < moduleInfo->numSections; sectionCnt++) { + u32 offset = ROUND_DOWN(sectionInfo->offset, 2); + if (offset <= address && address < offset + sectionInfo->size) { + snprintf((char *)strBuf, strBufSize, "[%d:%d:%06x]", moduleInfo->id, sectionIdx, address - offset); + return true; + } + sectionInfo++; + sectionIdx++; + } + return false; + } +} + +bool QuerySymbolToSingleMapFile_(MapFileHandle pMapFile, u32 address, u8 *strBuf, u32 strBufSize) { + if (pMapFile->mapBuf != nullptr) { + GetCharPtr_ = GetCharOnMem_; + return QuerySymbolToMapFile_(pMapFile->mapBuf, pMapFile->moduleInfo, address, strBuf, strBufSize); + } else if (pMapFile->fileEntry >= 0) { + u8 *buf = (u8 *)0x80000000; + bool ret; + if (!DVDFastOpen(pMapFile->fileEntry, &sFileInfo)) { + goto err; + } + unk_80574e18 = -1; + sFileLength = sFileInfo.size; + GetCharPtr_ = GetCharOnDvd_; + ret = QuerySymbolToMapFile_(buf, pMapFile->moduleInfo, address, strBuf, strBufSize); + DVDClose(&sFileInfo); + return ret; + } else { + return UnkFunction_(pMapFile->moduleInfo, address, strBuf, strBufSize); + } + +err: + strBuf[0] = '\0'; + return false; +} + +bool MapFile_QuerySymbol(u32 address, u8 *strBuf, u32 strBufSize) { + MapFile *pMap = sMapFileList; + if (sMapFileList == nullptr) { + if (address < (u32)_stack_end) { + snprintf((char *)strBuf, strBufSize, "[%p]", address); + return true; + } else { + u32 offset; + u32 section; + OSModuleInfo *info = OSSearchModule((void *)address, §ion, &offset); + if (info) { + snprintf((char *)strBuf, strBufSize, "[%d:%d:%06x]", info->id, section, offset); + return true; + } + return false; + } + } else { + for (; pMap != nullptr; pMap = pMap->next) { + if (QuerySymbolToSingleMapFile_(pMap, address, strBuf, strBufSize)) { + return true; + } + } + + return false; + } +} + +} // namespace db +} // namespace nw4r