summaryrefslogtreecommitdiff
path: root/src/nw4r/db/db_mapFile.cpp
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2024-05-24 16:41:33 +0200
committerrobojumper <robojumper@gmail.com>2024-05-24 16:41:33 +0200
commitb2d728089e500e463d7596867ba11e34cf6586f0 (patch)
tree918261d4590eed4b09ee63258dc59abeef8a82ed /src/nw4r/db/db_mapFile.cpp
parentd711118601dad11244eb8a2de79727ae9756cf9f (diff)
db_mapFile
Diffstat (limited to 'src/nw4r/db/db_mapFile.cpp')
-rw-r--r--src/nw4r/db/db_mapFile.cpp343
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, &section, &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