diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 8428ae57..d9385aba 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -107,6 +107,7 @@ d/d_player.cpp: d/d_rawarchive.cpp: .text start:0x80061B10 end:0x800629D0 + .data start:0x8050DDD8 end:0x8050DDF8 d/d_scene.cpp: .text start:0x800629D0 end:0x80062E40 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 0570fe6b..d978003d 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -2741,35 +2741,35 @@ fn_80061AB0 = .text:0x80061AB0; // type:function size:0x5C fn_80061B10 = .text:0x80061B10; // type:function size:0x88 fn_80061BA0 = .text:0x80061BA0; // type:function size:0x34 fn_80061BE0 = .text:0x80061BE0; // type:function size:0x10 -fn_80061BF0 = .text:0x80061BF0; // type:function size:0x28 -fn_80061C20 = .text:0x80061C20; // type:function size:0x80 -fn_80061CA0 = .text:0x80061CA0; // type:function size:0xA0 -fn_80061D40 = .text:0x80061D40; // type:function size:0x8 -fn_80061D50 = .text:0x80061D50; // type:function size:0x8 -fn_80061D60 = .text:0x80061D60; // type:function size:0x104 -fn_80061E70 = .text:0x80061E70; // type:function size:0x74 -fn_80061EF0 = .text:0x80061EF0; // type:function size:0xD0 -fn_80061FC0 = .text:0x80061FC0; // type:function size:0x34 -fn_80062000 = .text:0x80062000; // type:function size:0x9C -fn_800620A0 = .text:0x800620A0; // type:function size:0x104 -fn_800621B0 = .text:0x800621B0; // type:function size:0x14C -fn_80062300 = .text:0x80062300; // type:function size:0x5C -fn_80062360 = .text:0x80062360; // type:function size:0x14 -fn_80062380 = .text:0x80062380; // type:function size:0x74 -fn_80062400 = .text:0x80062400; // type:function size:0x90 -fn_80062490 = .text:0x80062490; // type:function size:0xAC -fn_80062540 = .text:0x80062540; // type:function size:0xB0 -fn_800625F0 = .text:0x800625F0; // type:function size:0x44 -fn_80062640 = .text:0x80062640; // type:function size:0x44 -fn_80062690 = .text:0x80062690; // type:function size:0x2C -fn_800626C0 = .text:0x800626C0; // type:function size:0x5C -fn_80062720 = .text:0x80062720; // type:function size:0x60 -fn_80062780 = .text:0x80062780; // type:function size:0x80 -fn_80062800 = .text:0x80062800; // type:function size:0x34 -fn_80062840 = .text:0x80062840; // type:function size:0x80 -fn_800628C0 = .text:0x800628C0; // type:function size:0x90 -fn_80062950 = .text:0x80062950; // type:function size:0x34 -fn_80062990 = .text:0x80062990; // type:function size:0x40 +__ct__14dRawArcEntry_cFv = .text:0x80061BF0; // type:function size:0x28 +__dt__14dRawArcEntry_cFv = .text:0x80061C20; // type:function size:0x80 +searchCallback__14dRawArcEntry_cFPvPvPC11ARCDirEntryPCcb = .text:0x80061CA0; // type:function size:0xA0 +searchCallback1__14dRawArcEntry_cFPvPvPC11ARCDirEntryPCc = .text:0x80061D40; // type:function size:0x8 +searchCallback2__14dRawArcEntry_cFPvPvPC11ARCDirEntryPCc = .text:0x80061D50; // type:function size:0x8 +destroy__14dRawArcEntry_cFPv = .text:0x80061D60; // type:function size:0x104 +loadArcFromDiskChecked__14dRawArcEntry_cFPCcPCcUcPQ23EGG4Heap = .text:0x80061E70; // type:function size:0x74 +loadArcFromDisk__14dRawArcEntry_cFPCcPCcUcPQ23EGG4Heap = .text:0x80061EF0; // type:function size:0xD0 +checkArcExistsOnDisk__14dRawArcEntry_cFPCcPCc = .text:0x80061FC0; // type:function size:0x34 +checkArcExistsOnDiskInner__14dRawArcEntry_cFPcPCcPCc = .text:0x80062000; // type:function size:0x9C +mount__14dRawArcEntry_cFPCcPvPvUcPQ23EGG4Heap = .text:0x800620A0; // type:function size:0x104 +ensureLoadedMaybe__14dRawArcEntry_cFPv = .text:0x800621B0; // type:function size:0x14C +onMount__14dRawArcEntry_cFPv = .text:0x80062300; // type:function size:0x5C +__ct__14dRawArcTable_cFv = .text:0x80062360; // type:function size:0x14 +__dt__14dRawArcTable_cFv = .text:0x80062380; // type:function size:0x74 +init__14dRawArcTable_cFUsPvPQ23EGG4Heap = .text:0x80062400; // type:function size:0x90 +getArcOrLoadFromDisk__14dRawArcTable_cFPCcPCcUcPQ23EGG4Heap = .text:0x80062490; // type:function size:0xAC +addEntryFromSuperArc__14dRawArcTable_cFPCcPvUcPQ23EGG4Heap = .text:0x80062540; // type:function size:0xB0 +ensureLoadedMaybe2__14dRawArcTable_cFPCc = .text:0x800625F0; // type:function size:0x44 +ensureLoadedMaybe__14dRawArcTable_cFPCc = .text:0x80062640; // type:function size:0x44 +hasEntry__14dRawArcTable_cFPCc = .text:0x80062690; // type:function size:0x2C +decreaseRefCount__14dRawArcTable_cFPCc = .text:0x800626C0; // type:function size:0x5C +getDataFromOarc__14dRawArcTable_cFPCcPCc = .text:0x80062720; // type:function size:0x60 +getSubEntryData__14dRawArcTable_cFPCcPCc = .text:0x80062780; // type:function size:0x80 +getLoadedArcData__14dRawArcTable_cFPCc = .text:0x80062800; // type:function size:0x34 +ensureAllEntriesLoaded__14dRawArcTable_cFv = .text:0x80062840; // type:function size:0x80 +findEntry__14dRawArcTable_cCFPCc = .text:0x800628C0; // type:function size:0x90 +findEmptySlot__14dRawArcTable_cFv = .text:0x80062950; // type:function size:0x34 +findLoadedEntry__14dRawArcTable_cFPCc = .text:0x80062990; // type:function size:0x40 fn_800629D0 = .text:0x800629D0; // type:function size:0x60 fn_80062A30 = .text:0x80062A30; // type:function size:0x50 fn_80062A80 = .text:0x80062A80; // type:function size:0x58 @@ -26141,7 +26141,7 @@ getFileFast__Q23EGG7ArchiveFlPQ23EGG4Heapl = .text:0x80493DC0; // type:function countFileCallbackFunc__3EGGFPvPvUlPC11ARCDirEntryPCc = .text:0x80493F10; // type:function size:0x18 countFile__Q23EGG7ArchiveFv = .text:0x80493F30; // type:function size:0x38 searchInsideWithPath__3EGGFPQ23EGG7ArchiveP9ARCHandlePFPvPvUlPC11ARCDirEntryPCc_vPvPcUl = .text:0x80493F70; // type:function size:0x144 -searchInside__Q23EGG7ArchiveFPFPvPvUlPC11ARCDirEntryPCc_vPv = .text:0x804940C0; // type:function size:0x74 +searchInside__Q23EGG7ArchiveFPFPvPvPC11ARCDirEntryPCc_vPv = .text:0x804940C0; // type:function size:0x74 loadFromDisc__EGG__Archive = .text:0x80494140; // type:function size:0x114 initialize__Q23EGG7DvdFileFv = .text:0x80494260; // type:function size:0x40 __ct__Q23EGG7DvdFileFv = .text:0x804942A0; // type:function size:0x44 @@ -27385,11 +27385,11 @@ strlen = .text:0x804C64DC; // type:function size:0x1C scope:weak __va_arg = .text:0x804C64F8; // type:function size:0xC8 scope:global __register_global_object = .text:0x804C65C0; // type:function size:0x18 scope:global __destroy_global_chain = .text:0x804C65D8; // type:function size:0x48 scope:global -fn_804C6620 = .text:0x804C6620; // type:function size:0x104 +__construct_new_array = .text:0x804C6620; // type:function size:0x104 fn_804C6724 = .text:0x804C6724; // type:function size:0xBC __construct_array = .text:0x804C67E0; // type:function size:0xF8 __destroy_arr = .text:0x804C68D8; // type:function size:0x78 -fn_804C6950 = .text:0x804C6950; // type:function size:0x80 +__destroy_new_array = .text:0x804C6950; // type:function size:0x80 __ptmf_test = .text:0x804C69D0; // type:function size:0x30 fn_804C6A00 = .text:0x804C6A00; // type:function size:0x3C __ptmf_scall = .text:0x804C6A3C; // type:function size:0x28 diff --git a/configure.py b/configure.py index 7782d9dd..7abf0df5 100644 --- a/configure.py +++ b/configure.py @@ -287,6 +287,7 @@ config.libs = [ Object(NonMatching, "d/d_dvd_unk.cpp"), Object(NonMatching, "d/d_dylink.cpp"), Object(NonMatching, "d/d_heap.cpp"), + Object(NonMatching, "d/d_rawarchive.cpp"), Object(NonMatching, "d/d_stage.cpp"), Object(NonMatching, "d/d_sys.cpp"), Object(NonMatching, "d/a/d_a_base.cpp"), diff --git a/include/d/d_rawarchive.h b/include/d/d_rawarchive.h new file mode 100644 index 00000000..7432f3f3 --- /dev/null +++ b/include/d/d_rawarchive.h @@ -0,0 +1,104 @@ +#ifndef D_RAWARCHIVE_H +#define D_RAWARCHIVE_H + +#include +#include + +// TODO: loading status could be an enum (-2/-1/0/+1) + +// Ghidra: ArcManagerEntry +// size: 0x40 +class dRawArcEntry_c { +public: + dRawArcEntry_c(); + ~dRawArcEntry_c(); + + bool destroy(void *arg); + bool loadArcFromDiskChecked(const char *fileName, const char *dirName, u8 mountDirection, EGG::Heap *heap); + bool loadArcFromDisk(const char *fileName, const char *dirName, u8 mountDirection, EGG::Heap *heap); + static bool checkArcExistsOnDisk(const char *fileName, const char *dirName); + static bool checkArcExistsOnDiskInner(char *outBuf, const char *fileName, const char *dirName); + + int mount(const char *name, void *data, void *callbackArg, u8 mountDirection, EGG::Heap *heap); + int onMount(void *callbackArg); + + int ensureLoadedMaybe(void *callbackArg); + + inline bool isReferenced() { + return mRefCount != 0; + } + + inline const char *name() { + return mArcName; + } + + inline bool isNotLoaded() { + return mpArc == nullptr; + } + + inline bool isLoading() { + return mpDvdReq != nullptr; + } + + inline void increaseRefCount() { + mRefCount++; + } + + inline void decreaseRefCount() { + mRefCount--; + } + + inline void *getData() { + return mpData; + } + + inline EGG::Archive *getArc() { + return mpArc; + } + +private: + static void searchCallback(void *, void *, const ARCDirEntry *, const char *, bool); + static void searchCallback1(void *, void *, const ARCDirEntry *, const char *); + static void searchCallback2(void *, void *, const ARCDirEntry *, const char *); + +private: + /* 0x00 */ char mArcName[0x20]; + /* 0x20 */ u16 mRefCount; + /* 0x24 */ mDvd_mountMemArchive_c *mpDvdReq; + /* 0x28 */ EGG::Archive *mpArc; + /* 0x2C */ EGG::Heap *mpCommandHeap; + /* 0x30 */ void *mpData; + /* 0x34 */ u32 mAmountRead; + /* 0x38 */ u32 mChecksum; + /* 0x3C */ EGG::FrmHeap *mpFrmHeap; +}; + +// Ghidra: ArcManagerEntryTable +// size: 0xC +class dRawArcTable_c { +public: + dRawArcTable_c(); + ~dRawArcTable_c(); + + bool init(u16 count, void *callbackArg, EGG::Heap *heap); + bool getArcOrLoadFromDisk(const char *name, const char *dirName, u8 mountDirection, EGG::Heap *heap); + bool addEntryFromSuperArc(const char *name, void *data, u8 mountDirection, EGG::Heap *heap); + int ensureLoadedMaybe2(const char *name); + int ensureLoadedMaybe(const char *name); + bool hasEntry(const char *name); + bool decreaseRefCount(const char *name); + void *getDataFromOarc(const char *name, const char *path); + void *getSubEntryData(const char *name, const char *path); + void *getLoadedArcData(const char *name); + int ensureAllEntriesLoaded(); + dRawArcEntry_c *findEntry(const char *name) const; + dRawArcEntry_c *findEmptySlot(); + dRawArcEntry_c *findLoadedEntry(const char *name); + +private: + /* 0x0 */ dRawArcEntry_c *mpEntries; + /* 0x4 */ u16 mCount; + /* 0x8 */ void *mCallbackArg; +}; + +#endif; diff --git a/include/egg/core/eggArchive.h b/include/egg/core/eggArchive.h index 72f2ec97..506362d8 100644 --- a/include/egg/core/eggArchive.h +++ b/include/egg/core/eggArchive.h @@ -45,7 +45,7 @@ public: /* 80493a40 */ static Archive *mountNandFile(NANDFileInfo *, Heap *heap, s32 align); /* 80493ac0 */ static Archive *loadFST(const char *fileName, Heap *heap, s32 align); /* 80493b80 */ void unmount(); - /* 80493c20 */ u32 getFile(const char *name, FileInfo *out); + /* 80493c20 */ void *getFile(const char *name, FileInfo *out); /* 80493cf0 */ s32 convertPathToEntryID(const char *path); /* 80493d00 */ void *getFileFast(s32 entryId, FileInfo *fileinfo); /* 80493dc0 */ void *getFileFast(s32 entryId, Heap *heap, s32 align); diff --git a/include/m/m_heap.h b/include/m/m_heap.h index c6681bb6..05cc8308 100644 --- a/include/m/m_heap.h +++ b/include/m/m_heap.h @@ -44,7 +44,7 @@ public: /* 802f1590 */ static void createCommandHeap(size_t size, EGG::Heap *parentHeap); /* 802f15c0 */ static void createDylinkHeap(size_t size, EGG::Heap *parentHeap); /* 802f15f0 */ static EGG::AssertHeap *createAssertHeap(EGG::Heap *parentHeap); - /* 802f1640 */ static EGG::Heap *makeHeapOnCurrentGameHeap(size_t size, const char *name, u32 align, u32 flags); + /* 802f1640 */ static EGG::FrmHeap *makeHeapOnCurrentGameHeap(size_t size, const char *name, u32 align, u32 flags); static int getDefaultGameHeapId(); diff --git a/include/rvl/ARC/arc.h b/include/rvl/ARC/arc.h index 33096322..1731aba5 100644 --- a/include/rvl/ARC/arc.h +++ b/include/rvl/ARC/arc.h @@ -74,9 +74,9 @@ typedef struct ARCEntry { typedef struct ARCDirEntry { ARCHandle *handle; // at 0x0 - u32 path_begin; // at 0x4 - u32 path_it; // at 0x8 - u32 path_end; // at 0xC + u32 entryNum; // at 0x4 + u32 isDir; // at 0x8 + const char *name; // at 0xC } ARCDirEntry; BOOL ARCGetCurrentDir(ARCHandle *handle, char *string, u32 maxlen); diff --git a/include/toBeSorted/arc_manager.h b/include/toBeSorted/arc_manager.h deleted file mode 100644 index 1c7615a3..00000000 --- a/include/toBeSorted/arc_manager.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ARC_MANAGER_H -#define ARC_MANAGER_H - -#include - -// Ghidra: ArcManagerEntry -// size: 0x40 -struct ArcManagerEntry { - /* 0x00 */ char arc_name[0x20]; - /* 0x20 */ u16 ref_count; - /* 0x24 */ int dvd_req_ptr; - /* 0x28 */ int archive_ptr; - /* 0x2C */ int heap_ptr_0; - /* 0x30 */ char field_0x30[0x3C - 0x30]; - /* 0x3C */ int heap_ptr_1; -}; - -// Ghidra: ArcManagerEntryTable -// size: 0xC -class ArcMangerEntryTable { -public: - /* 0x0 */ ArcManagerEntry *entries; - /* 0x4 */ u16 count; - /* 0x8 */ u32 field_0x8; - -public: - ArcMangerEntryTable(); -}; - -class OarcManager { -public: - void *getDataFromOarc(char *oarcName, char *fileName); -}; - -OarcManager g_OarcManager; - -#endif; diff --git a/src/d/d_rawarchive.cpp b/src/d/d_rawarchive.cpp new file mode 100644 index 00000000..db540865 --- /dev/null +++ b/src/d/d_rawarchive.cpp @@ -0,0 +1,430 @@ +#include +#include +// clang-format off +#include +// clang-format on + + +class UnkManager { +public: + /* vtable at 8050df50 */ + /** 800651c0 */ + virtual void CreateArc(void *data, const char *path); + /** 800653d0 */ + virtual void DestroyArc(const char *path); + + u32 stage; +}; + +extern "C" int fn_80061B10(void *d, u32 len) { + u32 *data = (u32*)d; + u32 result = 0; + // Compiler will unroll this loop + for (u32 len_words = len / 4; len_words != 0; len_words--) { + result += *data++; + } + return result; +} + +extern "C" int fn_80061BA0(void *data, u32 len) { + int result = fn_80061B10(data, len); + return result != 0 ? result : -1; +} + +extern "C" void fn_80061BE0(UnkManager *mgr, const char *name, size_t len) { + // Sets stage to all spaces + mgr->stage = 0x20202020; + // copies the stage name? + memcpy((char*)&mgr->stage, name, len); +} + +dRawArcEntry_c::dRawArcEntry_c() { + mArcName[0] = '\0'; + mRefCount = 0; + mpDvdReq = nullptr; + mpArc = nullptr; + mpCommandHeap = nullptr; + mpData = nullptr; + mChecksum = 0; + mpFrmHeap = 0; +} + +dRawArcEntry_c::~dRawArcEntry_c() { + // Wait for request to complete before destroying + if (mpDvdReq->mStatus == 0) { + do { + VIWaitForRetrace(); + } while (mpDvdReq->mStatus == 0); + } + destroy(nullptr); +} + + +void dRawArcEntry_c::searchCallback(void *arg, void *data, const ARCDirEntry *entry, const char *path, bool ctrl) { + UnkManager *mgr = (UnkManager *)arg; + if (entry->isDir) { + int len = strlen(entry->name); + fn_80061BE0(mgr, entry->name, len <= 4 ? len : 4); + } else { + // dolphin: arg vtable at 8050df50 + // any others? + if (ctrl) { + mgr->CreateArc(data, path); + // branch to 800651c0, sets up room + } else { + mgr->DestroyArc(path); + // branch to 800653d0, destroys room + } + } +} + +void dRawArcEntry_c::searchCallback1(void *a, void *b, const ARCDirEntry *c, const char *d) { + searchCallback(a, b, c, d, true); +} + +void dRawArcEntry_c::searchCallback2(void *a, void *b, const ARCDirEntry *c, const char *d) { + searchCallback(a, b, c, d, false); +} + + +bool dRawArcEntry_c::destroy(void *arg) { + if (mpDvdReq != nullptr) { + if (mpDvdReq->mStatus == 0) { + // Can't destroy if the request is still ongoing + return false; + } + mpArc = mpDvdReq->mDataPtr; + mpData = mpDvdReq->getArcBinary(); + mAmountRead = mpDvdReq->mAmountRead; + mpCommandHeap = mpDvdReq->mHeap; + mpDvdReq->do_delete(); + mpDvdReq = nullptr; + } + + if (mpArc != nullptr) { + if (arg != nullptr) { + mpArc->searchInside(searchCallback2, arg); + } + + if (mpFrmHeap != nullptr) { + mHeap::destroyFrmHeap(mpFrmHeap); + mpFrmHeap = nullptr; + } + mpArc->unmount(); + mpArc = nullptr; + } + + if (mpData != nullptr) { + EGG::Heap::free(mpData, nullptr); + mpData = nullptr; + } + + mAmountRead = 0; + mChecksum = 0; + mpCommandHeap = 0; + return true; +} + +bool dRawArcEntry_c::loadArcFromDiskChecked(const char *fileName, const char *dirName, u8 mountDirection, + EGG::Heap *heap) { + char arcPath[128]; + arcPath[0] = '\0'; + + if (checkArcExistsOnDiskInner(arcPath, fileName, dirName)) { + return loadArcFromDisk(fileName, arcPath, mountDirection, heap); + } + return false; +} + +// Regswap +inline void inline_strncat(char *dest, const char *src, size_t destSize) { + if (src != nullptr) { + size_t destLen = strlen(dest); + size_t srcLen = strlen(src); + size_t count = destLen + srcLen + 1 >= destSize ? destSize - destLen - 1 : srcLen; + strncpy(dest + destLen, src, count); + size_t offset = destLen + count; + dest[offset] = '\0'; + } +} + +inline void inline_strncpy(char *dest, const char *src, size_t destSize) { + if (src != dest) { + dest[0] = '\0'; + inline_strncat(dest, src, destSize); + } +} + +bool dRawArcEntry_c::loadArcFromDisk(const char *arcName, const char *arcPath, u8 mountDirection, EGG::Heap *heap) { + mpDvdReq = mDvd_mountMemArchive_c::create(arcPath, mountDirection, heap); + if (mpDvdReq == nullptr) { + return false; + } + inline_strncpy(mArcName, arcName, sizeof(mArcName)); + return true; +} + +bool dRawArcEntry_c::checkArcExistsOnDisk(const char *fileName, const char *dirName) { + char path[128]; + path[0] = '\0'; + return checkArcExistsOnDiskInner(path, fileName, dirName); +} + +// sprintf2 +extern "C" void fn_8003D650(char *out, const char *fmt, ...); + +bool dRawArcEntry_c::checkArcExistsOnDiskInner(char *outBuf, const char *fileName, const char *dirName) { + fn_8003D650(outBuf, "/US/%s/%s.arc", dirName, fileName); + if (!mDvd::IsExistPath(outBuf)) { + fn_8003D650(outBuf, "/%s/%s.arc", dirName, fileName); + if (!mDvd::IsExistPath(outBuf)) { + return false; + } + } + return true; +} + +int dRawArcEntry_c::mount(const char *name, void *data, void *callbackArg, u8 mountDirection, EGG::Heap *heap) { + inline_strncpy(mArcName, name, sizeof(mArcName)); + // TODO this conditional uses a few more instructions in the original binary + mpArc = EGG::Archive::mount(data, heap, mountDirection != 1 ? 4 : -4); + if (mpArc == nullptr) { + return -1; + } else { + int result = onMount(callbackArg); + int ret = 0; + if (result == -1) { + ret = result; + } + return ret; + } +} + +int dRawArcEntry_c::ensureLoadedMaybe(void *callbackArg) { + if (mpArc == nullptr) { + if (mpDvdReq == nullptr) { + return -1; + } + + if (mpDvdReq->mStatus == 0) { + return 1; + } + + mpArc = mpDvdReq->mDataPtr; + mpData = mpDvdReq->getArcBinary(); + mAmountRead = mpDvdReq->mAmountRead; + if (mpData != nullptr) { + u32 blockSize = EGG::ExpHeap::getSizeForMBlock(mpData); + if (mAmountRead != blockSize) { + mAmountRead = blockSize; + } + } + + mpCommandHeap = mpDvdReq->mHeap; + mpDvdReq->do_delete(); + mpDvdReq = nullptr; + if (mpArc == nullptr) { + return -1; + } + mpFrmHeap = mHeap::makeHeapOnCurrentGameHeap(-1, this->mArcName, 0x20, 0); + if (mpFrmHeap == nullptr) { + return -1; + } + int result = onMount(callbackArg); + mHeap::restoreCurrentHeap(); + mHeap::adjustFrmHeap(mpFrmHeap); + mChecksum = fn_80061BA0(mpData, mAmountRead); + if (result == -1) { + return result; + } + DCStoreRange(mpFrmHeap, mpFrmHeap->mHeapHandle->end - (u8*)mpFrmHeap); + } + + return 0; +} + +int dRawArcEntry_c::onMount(void *callbackArg) { + mpArc->countFile(); + if (callbackArg != nullptr) { + mpArc->searchInside(searchCallback1, callbackArg); + } + return 0; +} + + +dRawArcTable_c::dRawArcTable_c() { + mpEntries = nullptr; + mCount = 0; + mCallbackArg = nullptr; +} + +dRawArcTable_c::~dRawArcTable_c() { + if (mpEntries) { + delete[] mpEntries; + mpEntries = nullptr; + mCount = 0; + } +} + +bool dRawArcTable_c::init(u16 count, void *callbackArg, EGG::Heap *heap) { + mpEntries = new (heap, 0x04) dRawArcEntry_c[count](); + if (mpEntries == nullptr) { + return false; + } + + mCount = count; + mCallbackArg = callbackArg; + return true; +} + +bool dRawArcTable_c::getArcOrLoadFromDisk(const char *name, const char *dirName, u8 mountDirection, EGG::Heap *heap) { + dRawArcEntry_c *entry = findEntry(name); + if (entry == nullptr) { + entry = findEmptySlot(); + if (entry == nullptr) { + return false; + } + bool result = entry->loadArcFromDiskChecked(name, dirName, mountDirection, heap); + if (!result) { + entry->destroy(mCallbackArg); + return false; + } + } + entry->increaseRefCount(); + return true; +} + +bool dRawArcTable_c::addEntryFromSuperArc(const char *name, void *data, u8 mountDirection, EGG::Heap *heap) { + dRawArcEntry_c *entry = findEntry(name); + if (entry == nullptr) { + entry = findEmptySlot(); + if (entry == nullptr) { + return false; + } + int result = entry->mount(name, data, mCallbackArg, mountDirection, heap); + if (result != 0) { + entry->destroy(mCallbackArg); + return false; + } + } + entry->increaseRefCount(); + return true; +} + +int dRawArcTable_c::ensureLoadedMaybe2(const char *name) { + dRawArcEntry_c *entry = findEntry(name); + if (entry == nullptr) { + return -2; + } + return entry->ensureLoadedMaybe(mCallbackArg); +} + +int dRawArcTable_c::ensureLoadedMaybe(const char *name) { + dRawArcEntry_c *entry = findEntry(name); + if (entry == nullptr) { + return -2; + } + return entry->ensureLoadedMaybe(mCallbackArg); +} + +bool dRawArcTable_c::hasEntry(const char *name) { + return findEntry(name) != nullptr; +} + +bool dRawArcTable_c::decreaseRefCount(const char *name) { + dRawArcEntry_c *entry = findEntry(name); + if (entry == nullptr) { + return false; + } + entry->decreaseRefCount(); + if (!entry->isReferenced()) { + entry->destroy(mCallbackArg); + } + return true; +} + +void *dRawArcTable_c::getDataFromOarc(const char *name, const char *path) { + void *data = nullptr; + dRawArcEntry_c *entry = findLoadedEntry(name); + if (entry != nullptr) { + EGG::Archive *arc = entry->getArc(); + if (arc != nullptr) { + data = arc->getFile(path, nullptr); + } + } + return data; +} + +void *dRawArcTable_c::getSubEntryData(const char *name, const char *path) { + void *data = nullptr; + dRawArcEntry_c *entry = findLoadedEntry(name); + if (entry != nullptr) { + EGG::Archive *arc = entry->getArc(); + if (arc != nullptr) { + int num = arc->convertPathToEntryID(path); + if (num >= 0) { + data = arc->getFileFast(num, nullptr); + } + } + } + return data; +} + +void *dRawArcTable_c::getLoadedArcData(const char *name) { + dRawArcEntry_c *entry = findLoadedEntry(name); + return entry == nullptr ? nullptr : entry->getData(); +} + +int dRawArcTable_c::ensureAllEntriesLoaded() { + dRawArcEntry_c *entry = mpEntries; + int result = 0; + for (int i = 0; i < mCount; i++) { + if (entry->isLoading()) { + result = entry->ensureLoadedMaybe(mCallbackArg); + if (result != 0) { + return result; + } + } + entry++; + } + + return 0; +} + + +extern "C" bool strequals(const char *, const char*); + +// TODO the load from self can happen earlier +dRawArcEntry_c *dRawArcTable_c::findEntry(const char *name) const { + dRawArcEntry_c *entry = mpEntries; + for (int i = 0; i < mCount; i++) { + if (entry->isReferenced() && strequals(entry->name(), name)) { + return entry; + } + entry++; + } + + return nullptr; +} + +dRawArcEntry_c *dRawArcTable_c::findEmptySlot() { + dRawArcEntry_c *entry = mpEntries; + for (int i = 0; i < mCount; i++) { + if (!entry->isReferenced()) { + return entry; + } + entry++; + } + + return nullptr; +} + +dRawArcEntry_c *dRawArcTable_c::findLoadedEntry(const char *name) { + dRawArcEntry_c *entry = findEntry(name); + if (entry == nullptr) { + return nullptr; + } else if (entry->isNotLoaded()) { + return nullptr; + } + return entry; +} diff --git a/src/m/m_heap.cpp b/src/m/m_heap.cpp index ca18857f..5220d771 100644 --- a/src/m/m_heap.cpp +++ b/src/m/m_heap.cpp @@ -207,6 +207,6 @@ EGG::AssertHeap *mHeap::createAssertHeap(EGG::Heap *parent) { return g_assertHeap; } -EGG::Heap *mHeap::makeHeapOnCurrentGameHeap(size_t size, const char *name, u32 align, u32 flags) { +EGG::FrmHeap *mHeap::makeHeapOnCurrentGameHeap(size_t size, const char *name, u32 align, u32 flags) { return makeFrmHeapAndUpdate(size, g_gameHeaps[0], name, align, flags); }