diff options
| author | robojumper <robojumper@gmail.com> | 2024-05-24 16:41:33 +0200 |
|---|---|---|
| committer | robojumper <robojumper@gmail.com> | 2024-05-24 16:41:33 +0200 |
| commit | b2d728089e500e463d7596867ba11e34cf6586f0 (patch) | |
| tree | 918261d4590eed4b09ee63258dc59abeef8a82ed /src/nw4r/db/db_mapFile.cpp | |
| parent | d711118601dad11244eb8a2de79727ae9756cf9f (diff) | |
db_mapFile
Diffstat (limited to 'src/nw4r/db/db_mapFile.cpp')
| -rw-r--r-- | src/nw4r/db/db_mapFile.cpp | 343 |
1 files changed, 343 insertions, 0 deletions
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 <MSL_C/string.h> +#include <nw4r/db/db_mapFile.h> +#include <rvl/DVD.h> +#include <rvl/OS.h> + +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 |
