From 9843b7454769af53a8f1dc93879fa907ec1e61c3 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 12 Oct 2023 04:10:49 -0700 Subject: [PATCH] Nearly match CARAMManager Former-commit-id: e70cf7d4b3c97c15deaac6e0af4051476d301f39 --- config/GM8E01_00/symbols.txt | 10 +- config/GM8E01_01/symbols.txt | 6 +- configure.py | 3 +- include/Kyoto/CARAMManager.hpp | 51 ++++++-- src/Kyoto/CARAMManager.cpp | 209 +++++++++++++++++++++++++++++++++ tools/decompctx.py | 20 ++-- 6 files changed, 272 insertions(+), 27 deletions(-) create mode 100644 src/Kyoto/CARAMManager.cpp diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index f21df0cd..67a3daf1 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -14513,7 +14513,7 @@ FindFreeBlocks__12CARAMManagerFUiUiUi = .text:0x80344B98; // type:function size: Alloc__12CARAMManagerFUi = .text:0x80344C28; // type:function size:0x9C scope:global Shutdown__12CARAMManagerFv = .text:0x80344CC4; // type:function size:0x50 scope:global Initialize__12CARAMManagerFUi = .text:0x80344D14; // type:function size:0x170 scope:global -fn_80344E84 = .text:0x80344E84; // type:function size:0x7C +do_erase__Q24rstl67listFPQ34rstl67list4node = .text:0x80344E84; // type:function size:0x7C __sinit_CARAMManager_cpp = .text:0x80344F00; // type:function size:0x54 scope:local __dt__Q24rstl67listFv = .text:0x80344F54; // type:function size:0x78 scope:global PointInFrustumPlanes__14CFrustumPlanesCFRC9CVector3f = .text:0x80344FCC; // type:function size:0x60 scope:global @@ -17857,7 +17857,7 @@ cplext = .rodata:0x803D7CFC; // type:object size:0x7C scope:local cpdist = .rodata:0x803D7D78; // type:object size:0x78 scope:local cpdext = .rodata:0x803D7DF0; // type:object size:0x78 scope:local @stringBase0 = .rodata:0x803D7E68; // type:object size:0xE5 scope:local data:string_table -lbl_803D7F50 = .rodata:0x803D7F50; // type:object size:0x8 +@stringBase0 = .rodata:0x803D7F50; // type:object size:0x8 data:string_table lbl_803D7F58 = .rodata:0x803D7F58; // type:object size:0xF0 lbl_803D8048 = .rodata:0x803D8048; // type:object size:0x30 data:4byte lbl_803D8078 = .rodata:0x803D8078; // type:object size:0x30 @@ -19239,7 +19239,7 @@ lbl_804BFF00 = .bss:0x804BFF00; // type:object size:0x10 lbl_804BFF10 = .bss:0x804BFF10; // type:object size:0xC lbl_804BFF1C = .bss:0x804BFF1C; // type:object size:0x14 lbl_804BFF30 = .bss:0x804BFF30; // type:object size:0x10 -lbl_804BFF40 = .bss:0x804BFF40; // type:object size:0x10 +@52 = .bss:0x804BFF40; // type:object size:0x10 sPlayerPosition = .bss:0x804BFF50; // type:object size:0xC scope:local data:float sTextureProjectionTransform = .bss:0x804BFF5C; // type:object size:0x34 scope:local data:float lbl_804BFF90 = .bss:0x804BFF90; // type:object size:0x10 @@ -21307,7 +21307,7 @@ lbl_805A8911 = .sdata:0x805A8911; // type:object size:0x1 data:byte lbl_805A8912 = .sdata:0x805A8912; // type:object size:0x6 data:byte fixed_bl = .sdata:0x805A8918; // type:object size:0x4 scope:local data:4byte fixed_bd = .sdata:0x805A891C; // type:object size:0x4 scope:local data:4byte -mPreInitializeAlloc__12CARAMManager = .sdata:0x805A8920; // type:object size:0x8 scope:global data:4byte +mPreInitializeAlloc__12CARAMManager = .sdata:0x805A8920; // type:object size:0x4 scope:global data:4byte lbl_805A8928 = .sdata:0x805A8928; // type:object size:0x4 data:4byte lbl_805A892C = .sdata:0x805A892C; // type:object size:0x4 data:float lbl_805A8930 = .sdata:0x805A8930; // type:object size:0x4 data:float @@ -21992,7 +21992,7 @@ mChunkSize__12CARAMManager = .sbss:0x805A9528; // type:object size:0x4 scope:glo mNumChunks__12CARAMManager = .sbss:0x805A952C; // type:object size:0x4 scope:global data:4byte mpBookKeepingMemory__12CARAMManager = .sbss:0x805A9530; // type:object size:0x4 scope:global data:4byte mDMAUniqueID__12CARAMManager = .sbss:0x805A9534; // type:object size:0x4 scope:global data:4byte -mChunksAllocated__12CARAMManager = .sbss:0x805A9538; // type:object size:0x8 scope:global data:4byte +mChunksAllocated__12CARAMManager = .sbss:0x805A9538; // type:object size:0x4 scope:global data:4byte sMaterialCachedState = .sbss:0x805A9540; // type:object size:0x4 scope:global data:4byte sLastModelCached__13CCubeMaterial = .sbss:0x805A9544; // type:object size:0x4 scope:global data:4byte sRenderingModel__13CCubeMaterial = .sbss:0x805A9548; // type:object size:0x4 scope:global data:4byte diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index f3e71a3b..7a8cd5f9 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -14528,7 +14528,7 @@ FindFreeBlocks__12CARAMManagerFUiUiUi = .text:0x80344C78; // type:function size: Alloc__12CARAMManagerFUi = .text:0x80344D08; // type:function size:0x9C scope:global Shutdown__12CARAMManagerFv = .text:0x80344DA4; // type:function size:0x50 scope:global Initialize__12CARAMManagerFUi = .text:0x80344DF4; // type:function size:0x170 scope:global -fn_80344E84__Fv = .text:0x80344F64; // type:function size:0x7C scope:global +do_erase__Q24rstl67listFPQ34rstl67list4node__Fv = .text:0x80344F64; // type:function size:0x7C scope:global __sinit_CARAMManager_cpp = .text:0x80344FE0; // type:function size:0x54 scope:global __dt__Q24rstl67listFv = .text:0x80345034; // type:function size:0x78 scope:global PointInFrustumPlanes__14CFrustumPlanesCFRC9CVector3f = .text:0x803450AC; // type:function size:0x60 scope:global @@ -17911,7 +17911,7 @@ cplext = .rodata:0x803D7EDC; // type:object size:0x7C scope:local cpdist = .rodata:0x803D7F58; // type:object size:0x78 scope:local cpdext = .rodata:0x803D7FD0; // type:object size:0x78 scope:local @stringBase0 = .rodata:0x803D8048; // type:object size:0xE5 scope:local data:string_table -lbl_803D7F50 = .rodata:0x803D8130; // type:object size:0x8 scope:global +@stringBase0 = .rodata:0x803D8130; // type:object size:0x8 scope:global lbl_803D7F58 = .rodata:0x803D8138; // type:object size:0xF0 scope:global lbl_803D8048 = .rodata:0x803D8228; // type:object size:0x30 scope:global data:4byte lbl_803D8078 = .rodata:0x803D8258; // type:object size:0x30 scope:global @@ -19268,7 +19268,7 @@ lbl_804BFF00 = .bss:0x804C00E0; // type:object size:0x10 scope:local lbl_804BFF10 = .bss:0x804C00F0; // type:object size:0xC scope:local lbl_804BFF1C = .bss:0x804C00FC; // type:object size:0x14 scope:local lbl_804BFF30 = .bss:0x804C0110; // type:object size:0x10 scope:local -lbl_804BFF40 = .bss:0x804C0120; // type:object size:0x10 scope:local +@52 = .bss:0x804C0120; // type:object size:0x10 scope:local sPlayerPosition = .bss:0x804C0130; // type:object size:0xC scope:local data:float sTextureProjectionTransform = .bss:0x804C013C; // type:object size:0x34 scope:local data:float lbl_804BFF90 = .bss:0x804C0170; // type:object size:0x10 scope:local diff --git a/configure.py b/configure.py index 4dbbc02d..32a79fd7 100755 --- a/configure.py +++ b/configure.py @@ -137,7 +137,8 @@ config.ldflags = [ "-fp hardware", "-nodefaults", ] -config.progress_all = False +config.progress_all = True +config.build_rels = False # Base flags, common to most GC/Wii games. # Generally leave untouched, with overrides added below. diff --git a/include/Kyoto/CARAMManager.hpp b/include/Kyoto/CARAMManager.hpp index 65857868..468f307c 100644 --- a/include/Kyoto/CARAMManager.hpp +++ b/include/Kyoto/CARAMManager.hpp @@ -3,6 +3,10 @@ #include "types.h" +#include + +#include + class CARAMManager { public: enum EDMAPriority { @@ -15,22 +19,49 @@ public: kDMAPrio_Six, }; + static bool Initialize(uint); static void Shutdown(); - static void CollectGarbage(); - static void PreInitializeAlloc(uint size) { mPreInitializeAlloc += size; } - static void Initialize(uint); + static void* Alloc(uint len); + static uint FindFreeBlocks(uint, uint, uint); + static bool Free(const void* ptr); + static uint DMAToARAM(void*, void*, uint, EDMAPriority); + static int DMAToMRAM(void*, void*, uint, EDMAPriority); + static bool IsDMACompleted(uint handle); + static void WaitForDMACompletion(uint handle); static void WaitForAllDMAsToComplete(); + static bool CancelDMA(uint); + static void AramManagerDMACallback(u32 result); + static void RefreshActiveDMAList(); + static void CollectGarbage(); + + static void PreInitializeAlloc(uint size) { mPreInitializeAlloc += size; } static const void* GetInvalidAlloc() { return (const void*)kInvalidAlloc; } static const uint GetInvalidDMAHandle() { return kInvalidHandle; } - static bool CancelDMA(uint); - static void WaitForDMACompletion(uint); - static bool IsDMACompleted(uint handle); - static void* Alloc(uint len); - static void Free(const void* ptr); - static int DMAToARAM(void*, void*, uint, EDMAPriority); - static int DMAToMRAM(void*, void*, uint, EDMAPriority); + static uint GetAndIncrementUniqueID() { + mDMAUniqueID++; + if (mDMAUniqueID == GetInvalidDMAHandle()) { + mDMAUniqueID++; + } + return mDMAUniqueID; + } + private: + struct SAramDMARequest { + ARQRequest mRequest; + uint mUniqueID; + bool mComplete; + + }; + + static bool mbInitialized; + static u32 mpARAMStart; + static uint mChunkSize; + static uint mNumChunks; + static uint* mpBookKeepingMemory; static uint mPreInitializeAlloc; + static uint mDMAUniqueID; + static uint mChunksAllocated; + static rstl::list< SAramDMARequest* > mActiveDMAs; static const int kInvalidAlloc; static const int kInvalidHandle; }; diff --git a/src/Kyoto/CARAMManager.cpp b/src/Kyoto/CARAMManager.cpp new file mode 100644 index 00000000..9f4d82f1 --- /dev/null +++ b/src/Kyoto/CARAMManager.cpp @@ -0,0 +1,209 @@ +#include "Kyoto/CARAMManager.hpp" + +#include +#include + +bool CARAMManager::mbInitialized = false; +u32 CARAMManager::mpARAMStart = 0; +uint CARAMManager::mChunkSize = 0; +uint CARAMManager::mNumChunks = 0; +uint* CARAMManager::mpBookKeepingMemory; +uint CARAMManager::mPreInitializeAlloc = 16 * 1024; +uint CARAMManager::mDMAUniqueID; +uint CARAMManager::mChunksAllocated; +const int CARAMManager::kInvalidAlloc = -1; +const int CARAMManager::kInvalidHandle = -1; + +rstl::list< CARAMManager::SAramDMARequest* > CARAMManager::mActiveDMAs; + +bool CARAMManager::Initialize(uint chunkSize) { + uint numChunks = (ARGetSize() - mPreInitializeAlloc) / chunkSize; + mChunkSize = chunkSize; + mNumChunks = numChunks; + mpARAMStart = ARAlloc(chunkSize * numChunks); + mpBookKeepingMemory = (uint*)CMemory::Alloc(numChunks * 4, IAllocator::kHI_None, + IAllocator::kSC_Unk1, IAllocator::kTP_Heap, + CCallStack(-1, "??(??)", CCallStack::kUnknownType)); + CMemory::OffsetFakeStatics(mNumChunks * 4); + + for (uint i = 0; i < numChunks; ++i) { + mpBookKeepingMemory[i] = 0; + } + + mDMAUniqueID = 0; + mbInitialized = true; + return true; +} + +void CARAMManager::Shutdown() { + WaitForAllDMAsToComplete(); + CMemory::Free(mpBookKeepingMemory); + u32 unk = 0; + CMemory::OffsetFakeStatics(-mNumChunks * 4); + ARFree(&unk); + mbInitialized = false; +} + +void* CARAMManager::Alloc(const uint len) { + uint chunkCount = (mChunkSize - 1 + len) / mChunkSize; + uint block = FindFreeBlocks(0, mNumChunks, chunkCount); + + if (block == -1) { + return (void*)-1; + } + + mChunksAllocated += chunkCount; + uint blockOffset = mpARAMStart + block * mChunkSize; + mpBookKeepingMemory[block] = chunkCount; + + while (--chunkCount != 0) { + ++block; + mpBookKeepingMemory[block] = -1; + } + + return (void*)blockOffset; +} + +uint CARAMManager::FindFreeBlocks(uint arg0, uint arg1, uint arg2) { + while (arg0 < arg1) { + if (mpBookKeepingMemory[arg0] == 0) { + if (arg2 == 1) { + return arg0; + } + + ++arg0; + int r8 = 1; + while (arg0 < arg1) { + uint tmp = mpBookKeepingMemory[arg0]; + if (tmp != 0) { + arg0 += tmp; + break; + } + + r8++; + if (r8 == arg2) { + return arg0 - (arg2 - 1); + } + ++arg0; + } + } else { + arg0 += mpBookKeepingMemory[arg0]; + } + } + return -1; +} + +bool CARAMManager::Free(const void* ptr) { + if (GetInvalidAlloc() == ptr) { + return false; + } + + uint blockStart = ((u32)ptr - mpARAMStart) / mChunkSize; + uint blockCount = mpBookKeepingMemory[blockStart]; + mChunksAllocated -= blockCount; + while (blockCount--) { + mpBookKeepingMemory[blockStart++] = 0; + } + return true; +} + +uint CARAMManager::DMAToARAM(void* src, void* dest, uint len, EDMAPriority priority) { + DCStoreRange(src, len); + SAramDMARequest* req = new SAramDMARequest(); + req->mComplete = false; + req->mUniqueID = mDMAUniqueID; + mActiveDMAs.push_back(req); + ARQPostRequest(&req->mRequest, req->mUniqueID, ARQ_TYPE_MRAM_TO_ARAM, + (priority == kDMAPrio_One) ? ARQ_PRIORITY_HIGH : ARQ_PRIORITY_LOW, (u32)src, + (u32)dest, len, AramManagerDMACallback); + + GetAndIncrementUniqueID(); + return req->mUniqueID; +} + +int CARAMManager::DMAToMRAM(void* src, void* dest, uint len, EDMAPriority priority) { + DCInvalidateRange(dest, len); + SAramDMARequest* req = new SAramDMARequest(); + req->mComplete = false; + req->mUniqueID = mDMAUniqueID; + mActiveDMAs.push_back(req); + ARQPostRequest(&req->mRequest, req->mUniqueID, ARQ_TYPE_ARAM_TO_MRAM, + (priority == kDMAPrio_One) ? ARQ_PRIORITY_HIGH : ARQ_PRIORITY_LOW, (u32)src, + (u32)dest, len, AramManagerDMACallback); + + GetAndIncrementUniqueID(); + return req->mUniqueID; +} + +bool CARAMManager::IsDMACompleted(uint handle) { + rstl::list< SAramDMARequest* >::iterator it = mActiveDMAs.begin(); + for (; it != mActiveDMAs.end(); ++it) { + uint uniqueId = (*it)->mUniqueID; + if (uniqueId == handle) { + if ((*it)->mComplete) { + delete (*it); + mActiveDMAs.erase(it); + return true; + } + return false; + } + } + + return true; +} + +void CARAMManager::WaitForDMACompletion(uint handle) { + rstl::list< SAramDMARequest* >::iterator it = mActiveDMAs.begin(); + for (; it != mActiveDMAs.end(); ++it) { + uint uniqueId = (*it)->mUniqueID; + if (uniqueId == handle) { + // Spin until complete! + while (!(*it)->mComplete) + ; + delete (*it); + mActiveDMAs.erase(it); + return; + } + } +} + +void CARAMManager::WaitForAllDMAsToComplete() { + while ((int)mActiveDMAs.size() > 0) { + RefreshActiveDMAList(); + } +} + +bool CARAMManager::CancelDMA(uint handle) { + rstl::list< SAramDMARequest* >::iterator it = mActiveDMAs.begin(); + for (; it != mActiveDMAs.end(); ++it) { + uint uniqueId = (*it)->mUniqueID; + if (uniqueId == handle) { + return (*it)->mComplete != false; + } + } + return true; +} + +void CARAMManager::AramManagerDMACallback(u32 result) { + SAramDMARequest* req = reinterpret_cast< SAramDMARequest* >(result); + req->mComplete = true; + if (req->mRequest.type == ARQ_TYPE_ARAM_TO_MRAM) { + DCInvalidateRange(reinterpret_cast< void* >(req->mRequest.dest), req->mRequest.length); + } +} + +void CARAMManager::RefreshActiveDMAList() { + rstl::list< SAramDMARequest* >::iterator it = mActiveDMAs.begin(); + while (it != mActiveDMAs.end()) { + if ((*it)->mComplete) { + delete (*it); + it = mActiveDMAs.erase(it); + continue; + } + ++it; + } +} + +void CARAMManager::CollectGarbage() { + RefreshActiveDMAList(); +} diff --git a/tools/decompctx.py b/tools/decompctx.py index c42b1828..28d3cbad 100644 --- a/tools/decompctx.py +++ b/tools/decompctx.py @@ -17,7 +17,10 @@ import re script_dir = os.path.dirname(os.path.realpath(__file__)) root_dir = os.path.abspath(os.path.join(script_dir, "..")) src_dir = os.path.join(root_dir, "src") -include_dir = os.path.join(root_dir, "include") +include_dirs = [ + os.path.join(root_dir, "include"), + os.path.join(root_dir, "libc"), +] include_pattern = re.compile(r'^#include\s*[<"](.+?)[>"]$') guard_pattern = re.compile(r'^#ifndef\s+(.*)$') @@ -26,14 +29,15 @@ defines = set() def import_h_file(in_file: str, r_path: str) -> str: rel_path = os.path.join(root_dir, r_path, in_file) - inc_path = os.path.join(include_dir, in_file) if os.path.exists(rel_path): - return import_c_file(rel_path) - elif os.path.exists(inc_path): - return import_c_file(inc_path) + return import_c_file(rel_path) + for include_dir in include_dirs: + inc_path = os.path.join(include_dir, in_file) + if os.path.exists(inc_path): + return import_c_file(inc_path) else: - print("Failed to locate", in_file) - exit(1) + print("Failed to locate", in_file) + return "" def import_c_file(in_file) -> str: in_file = os.path.relpath(in_file, root_dir) @@ -84,4 +88,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main()