diff --git a/include/variables.h b/include/variables.h index 36293eeff94..5010961585c 100644 --- a/include/variables.h +++ b/include/variables.h @@ -6,7 +6,6 @@ extern u8 i_item_lst[24]; extern u8 lbl_80430188[16]; extern u8 lbl_80379235[16]; extern char lbl_80379234[0x64]; -extern char lbl_803739A0[0x310]; extern u32 _sRumbleSupported; extern u8 lbl_803A2EF4; extern char lbl_803A2EE0[20]; @@ -14,23 +13,16 @@ extern u8 lbl_80450B19; // extern u8 lbl_80450588; // extern u8 lbl_804511B8; extern u8 lbl_80450B20; -extern u8 lbl_80451A00; extern u8 lbl_80450B1C; extern u8 lbl_80450B28; -extern u8 lbl_80451A04; extern u8 lbl_80450B24; extern u8 lbl_80450B28; extern u8 lbl_80450B30; -extern u8 lbl_80451A08; extern u8 lbl_80450B2C; extern u8 lbl_80450B30; -extern u8 lbl_80451A08; extern u8 lbl_80450B2C; extern u8 lbl_80450B2C; -extern u8 lbl_80451A0C; -extern u8 lbl_80451A10; extern u8 lbl_80450B2C; -extern u8 lbl_80451A18; extern u8 lbl_80450B2C; extern u8 lbl_80450B1C; extern u8 lbl_80450B1C; @@ -101,9 +93,6 @@ extern u32 lbl_80000028; #define OS_GLOBAL(T, ADDR) *((T*)((void*)ADDR)) #define OS_GLOBAL_ADDR(T, ADDR) ((T*)((void*)ADDR)) -// func_802CEB40 -extern char lbl_8039CAD8[12]; // "JKRHeap.cpp" - // func_802D147C extern void* lbl_803CC0F0; // JKRDisposer::__vt @@ -192,10 +181,6 @@ extern void* lbl_804513C4; // JKRThreadSwitch::mUserPostCallback extern char lbl_8039CFA8[1]; // 8039cfdc-0x34 "JKRThreadSwitch: currentHeap destroyed.\n" -extern float lbl_80455FC0; // JKernel::@934 = 100.0 -extern float lbl_80455FC4; // JKernel::@935 = 1000.0 -extern double lbl_80455FC8; // JKernel::@937 = 4.503599627370496E15 - class JKRDvdFile; extern JSUList sDvdList__10JKRDvdFile; // JKRDvdFile::sDvdList extern u8 lbl_803CC438; // JKRDvdFile::__vt @@ -307,7 +292,6 @@ extern u8 lbl_80434318; // JKernel::@492 (global destructor chain) class JKRAramStream; extern JKRAramStream* sAramStreamObject__13JKRAramStream; // JKRAramStream::sAramStreamObject extern u8 transHeap__13JKRAramStream; // JKRAramStream::transHeap -extern char lbl_8039D120[16]; // "JKRAramStream.cpp" extern u8 transBuffer__13JKRAramStream; // JKRAramStream::transBuffer extern u8 transSize__13JKRAramStream; // JKRAramStream::transSize extern u8 lbl_803CC1B8; // JKRAramStream::__vt @@ -343,7 +327,6 @@ extern u8 lbl_803CC518; // JSUFileInputStream::__vt class JKRAram; extern u8 lbl_803CC158; // JKRAram::__vt -extern char lbl_8039D078[16]; // "JKRAram.cpp" extern JKRAram* sAramObject__7JKRAram; // JKRAram::sAramObject extern OSMessageQueue sMessageQueue__7JKRAram; // JKRAram::sMessageQueue extern bool lbl_804513FC; // DAT_804513fc (init global mutex) diff --git a/ldscript.lcf b/ldscript.lcf index ba50f6f137d..c4d4eee46f7 100644 --- a/ldscript.lcf +++ b/ldscript.lcf @@ -757,6 +757,7 @@ SECTIONS { "__dt__7JKRFileFv" = 0x802D7B90; "lbl_8039CE50" = 0x8039CE50; +"lbl_803739A0" = 0x803739A0; } FORCEACTIVE { getParentPane__7J2DPaneFv diff --git a/libs/JSystem/JKernel/JKRAram.cpp b/libs/JSystem/JKernel/JKRAram.cpp index ad2a8858fdc..1a4843275d2 100644 --- a/libs/JSystem/JKernel/JKRAram.cpp +++ b/libs/JSystem/JKernel/JKRAram.cpp @@ -107,17 +107,11 @@ asm void* JKRAram::run(void) { void JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4) { if (!IS_ALIGNED((u32)addr, 0x20) && !IS_ALIGNED(size, 0x20)) { - const char* file = lbl_8039D078; - const char* format = lbl_8039D078 + 0xc; - const char* arg1 = lbl_8039D078 + 0xc + 0x3; - JUTException_NS_panic_f(file, 0xdb, format, arg1); + JUTException_NS_panic_f("JKRAram.cpp", 0xdb, "%s", ":::address not 32Byte aligned."); } if (block && !IS_ALIGNED((u32)block->getAddress() + param_4, 0x20)) { - const char* file = lbl_8039D078; - const char* format = lbl_8039D078 + 0xc; - const char* arg1 = lbl_8039D078 + 0xc + 0x3; - JUTException_NS_panic_f(file, 0xe3, format, arg1); + JUTException_NS_panic_f("JKRAram.cpp", 0xe3, "%s", ":::address not 32Byte aligned."); } } @@ -290,3 +284,6 @@ asm JSUList<12JKRAMCommand>::~JSUList<12JKRAMCommand>(void) { #include "JSystem/JKernel/JKRAram/asm/func_802D2DF0.s" } #endif + +const char* lbl_8039D0A6 = "bad aramSync\n"; +const char* lbl_8039D0B4 = "\x00\x00\x00"; /* padding */ diff --git a/libs/JSystem/JKernel/JKRAramPiece.cpp b/libs/JSystem/JKernel/JKRAramPiece.cpp index ad2b83d1701..f04b2f1de86 100644 --- a/libs/JSystem/JKernel/JKRAramPiece.cpp +++ b/libs/JSystem/JKernel/JKRAramPiece.cpp @@ -24,15 +24,11 @@ JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destinatio JKRAramBlock* block, JKRAMCommand::AsyncCallback callback) { lock(); if (((source & 0x1f) != 0) || ((destination & 0x1f) != 0)) { - OSReport(lbl_8039D0B8, direction); // "direction = %x\n" - OSReport(lbl_8039D0B8 + 0x10, source); // "source = %x\n" - OSReport(lbl_8039D0B8 + 0x1D, destination); // "destination = %x\n" - OSReport(lbl_8039D0B8 + 0x2F, length); // "length = %x\n" - - const char* filename = lbl_8039D0B8 + 0x3C; // "JKRAramPiece.cpp"ยง - const char* format = lbl_8039D0B8 + 0x3C + 0x11; // "%s" - const char* arg1 = lbl_8039D0B8 + 0x3C + 0x14; // "illegal address. abort." - JUTException_NS_panic_f(filename, 0x6c, format, arg1); + OSReport("direction = %x\n", direction); + OSReport("source = %x\n", source); + OSReport("destination = %x\n", destination); + OSReport("length = %x\n", length); + JUTException_NS_panic_f("JKRAramPiece.cpp", 0x6c, "%s", "illegal address. abort."); } Message* message = new (JKRHeap::getSystemHeap(), -4) Message(); diff --git a/libs/JSystem/JKernel/JKRAramStream.cpp b/libs/JSystem/JKernel/JKRAramStream.cpp index 353bfbe2854..97a85bdb793 100644 --- a/libs/JSystem/JKernel/JKRAramStream.cpp +++ b/libs/JSystem/JKernel/JKRAramStream.cpp @@ -2,6 +2,8 @@ #include "JSystem/JKernel/JKRAramPiece/JKRAramPiece.h" #include "global.h" +extern char lbl_8039D120[32]; + JKRAramStream* JKRAramStream::create(long priority) { if (!sAramStreamObject) { sAramStreamObject = new (JKRGetSystemHeap(), 0) JKRAramStream(priority); @@ -86,10 +88,7 @@ s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) { heap->dump(); } - const char* file = lbl_8039D120; // "JKRAramStream.cpp"; - const char* format = lbl_8039D120 + 0x12; // "%s"; - const char* arg1 = lbl_8039D120 + 0x15; // ":::Cannot alloc memory\n"; - JUTException_NS_panic_f(file, 0xac, format, arg1); + JUTException_NS_panic_f("JKRAramStream.cpp", 0xac, "%s", ":::Cannot alloc memory\n"); } if (buffer) { @@ -208,3 +207,4 @@ JKRAramStreamCommand::JKRAramStreamCommand() { s32 JSURandomInputStream::getAvailable() const { return getLength() - getPosition(); } + diff --git a/libs/JSystem/JKernel/JKRHeap.cpp b/libs/JSystem/JKernel/JKRHeap.cpp index bf3ee748983..96d49dbb941 100644 --- a/libs/JSystem/JKernel/JKRHeap.cpp +++ b/libs/JSystem/JKernel/JKRHeap.cpp @@ -336,10 +336,7 @@ void JKRHeap::copyMemory(void* dst, void* src, u32 size) { } void JKRHeap::JKRDefaultMemoryErrorRoutine(JKRHeap* heap, u32 size, int alignment) { - const char* filename = lbl_8039CAD8; // "JKRHeap.cpp" - const char* format = lbl_8039CAD8 + 12; // "%s" - const char* arg1 = lbl_8039CAD8 + 15; // "abort\n" - JUTException_NS_panic_f(filename, 0x33f, format, arg1); + JUTException_NS_panic_f("JKRHeap.cpp", 0x33f, "%s", "abort\n"); } bool JKRHeap::setErrorFlag(bool errorFlag) { @@ -437,3 +434,5 @@ u8 JKRHeap::do_changeGroupID(u8 newGroupID) { u8 JKRHeap::do_getCurrentGroupId() const { return 0; } + +const char* lbl_8039CAEE = "\x00"; /* padding */ diff --git a/libs/JSystem/JKernel/JKRSolidHeap.cpp b/libs/JSystem/JKernel/JKRSolidHeap.cpp index 5bbbd40a3da..ddbe0b75f90 100644 --- a/libs/JSystem/JKernel/JKRSolidHeap.cpp +++ b/libs/JSystem/JKernel/JKRSolidHeap.cpp @@ -282,3 +282,5 @@ void* JKRSolidHeap::do_getMaxFreeBlock(void) const { s32 JKRSolidHeap::do_getTotalFreeSize(void) const { return getFreeSize(); } + +const char* lbl_8039CFA7 = ""; /* padding */ diff --git a/libs/JSystem/JKernel/JKRThread.cpp b/libs/JSystem/JKernel/JKRThread.cpp index b37c996d3d6..e2da7735f95 100644 --- a/libs/JSystem/JKernel/JKRThread.cpp +++ b/libs/JSystem/JKernel/JKRThread.cpp @@ -2,6 +2,13 @@ #include "JSystem/JKernel/JKRHeap/JKRHeap.h" #include "global.h" +// lbl_80455FC0 JKRThread.o @934 +static const u8 lbl_80455FC0[4] = {0x42, 0xc8, 0x0, 0x0}; +// lbl_80455FC4 JKRThread.o @935 +static const u8 lbl_80455FC4[4] = {0x44, 0x7a, 0x0, 0x0}; +// lbl_80455FC8 JKRThread.o @937 +static const u8 lbl_80455FC8[8] = {0x43, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this) { mSwitchCount = 0; mCost = 0; diff --git a/obj_files.mk b/obj_files.mk index 5ba663bc6d4..1a599c6b27e 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -10,10 +10,10 @@ EXTABINDEX_O_FILES := \ $(BUILD_DIR)/asm/extabindex.o TEXT_O_FILES := \ - $(BUILD_DIR)/asm/rodata/rodata_m_Do_main.o \ $(BUILD_DIR)/asm/sdata2/m_Do_main.o \ $(BUILD_DIR)/src/m_Do/m_Do_main.o \ $(BUILD_DIR)/asm/rodata/rodata_m_Do_printf.o \ + $(BUILD_DIR)/src/m_Do/m_Do_printf.o \ $(BUILD_DIR)/asm/m/Do/m_Do_printf.o \ $(BUILD_DIR)/asm/rodata/rodata_m_Do_audio.o \ $(BUILD_DIR)/src/m_Do/m_Do_audio.o \ @@ -804,26 +804,21 @@ TEXT_O_FILES := \ $(BUILD_DIR)/asm/sdata2/GFPixel.o \ $(BUILD_DIR)/asm/gf/GFPixel.o \ $(BUILD_DIR)/asm/gf/GFTev.o \ - $(BUILD_DIR)/asm/rodata/rodata_JKRHeap.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRHeap.o \ $(BUILD_DIR)/asm/rodata/rodata_JKRExpHeap.o \ $(BUILD_DIR)/asm/sdata2/JKRExpHeap.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRExpHeap.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRSolidHeap.o \ - $(BUILD_DIR)/asm/rodata/rodata_JKRSolidHeap_padding.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRAssertHeap.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRDisposer.o \ $(BUILD_DIR)/asm/rodata/rodata_JKRThread.o \ - $(BUILD_DIR)/asm/sdata2/JKRThread.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRThread.o \ $(BUILD_DIR)/asm/JKernel/JKRThread.o \ - $(BUILD_DIR)/asm/rodata/rodata_JKRAram.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRAram.o \ $(BUILD_DIR)/asm/JKernel/JKRAram.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRAramHeap.o \ $(BUILD_DIR)/asm/JKernel/JKRAramHeap.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRAramBlock.o \ - $(BUILD_DIR)/asm/rodata/rodata_JKRAramPiece.o \ $(BUILD_DIR)/libs/JSystem/JKernel/JKRAramPiece.o \ $(BUILD_DIR)/asm/JKernel/JKRAramPiece.o \ $(BUILD_DIR)/asm/rodata/rodata_JKRAramStream.o \ diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index 7001ca9f9a3..46b179a89f4 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -11,13 +11,23 @@ #include "m_Do/m_Do_machine/m_Do_machine.h" #include "m_Do/m_Do_reset/m_Do_reset.h" +extern u8 lbl_80451A00; +extern u8 lbl_80451A04; +extern u8 lbl_80451A08; +extern u8 lbl_80451A0C; +extern u8 lbl_80451A10; +extern u8 lbl_80451A18; +// extern char lbl_803739A0[0x310]; + +extern char lbl_803739A0; + void version_check(void) { - if ((!strcmp((char*)lbl_803739A0, (char*)lbl_803739A0)) && - (!strcmp(((char*)lbl_803739A0 + 0xA), ((char*)lbl_803739A0 + 0xA)))) { + if ((!strcmp("20Apr2004", "20Apr2004")) && + (!strcmp("Patch2", "Patch2"))) { return; } - OSReport_Error((char*)lbl_803739A0 + 0x11); + OSReport_Error((char*)"\x53\x44\x4B\x82\xCC\x83\x6F\x81\x5B\x83\x57\x83\x87\x83\x93\x82\xAA\x88\xEA\x92\x76\x82\xB5\x82\xDC\x82\xB9\x82\xF1\x81\x42\x92\xE2\x8E\x7E\x82\xB5\x82\xDC\x82\xB7\x0A"); do { } while (true); } @@ -93,24 +103,44 @@ void HeapCheck::heapDisplay(void) const { s32 heap_total_free_size = heap->getTotalFreeSize(); s32 heap_free_size = heap->getFreeSize(); - JUTReport__FiiPCce(0x64, 0xd4, lbl_803739A0 + 0x3C, names[0]); - JUTReport__FiiPCce(0x64, 0xe3, lbl_803739A0 + 0x45, heap_size1); - JUTReport__FiiPCce(0x64, 0xf0, lbl_803739A0 + 0x5B, heap_size); - JUTReport__FiiPCce(0x64, 0xfd, lbl_803739A0 + 0x71, heap_total_free_size - heap_size2); - JUTReport__FiiPCce(0x64, 0x10a, lbl_803739A0 + 0x87, heap_free_size - heap_size2); - JUTReport__FiiPCce(0x64, 0x117, lbl_803739A0 + 0x9D, heap_total_used_size); - JUTReport__FiiPCce(0x64, 0x124, lbl_803739A0 + 0xB3, + JUTReport__FiiPCce(0x64, 0xd4,"[%sName]", names[0]); + JUTReport__FiiPCce(0x64, 0xe3, "HeapSize %8ld", heap_size1); + JUTReport__FiiPCce(0x64, 0xf0, "TargetHeapSize %8ld", heap_size); + JUTReport__FiiPCce(0x64, 0xfd, "TotalFree %8ld", heap_total_free_size - heap_size2); + JUTReport__FiiPCce(0x64, 0x10a, "FreeSize %8ld", heap_free_size - heap_size2); + JUTReport__FiiPCce(0x64, 0x117, "TotalUsedSize %8ld", heap_total_used_size); + JUTReport__FiiPCce(0x64, 0x124, "TotalUsedRate %3ld%%", (int)(heap_total_used_size * 0x64) / (int)heap_size); - JUTReport__FiiPCce(0x64, 0x131, lbl_803739A0 + 0xCF, max_total_used_size); - JUTReport__FiiPCce(0x64, 0x13e, lbl_803739A0 + 0xE5, + JUTReport__FiiPCce(0x64, 0x131, "MaxTotalUsedSize %8ld", max_total_used_size); + JUTReport__FiiPCce(0x64, 0x13e, "MaxTotalUsedRate %3ld%%", (max_total_used_size * 0x64) / (int)heap_size); - JUTReport__FiiPCce(0x64, 0x14b, lbl_803739A0 + 0x101, max_total_free_size - heap_size2); - JUTReport__FiiPCce(0x64, 0x158, lbl_803739A0 + 0x117, + JUTReport__FiiPCce(0x64, 0x14b, "MinFreeSize %8ld", max_total_free_size - heap_size2); + JUTReport__FiiPCce(0x64, 0x158, "MinFreeRate %3ld%%", ((max_total_free_size - heap_size2) * 0x64) / (int)heap_size); heap_size2 = countUsed(heap); - JUTReport__FiiPCce(0x64, 0x165, lbl_803739A0 + 0x133, heap_size2); + JUTReport__FiiPCce(0x64, 0x165, "UsedCount %3ld%", heap_size2); } +const char* lbl_80373AEF = ""; +const char* lbl_80373AF0 = "TotalFree"; +const char* lbl_80373AFA = "MaxUsed "; +const char* lbl_80373B04 = "Used "; +const char* lbl_80373B0E = "RelUsed "; +const char* lbl_80373B18 = "/ MaxFree"; +const char* lbl_80373B22 = "/HeapSize"; +const char* lbl_80373B2C = "Blk/Bytes"; +const char* lbl_80373B36 = "ARAM Free"; +const char* lbl_80373B40 = "%d"; +const char* lbl_80373B43 = "%s"; +const char* lbl_80373B46 = " [%s]"; +const char* lbl_80373B4C = "%10d"; +const char* lbl_80373B51 = "Press X+Y+START to CLEAR console."; +const char* lbl_80373B73 = "3DStick UP/Down to scroll"; +const char* lbl_80373B8D = "Press A to output terminal from console."; +const char* lbl_80373BB6 = "\x53\x43\x52\x4F\x4C\x4C\x81\x46\x25\x33\x64\x20\x25\x33\x64\x20\x25\x33\x64\x20\x4F\x75\x74\x70\x75\x74\x3D\x25\x31\x78"; /* undecodable string */ +const char* lbl_80373BD5 = "Press L+R trigger to control console."; +const char* lbl_80373BFB = "Press [Z] trigger to close this window."; + asm void debugDisplay(void) { nofralloc #include "m_Do\m_Do_main\asm\func_80005AD8.s" @@ -122,30 +152,43 @@ asm void Debug_console(u32) { } #ifdef NONMATCHING - -extern void memcpy(void*, void*, int); - void LOAD_COPYDATE(void*) { - s32 dvd_status; - char buffer[32]; DVDFileInfo file_info; - dvd_status = DVDOpen((const char*)lbl_803739A0[0x283], &file_info); - + s32 dvd_status = DVDOpen("/str/Final/Release/COPYDATE", &file_info); if (dvd_status) { + char buffer[32]; DVDReadPrio(&file_info, buffer, 32, 0, 2); memcpy(lbl_803A2EE0, buffer, 17); DVDClose(&file_info); } - return; } #else +const char* lbl_80373C23 = "/str/Final/Release/COPYDATE"; asm void LOAD_COPYDATE(void*) { nofralloc #include "m_Do\m_Do_main\asm\func_8000614C.s" } #endif +const char* lbl_80373C3F = "Root"; +const char* lbl_80373C44 = "\x83\x8B\x81\x5B\x83\x67"; /* undecodable string */ +const char* lbl_80373C4B = "System"; +const char* lbl_80373C52 = "\x83\x56\x83\x58\x83\x65\x83\x80"; /* undecodable string */ +const char* lbl_80373C5B = "Zelda"; +const char* lbl_80373C61 = "\x83\x5B\x83\x8B\x83\x5F"; /* undecodable string */ +const char* lbl_80373C68 = "Game"; +const char* lbl_80373C6D = "\x83\x51\x81\x5B\x83\x80"; /* undecodable string */ +const char* lbl_80373C74 = "Archive"; +const char* lbl_80373C7C = "\x83\x41\x81\x5B\x83\x4A\x83\x43\x83\x75"; /* undecodable string */ +const char* lbl_80373C87 = "J2d"; +const char* lbl_80373C8B = "J2D"; +const char* lbl_80373C8F = "Hostio"; +const char* lbl_80373C96 = "\x83\x7A\x83\x58\x83\x67\x49\x4F"; /* undecodable string */ +const char* lbl_80373C9F = "Command"; +const char* lbl_80373CA7 = "\x83\x52\x83\x7D\x83\x93\x83\x68"; /* undecodable string */ + + void debug(void) { if (lbl_80450580[0]) { if (lbl_80450B1A[0]) { diff --git a/src/m_Do/m_Do_printf.cpp b/src/m_Do/m_Do_printf.cpp index 4bf93c8658d..9c427327383 100644 --- a/src/m_Do/m_Do_printf.cpp +++ b/src/m_Do/m_Do_printf.cpp @@ -1 +1,13 @@ // ok + +#if 0 +// lbl_80373CB0 m_Do_printf.o @stringBase0 = ??? +static const char* lbl_80373CB0 = "\x1b[41;37m***** FATAL ERROR *****\n"; +static const char* lbl_80373CD1 = "***** FATAL ERROR *****\n\x1b[m"; +static const char* lbl_80373CED = "\x1b[41;37m[ERROR]"; +static const char* lbl_80373CFD = "\x1b[m"; +static const char* lbl_80373D01 = "\x1b[43;30m[WARN]"; +static const char* lbl_80373D10 = " in \"%s\" on line %d.\n"; +static const char* lbl_80373D26 = "\nAddress: Back Chain LR Save\n"; +static const char* lbl_80373D4C = "0x%08x: 0x%08x 0x%08x\n"; +#endif diff --git a/tools/section2cpp.py b/tools/section2cpp.py new file mode 100644 index 00000000000..9276058f94e --- /dev/null +++ b/tools/section2cpp.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python3 +# PYTHON_ARGCOMPLETE_OK +import argparse +import sys +import os +import struct +import shlex +from pathlib import Path, PurePath, PureWindowsPath +from typing import ( + Any, + Dict, + List, + Match, + NamedTuple, + NoReturn, + Optional, + Set, + Tuple, + Union, + Callable, + Pattern, +) + + +try: + import argcomplete # type: ignore +except ModuleNotFoundError: + argcomplete = None + +parser = argparse.ArgumentParser(description="Extract section data and generate C++ code (arrays).") + +parser.add_argument( + "--section", + dest="section", + type=str, + metavar="SECTION", + help="SECTION to extract data from.", + required=True +) + +parser.add_argument( + "--file-offset", + dest="file_offset", + type=lambda x: int(x,0), + metavar="OFFSET", + help="OFFSET in the baserom for the SECTION." +) + +parser.add_argument( + "--object", + dest="object_name", + type=str, + metavar="OBJECT", + help="OBJECT filename to extract data from. (e.g. JKRSolidHeap.o)", + required=True +) + +parser.add_argument( + "--baserom", + dest="baserom", + type=str, + metavar="DOL", + help="baserom.dol path", + default="baserom.dol" +) + +parser.add_argument( + "--string", + dest="as_string", + action="store_true", + help="Print arrays as strings" +) + + +# +# +# + +def _itersplit(l, splitters): + current = [] + for item in l: + if item in splitters: + yield current + current = [] + else: + current.append(item) + yield current + +def magicsplit(l, *splitters): + return [subl for subl in _itersplit(l, splitters) ] + +def str_encoding(data): + try: + data.decode("utf-8") + return "utf-8" + except: + pass + + try: + data.decode("shift_jisx0213") + return "shift-jis" + except: + pass + + return None, None + +def raw_string(data): + assert data[-1] == 0 + return str(data[:-1])[2:-1].replace("\"", "\\\"") + +def escape_char(v): + if v == "\n": + return "\\n" + elif v == "\t": + return "\\t" + elif v == "\v": + return "\\v" + elif v == "\b": + return "\\b" + elif v == "\r": + return "\\r" + elif v == "\f": + return "\\f" + elif v == "\a": + return "\\a" + elif v == "\\": + return "\\\\" + elif v == "\"": + return "\\\"" + elif ord(v) < 32 and ord(v) > 127: + return "\\x" + hex(v)[2:].upper().rjust(2, '0') + else: + return v + +def escape(v): + return "".join([ escape_char(x) for x in list(v) ]) + + +class Symbol: + def __init__(self, name, addr, size): + self.name = name + self.addr = addr + self.size = size + self.padding = 0 + + def __str__(self): + return " %s %s %s+%s %s" % (self.name.ljust(40, ' '), hex(self.addr), hex(self.addr + self.size), hex(self.padding), hex(self.size)) + +class ObjectFile: + def __init__(self, path): + self.path = path + self.symbols = [] + self.start = 0 + self.end = 0 + self.mk = False + + def addSymbol(self, name, str_addr, str_size): + addr = int(str_addr, base=16) + size = int(str_size, base=16) + + symbol = Symbol(name, addr, size) + if not self.symbols: + self.start = symbol.addr + else: + last_symbol = self.symbols[-1] + last_addr = last_symbol.addr + last_symbol.size + if last_addr != addr: + last_symbol.padding += addr - last_addr + self.symbols += [ symbol ] + + def setEnd(self, end): + self.end = end + last_symbol = self.symbols[-1] + last_symbol.padding = self.end - (last_symbol.addr + last_symbol.size) + +def find_symbols(): + file = open('frameworkF.map', 'r') + lines = file.readlines() + + in_section = False + last_obj = None + for line in lines: + data = [ x.strip() for x in line.strip().split(" ") ] + data = [ x for x in data if len(x) > 0 ] + + if len(data) == 3: + in_section = False + if data[0] == section: + in_section = True + continue + + if not in_section: + continue + if len(data) < 6 or len(data) > 7: + continue + + # get object filename + obj = data[5] + if len(data) > 6: + obj = data[6] + + # remove path from object filename + obj = obj.split("\\")[-1] + if last_obj != obj: + assert obj not in object_map + object_map[obj] = ObjectFile(obj) + last_obj = obj + + # add symbol + size = data[1] + addr = data[2] + name = data[4] + object_map[obj].addSymbol(name, addr, size) + + keys = list(object_map.keys()) + for i,_ in enumerate(keys[:-1]): + obj = object_map[keys[i]] + next_obj = object_map[keys[i + 1]] + obj.setEnd(next_obj.start) + + # total size of rodata must be aligned to 0x20 + obj = object_map[keys[-1]] + last_symbol = obj.symbols[-1] + last_addr = last_symbol.addr + last_symbol.size + last_symbol.padding = ((last_addr + 31) & ~31) - last_addr + file.close() + +def output_cpp(): + if not object_name in object_map: + print("error: %s object file not found!" % object_name) + sys.exit(1) + + br = baserom.open("rb") + br.seek(0, os.SEEK_END) + br_size = br.tell() + br.seek(0, os.SEEK_SET) + + obj = object_map[object_name] + for symbol in obj.symbols: + + label = "lbl_%s" % (hex(symbol.addr).upper()[2:]) + + symbol_file_offset = symbol.addr - file_offset + symbol_file_size = symbol.size + symbol.padding + + if symbol_file_offset + symbol_file_size > br_size: + print("error: reading outside baserom file. (%i, %i)" % (symbol_file_offset + symbol_file_size, br_size)) + + br.seek(symbol_file_offset, os.SEEK_SET) + data = br.read(symbol.size) + padding = br.read(symbol.padding) + + + value = "???" + if len(data) == 4: + u32_data = struct.unpack('>I', data)[0] + s32_data = struct.unpack('>i', data)[0] + float_data = struct.unpack('>f', data)[0] + + if s32_data == 0 or (s32_data >= -4096 and s32_data <= 4096): + value = str(s32_data) + elif u32_data == 0 or u32_data <= 4096: + value = str(u32_data) + elif int(float_data) == float_data and float_data >= -4096 and float_data <= 4096: + value = "%sf (%s)" % (str(float_data), hex(u32_data)) + elif len(data) == 8: + u64_data = struct.unpack('>Q', data)[0] + s64_data = struct.unpack('>q', data)[0] + double_data = struct.unpack('>d', data)[0] + + if s64_data == 0 or (s64_data >= -4096 and s64_data <= 4096): + value = str(s64_data) + elif u64_data == 0 or u64_data <= 4096: + value = str(u64_data) + elif int(double_data) == double_data and double_data >= -4096 and double_data <= 4096: + value = "%s (%s)" % (str(double_data), hex(u64_data)) + + print("// %s %s %s = %s" % (label, obj.path, symbol.name, value)) + if args.as_string: + offset = 0 + str_segments = [ x + [0] for x in magicsplit(data, 0) ] + for segment in str_segments[:-1]: + str_data = bytes(segment) + encoding = str_encoding(str_data) + + str_label = "lbl_%s" % (hex(symbol.addr + offset).upper()[2:]) + if encoding == "shift-jis" : + print("const char* %s = \"%s\"; /* shift-jis encoded (TODO) */" % (str_label, raw_string(str_data))) + elif encoding == "utf-8" : + print("const char* %s = \"%s\";" % (str_label, raw_string(str_data))) + else: + print("const char* %s = \"%s\"; /* undecodable string */" % (str_label, raw_string(str_data))) + offset += len(str_data) + + if padding: + padding_label = "lbl_%s" % (hex(symbol.addr + symbol.size).upper()[2:]) + print("const char* %s = \"%s\"; /* padding */" % (padding_label, raw_string(padding))) + else: + cpp_array = ",".join([hex(x) for x in list(data)]) + print("static const u8 %s[%i] = { %s };" % (label, len(data), cpp_array)) + + if padding: + padding_label = "lbl_%s" % (hex(symbol.addr + symbol.size).upper()[2:]) + cpp_array = ",".join([hex(x) for x in list(padding)]) + print("static const u8 %s[%i] = { %s }; /* padding */" % (padding_label, len(padding), cpp_array)) + + br.close() + +# +# +# + +try: + args = parser.parse_args() +except: + parser.print_help() + sys.exit(0) + +section = args.section +object_name = args.object_name +file_offset: Optional[int] = args.file_offset +baserom = Path(args.baserom) + +file_offsets = { + ".rodata": 0x80003000, + ".sdata": 0x800802A0, + ".sdata2": 0x800811A0, +} + +if not file_offset: + if not section in file_offsets: + print("error: missing --file-offset") + sys.exit(1) + else: + file_offset = file_offsets[section] + +if not baserom.exists(): + print("error: baserom '%s' not found!" % args.baserom) + sys.exit(1) + +object_map: Dict[str,ObjectFile] = {} + +find_symbols() +output_cpp()