mirror of
https://github.com/zeldaret/ss
synced 2026-06-02 02:00:06 -04:00
344 lines
8.9 KiB
C++
344 lines
8.9 KiB
C++
#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
|