summaryrefslogtreecommitdiff
path: root/src/DynamicLink.cpp
diff options
context:
space:
mode:
authorLuke Street <luke.street@encounterpc.com>2023-09-10 00:42:26 -0400
committerLuke Street <luke.street@encounterpc.com>2023-09-10 00:48:55 -0400
commitadb95b135c3d7498eba29bbd9728d345eed5a407 (patch)
tree655575b939c12067569263171b68c079b1a232c8 /src/DynamicLink.cpp
parent81ac53f1317dafb3506ae3ed8b2820d40645c3c8 (diff)
Import project
Original repository: https://github.com/encounter/ww
Diffstat (limited to 'src/DynamicLink.cpp')
-rw-r--r--src/DynamicLink.cpp510
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++;
+ }
+}