diff options
| author | Luke Street <luke.street@encounterpc.com> | 2023-09-10 00:42:26 -0400 |
|---|---|---|
| committer | Luke Street <luke.street@encounterpc.com> | 2023-09-10 00:48:55 -0400 |
| commit | adb95b135c3d7498eba29bbd9728d345eed5a407 (patch) | |
| tree | 655575b939c12067569263171b68c079b1a232c8 /src/DynamicLink.cpp | |
| parent | 81ac53f1317dafb3506ae3ed8b2820d40645c3c8 (diff) | |
Import project
Original repository: https://github.com/encounter/ww
Diffstat (limited to 'src/DynamicLink.cpp')
| -rw-r--r-- | src/DynamicLink.cpp | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/src/DynamicLink.cpp b/src/DynamicLink.cpp new file mode 100644 index 00000000..1a4c56c9 --- /dev/null +++ b/src/DynamicLink.cpp @@ -0,0 +1,510 @@ +/** + * DynamicLink.cpp + * REL Linking Manager + */ + +#include "DynamicLink.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRDvdRipper.h" +#include "JSystem/JKernel/JKRExpHeap.h" +#include "JSystem/JKernel/JKRFileCache.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "MSL_C/stdio.h" +#include "REL/executor.h" +#include "m_Do/m_Do_dvd_thread.h" +#include "dolphin/os/OS.h" + +// TODO +// #include "m_Do/m_Do_ext.h" +JKRExpHeap* mDoExt_getArchiveHeap(); +extern JKRExpHeap* archiveHeap; +// end m_Do_ext.h + +DynamicModuleControlBase* DynamicModuleControlBase::mFirst; +DynamicModuleControlBase* DynamicModuleControlBase::mLast; + +DynamicModuleControlBase::~DynamicModuleControlBase() { + force_unlink(); + if (mPrev != NULL) { + mPrev->mNext = mNext; + } + if (mNext != NULL) { + mNext->mPrev = mPrev; + } + if (mFirst == this) { + mFirst = mNext; + } + if (mLast == this) { + mLast = mPrev; + } + mNext = NULL; + mPrev = NULL; +} + +DynamicModuleControlBase::DynamicModuleControlBase() { + mLinkCount = 0; + mDoLinkCount = 0; + mNext = NULL; + if (mFirst == NULL) { + mFirst = this; + } + mPrev = mLast; + if (mPrev != NULL) { + mPrev->mNext = this; + } + mLast = this; +} + +extern OSThread mainThread; + +BOOL DynamicModuleControlBase::link() { + OSThread* thread = OSGetCurrentThread(); + if (thread != &mainThread) { + OSReport_Error("DynamicModuleControlBase::link not mainthread %08x\n", thread); + } + + if (mLinkCount == 0) { + do_load(); + if (do_link() == false) { + return false; + } + if (mDoLinkCount < 65535) { + mDoLinkCount++; + } + } + JUT_ASSERT(__FILE__, 100, mLinkCount < 65535); + if (mLinkCount < 65535) { + mLinkCount++; + } + return true; +} + +BOOL DynamicModuleControlBase::unlink() { + OSThread* thread = OSGetCurrentThread(); + if (thread != &mainThread) { + OSReport_Error("DynamicModuleControlBase::unlink not mainthread %08x\n", thread); + } + + if (mLinkCount != 0) { + mLinkCount--; + if (mLinkCount == 0) { + do_unlink(); + do_unload(); + } + } else { + OSReport_Warning("%08x DynamicModuleControlBase::unlink() mLinkCount id already zero.\n", + this); + } + return true; +} + +BOOL DynamicModuleControlBase::load_async() { + if (mLinkCount == 0) { + return do_load_async(); + } + return true; +} + +bool DynamicModuleControlBase::force_unlink() { + if (mLinkCount != 0) { + mLinkCount = 0; + do_unlink(); + } + return true; +} + +void DynamicModuleControlBase::dump() { + u16 doLinkCount; + u16 linkCount; + DynamicModuleControlBase* current = getFirstClass(); + size_t totalSize = 0; + JUTReportConsole_f("\nDynamicModuleControlBase::dump()\n"); + JUTReportConsole_f("Do Ln Size Name\n"); + while (current != NULL) { + doLinkCount = current->mDoLinkCount; + linkCount = current->mLinkCount; + if (doLinkCount != 0 || linkCount != 0) { + u32 size = current->getModuleSize(); + const char* name = current->getModuleName(); + if (size < 0xFFFFFFFF) { + name = (name != NULL) ? name : "(Null)"; + const char* type = current->getModuleTypeString(); + JUTReportConsole_f("%3d%3d%5.1f %05x %-4s %s\n", doLinkCount, linkCount, + size / 1024.0f, size, type, name); + totalSize = totalSize + size; + } else { + name = (name != NULL) ? name : "(Null)"; + const char* type = current->getModuleTypeString(); + JUTReportConsole_f("%3d%3d ???? ????? %-4s %s\n", doLinkCount, linkCount, type, + name); + } + current->dump2(); + } + current = current->getNextClass(); + } + JUTReportConsole_f("TotalSize %6.2f %06x\n\n", totalSize / 1024.0f, totalSize); +} + +DynamicModuleControl::DynamicModuleControl(char const* name) { + mModule = NULL; + mBss = NULL; + unk_24 = 0; + mName = name; + mResourceType = 0; + unk_33 = 0; + mChecksum = 0; + mSize = 0; + mAsyncLoadCallback = NULL; +} + +u32 DynamicModuleControl::sAllocBytes; +JKRArchive* DynamicModuleControl::sArchive; +JKRFileCache* DynamicModuleControl::sFileCache; + +static const char* baseString = "Base"; +static const char* unusedString = ",ダイナミックリンクプログラム名,サイズ\n"; +static const char* unusedString2 = ",%s,%d,\n"; +static const char* unusedString3 = "\n"; + +JKRArchive* DynamicModuleControl::mountCallback(void* param_0) { + JKRExpHeap* heap = mDoExt_getArchiveHeap(); + sFileCache = JKRFileCache::mount("/rels", heap, NULL); + sArchive = JKRArchive::mount("RELS.arc", JKRArchive::MOUNT_COMP, heap, + JKRArchive::MOUNT_DIRECTION_HEAD); + if (sArchive == NULL) { + // "Mount failure, but if the archive isn't created, it was too slow %s\n" + OSReport_Error("マウント失敗ですが単にアーカイブを作ってないだけなら遅いだけです %s\n", + "RELS.arc"); + } + return sArchive; +} + +bool DynamicModuleControl::initialize() { + sFileCache = NULL; + sAllocBytes = 0; + sArchive = NULL; + mountCallback(NULL); + return true; +} + +bool DynamicModuleControl::callback(void* moduleControlPtr) { + DynamicModuleControl* moduleControl = (DynamicModuleControl*)moduleControlPtr; + return moduleControl->do_load(); +} + +static u32 calcSum2(u16 const* data, u32 size) { + u32 sum = 0; + while (size > 0) { + sum = sum + *data; + size = size - 2; + data++; + } + return sum; +} + +bool DynamicModuleControl::do_load() { + if (mModule != NULL) { + return true; + } + s32 i = 0; + while (true) { + if (mModule != NULL) { + i_JKRFree(mModule); + mModule = NULL; + } + char buffer[64]; + snprintf(buffer, 64, "%s.rel", mName); + if (mModule == NULL && sArchive != NULL) { + if (mModule == NULL) { + mModule = (OSModuleInfo*)JKRGetResource('MMEM', buffer, sArchive); + if (mModule != NULL) { + mResourceType = 1; + } + } + if (mModule == NULL) { + mModule = (OSModuleInfo*)JKRGetResource('AMEM', buffer, sArchive); + if (mModule != NULL) { + mResourceType = 2; + } + } + if (mModule == NULL) { + mModule = (OSModuleInfo*)JKRGetResource('DMEM', buffer, sArchive); + if (mModule != NULL) { + mResourceType = 3; + } + } + } + if (mModule != NULL) { + mSize = sArchive->getExpandedResSize(mModule); + JKRDetachResource(mModule, NULL); + } else { + if (mModule == NULL) { + snprintf(buffer, 64, "/rels/%s.rel", mName); + mModule = (OSModuleInfo*)JKRDvdToMainRam( + buffer, NULL, EXPAND_SWITCH_UNKNOWN1, NULL, archiveHeap, + JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0, NULL); + if (mModule != NULL) { + mSize = 0; + mResourceType = 7; + } + } + if (mModule == NULL && sFileCache != NULL) { + mModule = (OSModuleInfo*)sFileCache->getResource('rels', buffer); + if (mModule != NULL) { + mSize = 0; + mResourceType = 11; + JKRDetachResource(mModule, NULL); + } + } + } + if (mModule == NULL) { + // "DynamicModuleControl::do_load() Resource loading failure [%s]\n" + OSReport_Error("DynamicModuleControl::do_load() リソース読み込み失敗 [%s]\n", mName); + return false; + } + if (mSize > 0) { + u32 sum = calcSum2((u16*)mModule, mSize); + if (unk_33 == 0) { + mChecksum = sum; + unk_33++; + } else { + u32 newsum = sum & 0xFFFF; + if (newsum != mChecksum) { + OSReport_Error( + // "DynamicModuleControl::do_load() Checksum Error %04x %04x[%s]\n" + "DynamicModuleControl::do_load() チェックサムエラー %04x %04x[%s]\n", + newsum, mChecksum, mName); + unk_33 = 0; + i++; + if (i >= 3) { + return false; + } + } else { + if (unk_33 < 0xFF) { + unk_33++; + } + break; + } + } + } else { + if (unk_33 < 0xFF) { + unk_33++; + } + break; + } + } + return true; +} + +BOOL DynamicModuleControl::do_load_async() { + if (mAsyncLoadCallback == NULL) { + if (mModule != NULL) { + return true; + } + mAsyncLoadCallback = mDoDvdThd_callback_c::create( + (mDoDvdThd_callback_func)DynamicModuleControl::callback, this); + if (mAsyncLoadCallback == NULL) { + OSReport_Error( + // "DynamicModuleControl::do_load_async() async load callback entry failure [%s]\n" + "DynamicModuleControl::do_load_async() 非同期読み込みコールバック登録失敗 [%s]\n", + mName); + } + } + if (mAsyncLoadCallback != NULL && mAsyncLoadCallback->sync()) { + mAsyncLoadCallback->destroy(); + mAsyncLoadCallback = NULL; + return true; + } else { + return false; + } +} + +bool DynamicModuleControl::do_unload() { + if (mModule != NULL) { + i_JKRFree(mModule); + mModule = NULL; + } + return true; +} + +void DynamicModuleControl::dump2() { + if (mModule != NULL) { + OSSectionInfo* section = (OSSectionInfo*)mModule->info.sectionInfoOffset; + OSReport("mModule=%08x %08x %08x %08x %08x\n", mModule, section[1].mOffset & ~1, + section[1].mSize, mModule->mImportTableOffset - mModule->mRelocationTableOffset, + mModule->mImportTableSize); + } +} + +BOOL DynamicModuleControl::do_link() { + OSGetTime(); + if (mModule == NULL) { + do_load(); + } + if (mModule != NULL) { + JUT_ASSERT(__FILE__, 613, mModule->info.sectionInfoOffset < 0x80000000); + JUT_ASSERT(__FILE__, 615, (u32)mModule + mModule->fixSize < 0x82000000); + OSGetTime(); + OSGetTime(); + if (mModule->mModuleVersion >= 3) { + u32 fixSizePtr; + u32 fixSize = mModule->fixSize; + u32 fixSize2 = (fixSize + 0x1f) & ~0x1f; + fixSizePtr = (u32)mModule + fixSize2; + s32 size = JKRGetMemBlockSize(NULL, mModule); + if (size < 0) { + void* bss = JKRAlloc(mModule->mBssSize, 0x20); + if (bss == NULL) { + // "BSS Memory allocation failed\n" + OSReport_Error("BSSメモリ確保失敗\n", bss); + goto error; + } + mBss = bss; + BOOL linkResult = OSLink(mModule); + if (linkResult == FALSE) { + // "link failed\n" + OSReport_Error("リンク失敗\n"); + goto error; + } + } else { + if (fixSize2 + mModule->mBssSize < size) { + BOOL linkResult = OSLinkFixed(mModule, fixSizePtr); + if (linkResult == FALSE) { + // "link failed\n" + OSReport_Error("リンク失敗\n"); + goto error; + } + s32 result = JKRResizeMemBlock(NULL, mModule, fixSize2 + mModule->mBssSize); + if (result < 0) { + // "Module size (resize) failed\n" + OSReport_Error("モジュールリサイズ(縮小)失敗\n"); + } + } else { + s32 result = JKRResizeMemBlock(NULL, mModule, fixSize2 + mModule->mBssSize); + if (result > 0) { + BOOL linkResult = OSLinkFixed(mModule, fixSizePtr); + if (linkResult == FALSE) { + // "link failed\n" + OSReport_Error("リンク失敗\n"); + goto error; + } + } else { + void* bss = JKRAlloc(mModule->mBssSize, 0x20); + if (bss == NULL) { + // "BSS Memory allocation failure [%x]\n" + OSReport_Error("BSSメモリ確保失敗 [%x]\n", mModule->mBssSize); + goto error; + } + mBss = bss; + BOOL linkResult = OSLinkFixed(mModule, (u32)bss); + if (linkResult == FALSE) { + // "link failed\n" + OSReport_Error("リンク失敗\n"); + goto error; + } + s32 result = JKRResizeMemBlock(NULL, mModule, fixSize); + if (result < 0) { + // "Module size (resize) failed\n" + OSReport_Error("モジュールリサイズ(縮小)失敗\n"); + } + } + } + } + } else { + JUT_ASSERT(__FILE__, 724, 0); + } + OSGetTime(); + sAllocBytes = sAllocBytes + getModuleSize(); + OSGetTime(); + unk_24 = ((u32(*)())mModule->prolog)(); + OSGetTime(); + return TRUE; + } + +error: + unk_33 = 0; + if (mBss != NULL) { + JKRHeap::free(mBss, NULL); + mBss = NULL; + } + if (mModule != NULL) { + JKRHeap::free(mModule, NULL); + mModule = NULL; + } + return FALSE; +} + +bool DynamicModuleControl::do_unlink() { + OSTime time1 = OSGetTime(); + ((void (*)())mModule->epilog)(); + OSTime time2 = OSGetTime(); + BOOL unklink = OSUnlink(mModule); + OSTime time3 = OSGetTime(); + if (unklink == FALSE) { + // "Unlink failed mModule=%08x mBss=%08x\n" + OSReport_Error("アンリンク失敗 mModule=%08x mBss=%08x\n", mModule, mBss); + return false; + } + sAllocBytes = sAllocBytes - getModuleSize(); + if (mBss != NULL) { + i_JKRFree(mBss); + mBss = NULL; + } + do_unload(); + return true; +} + +int DynamicModuleControl::getModuleSize() const { + if (mModule != NULL) { + u32 size = JKRGetMemBlockSize(NULL, mModule); + if (mBss != NULL) { + JKRGetMemBlockSize(NULL, mBss); + } + return size + mModule->mBssSize; + } else { + return 0; + } +} + +const char* DynamicModuleControl::getModuleTypeString() const { + static const char* strings[4] = {"????", "MEM", "ARAM", "DVD"}; + return strings[mResourceType & 3]; +} + +void ModuleProlog() { + /* empty function */ +} + +void ModuleEpilog() { + /* empty function */ +} + +void ModuleUnresolved() { + // "\nError: Unlinked function was called.\n" + OSReport_Error("\nError: リンクされていない関数が呼び出されました.\n"); + OSReport_Error("Address: Back Chain LR Save\n"); + u32 i = 0; + u32* stackPtr = (u32*)OSGetStackPointer(); + while ((stackPtr != NULL) && ((u32)stackPtr != 0xFFFFFFFF) && (i++ < 0x10)) { + OSReport_Error("0x%08x: 0x%08x 0x%08x\n", stackPtr, *stackPtr, *(stackPtr + 1)); + stackPtr = (u32*)*stackPtr; + } + OSReport_Error("\n"); +} + +void ModuleConstructorsX(const VoidFunc* _ctors) { + JUT_ASSERT(__FILE__, 850, _ctors); + while (*_ctors != 0) { + (**_ctors)(); + _ctors++; + } +} + +void ModuleDestructorsX(const VoidFunc* _dtors) { + JUT_ASSERT(__FILE__, 864, _dtors); + while (*_dtors != 0) { + (**_dtors)(); + _dtors++; + } +} |
