diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 34ce56fe..e11feb0e 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -66,8 +66,11 @@ d/d_dvd_unk.cpp: d/d_dylink.cpp: .text start:0x80052E00 end:0x80053A30 .ctors start:0x804DB674 end:0x804DB678 - .data start:0x8050D2D8 end:0x8050D30C + .rodata start:0x804DDFD0 end:0x804DDFF0 + .data start:0x8050D2D8 end:0x8050D348 + .sdata start:0x80571C40 end:0x80571C50 .sbss start:0x805750E0 end:0x805750FC + .bss start:0x805975B0 end:0x80597608 d/d_fader.cpp: .text start:0x80053A30 end:0x80053E70 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 8f6bb548..78573dd8 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -2167,23 +2167,23 @@ fn_80052D00 = .text:0x80052D00; // type:function size:0x14 fn_80052D20 = .text:0x80052D20; // type:function size:0x30 fn_80052D50 = .text:0x80052D50; // type:function size:0x78 fn_80052DD0 = .text:0x80052DD0; // type:function size:0x2C -fn_80052E00 = .text:0x80052E00; // type:function size:0x1A0 -fn_80052FA0 = .text:0x80052FA0; // type:function size:0x30 +initDylinkHeap__4dDylFiPC10RelNamePtriPQ23EGG4Heap = .text:0x80052E00; // type:function size:0x1A0 +isLinked__4dDylFUs = .text:0x80052FA0; // type:function size:0x30 Unlink__4dDylFUs = .text:0x80052FD0; // type:function size:0x20 -fn_80052FF0 = .text:0x80052FF0; // type:function size:0x84 -fn_80053080 = .text:0x80053080; // type:function size:0x58 -fn_800530E0 = .text:0x800530E0; // type:function size:0x7C -fn_80053160 = .text:0x80053160; // type:function size:0xDC +tryLink__4dDylFUs = .text:0x80052FF0; // type:function size:0x84 +nandCallback__4dDylFlP16NANDCommandBlock = .text:0x80053080; // type:function size:0x58 +dvdCallback__4dDylFlP11DVDFileInfo = .text:0x800530E0; // type:function size:0x7C +startDvdRead__4dDylFPQ24dDyl13UnkNandStructPvll = .text:0x80053160; // type:function size:0xDC fn_80053240 = .text:0x80053240; // type:function size:0x35C -fn_800535A0 = .text:0x800535A0; // type:function size:0xB0 -fn_80053650 = .text:0x80053650; // type:function size:0xDC -fn_80053730 = .text:0x80053730; // type:function size:0x48 -fn_80053780 = .text:0x80053780; // type:function size:0x54 -fn_800537E0 = .text:0x800537E0; // type:function size:0x30 -fn_80053810 = .text:0x80053810; // type:function size:0x6C -fn_80053880 = .text:0x80053880; // type:function size:0xC -do_link__21dDynamicModuleControlFv = .text:0x80053890; // type:function size:0xA0 -fn_80053930 = .text:0x80053930; // type:function size:0x9C +loadRelsArcCallback__4dDylFPv = .text:0x800535A0; // type:function size:0xB0 +dvdCallback__4dDylFPv = .text:0x80053650; // type:function size:0xDC +initModule__4dDylFv = .text:0x80053730; // type:function size:0x48 +destroy__4dDylFv = .text:0x80053780; // type:function size:0x54 +initRelsArc__4dDylFv = .text:0x800537E0; // type:function size:0x30 +__dt__21dDynamicModuleControlFv = .text:0x80053810; // type:function size:0x6C +set__21dDynamicModuleControlFPUsi = .text:0x80053880; // type:function size:0xC +do_link__21dDynamicModuleControlCFv = .text:0x80053890; // type:function size:0xA0 +do_unlink__21dDynamicModuleControlFv = .text:0x80053930; // type:function size:0x9C __sinit_\d_dylink_cpp = .text:0x800539D0; // type:function size:0x54 fn_80053A30 = .text:0x80053A30; // type:function size:0xE4 fn_80053B20 = .text:0x80053B20; // type:function size:0x128 @@ -17756,9 +17756,9 @@ __ct__14mDvd_command_cFv = .text:0x802EF460; // type:function size:0x1C do_delete__14mDvd_command_cFv = .text:0x802EF480; // type:function size:0x20 destroy__14mDvd_command_cFPP14mDvd_command_c = .text:0x802EF4A0; // type:function size:0x54 __dt__15mDvd_callback_cFv = .text:0x802EF500; // type:function size:0x58 -__ct__15mDvd_callback_cFPFPv_bPv = .text:0x802EF560; // type:function size:0x64 -create__15mDvd_callback_cFPFPv_bPv = .text:0x802EF5D0; // type:function size:0x78 -fn_802EF650 = .text:0x802EF650; // type:function size:0x30 +__ct__15mDvd_callback_cFPFPv_UlPv = .text:0x802EF560; // type:function size:0x64 +create__15mDvd_callback_cFPFPv_UlPv = .text:0x802EF5D0; // type:function size:0x78 +createOrFail__15mDvd_callback_cFPFPv_UlPv = .text:0x802EF650; // type:function size:0x30 execute__15mDvd_callback_cFv = .text:0x802EF680; // type:function size:0x54 __dt__22mDvd_mountMemArchive_cFv = .text:0x802EF6E0; // type:function size:0x58 __ct__22mDvd_mountMemArchive_cFi = .text:0x802EF740; // type:function size:0x74 @@ -21967,7 +21967,7 @@ fn_803A94D0 = .text:0x803A94D0; // type:function size:0x4 fn_803A94E0 = .text:0x803A94E0; // type:function size:0x4 fn_803A94F0 = .text:0x803A94F0; // type:function size:0x4 fn_803A9500 = .text:0x803A9500; // type:function size:0x4 -fn_803A9510 = .text:0x803A9510; // type:function size:0xC +OSSetStringTable = .text:0x803A9510; // type:function size:0xC fn_803A9520 = .text:0x803A9520; // type:function size:0x2C4 fn_803A97F0 = .text:0x803A97F0; // type:function size:0x2E8 OSLink = .text:0x803A9AE0; // type:function size:0x8 @@ -22633,10 +22633,10 @@ fn_803D0790 = .text:0x803D0790; // type:function size:0x40 fn_803D07D0 = .text:0x803D07D0; // type:function size:0x14C fn_803D0920 = .text:0x803D0920; // type:function size:0x1F4 fn_803D0B20 = .text:0x803D0B20; // type:function size:0x140 -fn_803D0C60 = .text:0x803D0C60; // type:function size:0x74 +NANDCreate = .text:0x803D0C60; // type:function size:0x74 fn_803D0CE0 = .text:0x803D0CE0; // type:function size:0x74 fn_803D0D60 = .text:0x803D0D60; // type:function size:0x78 -fn_803D0DE0 = .text:0x803D0DE0; // type:function size:0xB0 +NANDDelete = .text:0x803D0DE0; // type:function size:0xB0 fn_803D0E90 = .text:0x803D0E90; // type:function size:0x98 fn_803D0F30 = .text:0x803D0F30; // type:function size:0xC0 NANDRead = .text:0x803D0FF0; // type:function size:0x68 @@ -22657,8 +22657,8 @@ fn_803D1910 = .text:0x803D1910; // type:function size:0x154 fn_803D1A70 = .text:0x803D1A70; // type:function size:0x74 fn_803D1AF0 = .text:0x803D1AF0; // type:function size:0x64 fn_803D1B60 = .text:0x803D1B60; // type:function size:0x84 -fn_803D1BF0 = .text:0x803D1BF0; // type:function size:0x8 -fn_803D1C00 = .text:0x803D1C00; // type:function size:0x8 +NANDSetUserData = .text:0x803D1BF0; // type:function size:0x8 +NANDGetUserData = .text:0x803D1C00; // type:function size:0x8 fn_803D1C10 = .text:0x803D1C10; // type:function size:0x334 nandOpen = .text:0x803D1F50; // type:function size:0x110 scope:local NANDOpen = .text:0x803D2060; // type:function size:0x8C @@ -26132,7 +26132,7 @@ removeList__Q23EGG7ArchiveFPQ23EGG7Archive = .text:0x80493850; // type:function mount__Q23EGG7ArchiveFPvPQ23EGG4Heapi = .text:0x80493860; // type:function size:0xE4 mountType2__Q23EGG7ArchiveFPvPQ23EGG4Heapi = .text:0x80493950; // type:function size:0xE4 mountNandFile__EGG__Archive = .text:0x80493A40; // type:function size:0x7C -getNandFile__EGG__Ardhive = .text:0x80493AC0; // type:function size:0xBC +loadFST__Q23EGG7ArchiveFPCcPQ23EGG4Heapl = .text:0x80493AC0; // type:function size:0xBC unmount__Q23EGG7ArchiveFv = .text:0x80493B80; // type:function size:0x94 getFile__Q23EGG7ArchiveFPCcPQ33EGG7Archive8FileInfo = .text:0x80493C20; // type:function size:0xC4 convertPathToEntryID__Q23EGG7ArchiveFPCc = .text:0x80493CF0; // type:function size:0x8 @@ -27833,7 +27833,7 @@ lbl_804DC948 = .rodata:0x804DC948; // type:object size:0xDC lbl_804DCA24 = .rodata:0x804DCA24; // type:object size:0x80 lbl_804DCAA4 = .rodata:0x804DCAA4; // type:object size:0x80 lbl_804DCB24 = .rodata:0x804DCB24; // type:object size:0xCC -lbl_804DCBF0 = .rodata:0x804DCBF0; // type:object size:0x13E0 +DYNAMIC_NAME_TABLE = .rodata:0x804DCBF0; // type:object size:0x13E0 lbl_804DDFD0 = .rodata:0x804DDFD0; // type:object size:0xC data:4byte lbl_804DDFDC = .rodata:0x804DDFDC; // type:object size:0x14 data:4byte lbl_804DDFF0 = .rodata:0x804DDFF0; // type:object size:0x18 @@ -30698,7 +30698,7 @@ lbl_8050D2CC = .data:0x8050D2CC; // type:object size:0xC lbl_8050D2D8 = .data:0x8050D2D8; // type:object size:0x32 data:string lbl_8050D30C = .data:0x8050D30C; // type:object size:0x14 lbl_8050D320 = .data:0x8050D320; // type:object size:0x10 -lbl_8050D330 = .data:0x8050D330; // type:object size:0xC +__vt__21dDynamicModuleControl = .data:0x8050D330; // type:object size:0xC lbl_8050D33C = .data:0x8050D33C; // type:object size:0xC lbl_8050D348 = .data:0x8050D348; // type:object size:0x10 lbl_8050D358 = .data:0x8050D358; // type:object size:0x10 data:string @@ -37576,8 +37576,8 @@ lbl_80571C20 = .sdata:0x80571C20; // type:object size:0x8 data:string lbl_80571C28 = .sdata:0x80571C28; // type:object size:0x8 lbl_80571C30 = .sdata:0x80571C30; // type:object size:0x8 data:string lbl_80571C38 = .sdata:0x80571C38; // type:object size:0x8 data:string -lbl_80571C40 = .sdata:0x80571C40; // type:object size:0x4 data:4byte -lbl_80571C44 = .sdata:0x80571C44; // type:object size:0x4 data:4byte +status_1__4dDyl = .sdata:0x80571C40; // type:object size:0x4 data:4byte +status_2__4dDyl = .sdata:0x80571C44; // type:object size:0x4 data:4byte lbl_80571C48 = .sdata:0x80571C48; // type:object size:0x8 lbl_80571C50 = .sdata:0x80571C50; // type:object size:0x8 data:float lbl_80571C58 = .sdata:0x80571C58; // type:object size:0x8 data:byte diff --git a/include/DynamicLink.h b/include/DynamicLink.h index 1e9e3319..9b600242 100644 --- a/include/DynamicLink.h +++ b/include/DynamicLink.h @@ -61,7 +61,7 @@ struct DynamicModuleControl : DynamicModuleControlBase { /* 802dfa60 */ virtual bool do_unlink(); /* 802df3d0 */ DynamicModuleControl(char const*, EGG::ExpHeap *); /* 802df4d0 */ static void initialize(EGG::ExpHeap *heap); - /* 802df530 */ static bool callback(void*); + /* 802df530 */ static u32 callback(void*); void checkHeapStatus(); /* 0x10 */ UNKWORD unk_16; diff --git a/include/d/d_dylink.h b/include/d/d_dylink.h index c7a0a6a2..3aef764e 100644 --- a/include/d/d_dylink.h +++ b/include/d/d_dylink.h @@ -3,10 +3,18 @@ #include -namespace dDyl { +class dDynamicModuleControl { +public: + dDynamicModuleControl() {} + virtual ~dDynamicModuleControl(); -bool Unlink(u16 relId); + void set(u16 *ptr, int count); + BOOL do_link() const; + BOOL do_unlink(); -} // dDyl +private: + u16 *mPtr; + int mCount; +}; #endif diff --git a/include/m/m_dvd.h b/include/m/m_dvd.h index 11890653..8045f220 100644 --- a/include/m/m_dvd.h +++ b/include/m/m_dvd.h @@ -69,7 +69,7 @@ public: u8 mCompressionType; }; -typedef bool (*dvdReadCallback)(void *); +typedef u32 (*dvdReadCallback)(void *); class mDvd_callback_c : public mDvd_command_c { public: @@ -78,10 +78,11 @@ public: virtual u32 execute() override; static mDvd_callback_c *create(dvdReadCallback cb, void *cbData); + static mDvd_callback_c *createOrFail(dvdReadCallback cb, void *cbData); dvdReadCallback mCallback; void *mCallbackData; - BOOL mSuccess; + u32 mCallbackResult; }; class mDvd_mountMemArchive_c : public mDvd_command_c { diff --git a/include/m/m_heap.h b/include/m/m_heap.h index 3cc53ff3..c6681bb6 100644 --- a/include/m/m_heap.h +++ b/include/m/m_heap.h @@ -32,7 +32,7 @@ public: } /* 802f12b0 */ mHeap(EGG::Heap *heap); /* 802f12f0 */ ~mHeap(); - /* 802f1350 */ static EGG::Heap *createHeap(size_t size, EGG::Heap *, const char *name); + /* 802f1350 */ static EGG::ExpHeap *createHeap(size_t size, EGG::Heap *, const char *name); /* 802f13d0 */ static void saveCurrentHeap(); /* 802f13e0 */ static void restoreCurrentHeap(); /* 802f1410 */ static EGG::FrmHeap *makeFrmHeapAndUpdate(size_t size, EGG::Heap *parentHeap, const char *name, @@ -56,7 +56,7 @@ public: static EGG::Heap *s_SavedCurrentHeap; static EGG::Heap *g_archiveHeap; static EGG::Heap *g_commandHeap; - static EGG::Heap *g_dylinkHeap; + static EGG::ExpHeap *g_dylinkHeap; static EGG::AssertHeap *g_assertHeap; static u8 g_DefaultGameHeapId; static const char *const s_GameHeapNames[4]; diff --git a/src/DynamicLink.cpp b/src/DynamicLink.cpp index 2c7947c0..526e12ce 100644 --- a/src/DynamicLink.cpp +++ b/src/DynamicLink.cpp @@ -129,7 +129,7 @@ void DynamicModuleControl::initialize(EGG::ExpHeap *heap) { sTotalFreeSize = heap->getTotalFreeSize(); } -bool DynamicModuleControl::callback(void *arg) { +u32 DynamicModuleControl::callback(void *arg) { return static_cast(arg)->do_load(); } diff --git a/src/d/d_dylink.cpp b/src/d/d_dylink.cpp index 3bec3f39..6ab8cbdb 100644 --- a/src/d/d_dylink.cpp +++ b/src/d/d_dylink.cpp @@ -1,8 +1,10 @@ -#include #include +#include #include #include #include +#include +#include // clang-format off #include // clang-format on @@ -12,9 +14,13 @@ struct RelNamePtr { const char *name; }; -static RelNamePtr *pDynamicNameTable; +extern const RelNamePtr DYNAMIC_NAME_TABLE[]; + +static const RelNamePtr *pDynamicNameTable; static int nDynamicNameTable; +DynamicModuleControl g_DMC("d_profile", nullptr); + namespace dDyl { DynamicModuleControl **pDMC; @@ -23,8 +29,21 @@ EGG::Heap *cCc_frmHeap; u32 Initialized; mDvd_callback_c *DVD; -// initDylinkHeap -extern "C" int fn_80052E00(int maxRelId, RelNamePtr *dynNameTable, int dynNameTableNum, EGG::Heap *parentHeap) { +enum NandChunkStatus { + Success = 1, + DVDPending = 2, + NANDPending = 4, + Error = 8, + + FinalizedMask = Success | Error, +}; + +NandChunkStatus status_1 = Success; +NandChunkStatus status_2 = Success; +char relsDir[] = "/rels"; + +/** 80052E00 */ +int initDylinkHeap(int maxRelId, const RelNamePtr *dynNameTable, int dynNameTableNum, EGG::Heap *parentHeap) { cCc_frmHeap = mHeap::createFrmHeap(maxRelId * 0x10 + dynNameTableNum * 0x48, parentHeap, "ダイナミックリンク制御用ヒープ(dDyl::cCc_frmHeap)", 0x20, 0); @@ -38,7 +57,7 @@ extern "C" int fn_80052E00(int maxRelId, RelNamePtr *dynNameTable, int dynNameTa nDynamicNameTable = dynNameTableNum; for (int i = 0; i < nDynamicNameTable; i++) { - RelNamePtr *rel = &pDynamicNameTable[i]; + const RelNamePtr *rel = &pDynamicNameTable[i]; if (rel->name != nullptr) { for (int j = 0; j < nDMC; j++) { DynamicModuleControl **dmc = &pDMC[j]; @@ -59,12 +78,12 @@ extern "C" int fn_80052E00(int maxRelId, RelNamePtr *dynNameTable, int dynNameTa return 1; } -// isLoaded? -extern "C" bool fn_80052FA0(u16 relId) { +/** 80052FA0 */ +bool isLinked(u16 relId) { return pDMC[relId] != nullptr ? pDMC[relId]->isLinked() : true; } -bool dDyl::Unlink(u16 relId) { +BOOL Unlink(u16 relId) { DynamicModuleControl *dmc = pDMC[relId]; if (dmc != nullptr) { return dmc->unlink(); @@ -73,7 +92,7 @@ bool dDyl::Unlink(u16 relId) { return false; } -extern "C" int fn_80052FF0(u16 relId) { +int tryLink(u16 relId) { if (!Initialized) { return 0; } @@ -81,8 +100,7 @@ extern "C" int fn_80052FF0(u16 relId) { DynamicModuleControl *dmc = pDMC[relId]; if (dmc != nullptr) { if (dmc->load_async()) { - // what is going on here? - return (bool)dmc->link() + 2; + return dmc->link() ? 1 : 2; } else { return 0; } @@ -91,4 +109,283 @@ extern "C" int fn_80052FF0(u16 relId) { } } +// TODO prevent moves +struct UnkNandStruct { + /* 0x00 */ NandChunkStatus status; + /* 0x04 */ OSThreadQueue queue; + /* 0x0C */ DVDFileInfo dvdFileInfo; + /* 0x48 */ NANDFileInfo *nandFileInfo; + /* 0x4C */ NANDCommandBlock nandBlock; + + UnkNandStruct() { + status = status_2; + OSInitThreadQueue(&queue); + nandFileInfo = nullptr; + updateStatus(status_1); + nandFileInfo = nullptr; + dvdFileInfo.block.userData = this; + NANDSetUserData(&nandBlock, this); + } + + void waitForFinalization() { + if (!isFinalized()) { + BOOL enabled = OSDisableInterrupts(); + while (!isFinalized()) { + OSSleepThread(&queue); + } + OSRestoreInterrupts(enabled); + } + } + + bool isFinalized() { + return (status & FinalizedMask) != 0; + } + + void updateStatus(NandChunkStatus newStatus) { + if (status != newStatus) { + status = newStatus; + OSWakeupThread(&queue); + } + } + + void open(s32 entryNum, NANDFileInfo *fInfo) { + DVDFastOpen(entryNum, &dvdFileInfo); + nandFileInfo = fInfo; + } + + bool isError() { + return (status & Error) != 0; + } +}; + +void nandCallback(s32 result, NANDCommandBlock *block) { + UnkNandStruct *s = reinterpret_cast(NANDGetUserData(block)); + NandChunkStatus status = result >= 0 ? Success : Error; + s->updateStatus(status); +} + +void dvdCallback(s32 result, DVDFileInfo *dvdInfo) { + NandChunkStatus status = Error; + UnkNandStruct *s = reinterpret_cast(dvdInfo->block.userData); + u32 length = dvdInfo->block.length; + if (result == length) { + if (!NANDWriteAsync(s->nandFileInfo, dvdInfo->block.addr, length, nandCallback, &s->nandBlock)) { + status = NANDPending; + } + } + s->updateStatus(status); +} + +bool startDvdRead(UnkNandStruct *s, void *dst, s32 size, s32 offset) { + s->waitForFinalization(); + + if ((s->status & 8) != 0) { + return false; + } + + BOOL dvdResult = DVDReadAsyncPrio(&s->dvdFileInfo, dst, size, offset, dvdCallback, 2); + NandChunkStatus status = dvdResult != 0 ? DVDPending : Error; + s->updateStatus(status); + return dvdResult; +} + +extern "C" void fn_802DEFE0(const char *fmt, ...); + +extern "C" bool fn_80053240(char *relPath, char *tmpRelPath, EGG::Heap *heap) { + DVDFileInfo dvdFileInfo; + NANDFileInfo nandFileInfo; + + s32 entryNum = DVDConvertPathToEntrynum(relPath); + if (entryNum < 0 || !DVDFastOpen(entryNum, &dvdFileInfo)) { + goto err; + } + + u32 sizeRead = 0; + + u32 fileSize = ROUND_UP(dvdFileInfo.size, 0x20); + NANDResult deleteResult = NANDDelete(tmpRelPath); + if (deleteResult != NAND_RESULT_OK && deleteResult != NAND_RESULT_NOEXISTS) { + goto end; + } + + if (NANDCreate(tmpRelPath, NAND_PERM_RUSR | NAND_PERM_WUSR, 0) || NANDOpen(tmpRelPath, &nandFileInfo, 2)) { + goto end; + } + + fn_802DEFE0("BufferSize %u KB\n", 0x200); + + void *buf = heap->alloc(0x80000, 0x20); + if (buf == nullptr) { + goto end; + } + + // Weird part start (everything above this is regshuffles) + + // TODO the initialization of this value is a bit + // weird because it essentially computes the signed + // division 0x80000 / 2 + // (which adds +1 to the dividend if the result is negative to + // ensure rounding to 0 behavior) + // and the optimizer fails to constant propagate these through + // to realize that 0x80000 is actually always positive + int totalBufSize = 0x80000; + int chunkSize = 0x80000 / 2; + + // TODO this initalization happens slightly differently + UnkNandStruct nandStructs[2]; + + // Weird part end (most below this is regshuffles) + + nandStructs[0].open(entryNum, &nandFileInfo); + nandStructs[1].open(entryNum, &nandFileInfo); + + // dispatch multiple requests to load parts of the profile REL in parallel + int whichThread = 0; + for (; sizeRead < fileSize; sizeRead += chunkSize) { + if (chunkSize > fileSize - sizeRead) { + chunkSize = fileSize - sizeRead; + } + // NB the whichThread * totalBufSize / 2 match relies on whichThread * totalBufSize being able to overflow + if (!startDvdRead(&nandStructs[whichThread], ((u8 *)buf) + whichThread * totalBufSize / 2, chunkSize, + /* offset */ sizeRead)) { + break; + } + + whichThread ^= 1; + } + + nandStructs[0].waitForFinalization(); + nandStructs[1].waitForFinalization(); + + if (nandStructs[0].isError() || nandStructs[1].isError()) { + sizeRead = 0; + } + + // Yes this condition is extremely weird but in the binary + // this literally checks if a stack address isn't zero + // There's also a bit of a weird addressing going on here + if ((u32)&nandStructs[1]) { + nandStructs[1].waitForFinalization(); + } + nandStructs[0].waitForFinalization(); + + heap->free(buf); + if (NANDClose(&nandFileInfo) != NAND_RESULT_OK) { + sizeRead = 0; + } + +end: + DVDClose(&dvdFileInfo); + return sizeRead >= fileSize; + +err: + return false; +} + +u32 loadRelsArcCallback(void *arg) { + EGG::Archive *arc = nullptr; + EGG::Heap *heap = DynamicModuleControl::sDylinkHeap; + + char rels[] = "/rels.arc"; + char tmpRels[] = "/tmp/rels.arc"; + + if (fn_80053240(rels, tmpRels, heap)) { + arc = EGG::Archive::loadFST(tmpRels, heap, 0x20); + } + if (arc != nullptr) { + DynamicModuleControl::sArchive = arc; + } + return (u32)arc; +} + +u32 dvdCallback(void *arg) { + DynamicModuleControl::initialize(mHeap::g_dylinkHeap); + DynamicModuleControl::sRelsDir = relsDir; + DVDFileInfo info; + + if (DVDOpen("/RVZELDANP.str", &info)) { + if (info.size != 0) { + u32 size = ROUND_UP(info.size, 0x20); + void *destination = DynamicModuleControl::sDylinkHeap->alloc(size, 0x20); + DVDReadPrio(&info, destination, size, 0, 2); + OSSetStringTable(destination); + } + DVDClose(&info); + } + + BOOL result = g_DMC.link(); + do { + } while (!result); + Initialized = 1; + return true; +} + +void initModule() { + initDylinkHeap(0x2bf, DYNAMIC_NAME_TABLE, 0x27c, mHeap::g_dylinkHeap); + DVD = mDvd_callback_c::createOrFail(dvdCallback, mHeap::g_dylinkHeap); +} + +void initRelsArc() { + DVD = mDvd_callback_c::createOrFail(loadRelsArcCallback, nullptr); +} + +bool destroy() { + if (DVD == nullptr) { + return true; + } + + if (DVD->mStatus != 0) { + DVD->do_delete(); + DVD = nullptr; + return true; + } + + return false; +} + } // namespace dDyl + +dDynamicModuleControl::~dDynamicModuleControl() { + if (mPtr != nullptr) { + do_unlink(); + } +} + +void dDynamicModuleControl::set(u16 *ptr, int count) { + mPtr = ptr; + mCount = count; +} + +BOOL dDynamicModuleControl::do_link() const { + if (mPtr == nullptr) { + return true; + } + bool result = true; + u16 *rel = mPtr; + for (int i = 0; i < mCount; i++) { + bool linked = dDyl::isLinked(*rel); + if (!linked && dDyl::tryLink(*rel) != 1) { + result = false; + goto end; + } + rel++; + } +end: + return result; +} + +BOOL dDynamicModuleControl::do_unlink() { + u16 *rel = mPtr; + if (rel == nullptr) { + return true; + } + for (int i = 0; i < mCount; i++) { + bool linked = dDyl::isLinked(*rel); + if (linked && dDyl::Unlink(*rel) == 0) { + return false; + } + rel++; + } + mPtr = nullptr; + return true; +} diff --git a/src/m/m_dvd.cpp b/src/m/m_dvd.cpp index 82fce847..21fed247 100644 --- a/src/m/m_dvd.cpp +++ b/src/m/m_dvd.cpp @@ -330,7 +330,7 @@ mDvd_callback_c::~mDvd_callback_c() {} mDvd_callback_c::mDvd_callback_c(dvdReadCallback cb, void *cbData) { mCallback = cb; mCallbackData = cbData; - mSuccess = false; + mCallbackResult = 0; } /* 802ef5d0 */ @@ -343,7 +343,7 @@ mDvd_callback_c *mDvd_callback_c::create(dvdReadCallback cb, void *cbData) { } /** 802ef650 */ -extern "C" mDvd_callback_c *fn_802EF650(dvdReadCallback cb, void *cbData) { +mDvd_callback_c *mDvd_callback_c::createOrFail(dvdReadCallback cb, void *cbData) { mDvd_callback_c *cmd = mDvd_callback_c::create(cb, cbData); while (!cmd) {} return cmd; @@ -351,9 +351,9 @@ extern "C" mDvd_callback_c *fn_802EF650(dvdReadCallback cb, void *cbData) { /** 802ef680 */ u32 mDvd_callback_c::execute() { - mSuccess = (mCallback)(mCallbackData); + mCallbackResult = (mCallback)(mCallbackData); waitDone(); - return (bool)mSuccess; + return (bool)mCallbackResult; } /** 802ef6e0 */ diff --git a/src/m/m_heap.cpp b/src/m/m_heap.cpp index 6ab9cc12..ca18857f 100644 --- a/src/m/m_heap.cpp +++ b/src/m/m_heap.cpp @@ -11,7 +11,7 @@ EGG::Heap *mHeap::g_gameHeaps[4]; EGG::Heap *mHeap::s_SavedCurrentHeap; EGG::Heap *mHeap::g_archiveHeap; EGG::Heap *mHeap::g_commandHeap; -EGG::Heap *mHeap::g_dylinkHeap; +EGG::ExpHeap *mHeap::g_dylinkHeap; EGG::AssertHeap *mHeap::g_assertHeap; const char *const mHeap::s_GameHeapNames[4] = { 0, @@ -144,7 +144,7 @@ mHeap::~mHeap() { heap->becomeCurrentHeap(); } -EGG::Heap *mHeap::createHeap(size_t size, EGG::Heap *block, const char *name) { +EGG::ExpHeap *mHeap::createHeap(size_t size, EGG::Heap *block, const char *name) { EGG::ExpHeap *heap = EGG::ExpHeap::create(size, block, 4); if (heap != nullptr) { heap->setGroupID(0);