From e054193f0ad047bfa8df174a2dd6b1cc98bca6c7 Mon Sep 17 00:00:00 2001 From: Jcw87 Date: Sat, 16 Sep 2023 13:49:23 -0700 Subject: [PATCH] JKRThread, JKRExpHeap, JKRFileLoader, JKRArchive (#42) * JKRThread * JKRExpHeap * JKRFileLoader * JKRArchive --- configure.py | 4 +- include/JSystem/JKernel/JKRAramArchive.h | 2 - include/JSystem/JKernel/JKRArchive.h | 9 +- include/JSystem/JKernel/JKRCompArchive.h | 2 - include/JSystem/JKernel/JKRDvdArchive.h | 2 - include/JSystem/JKernel/JKRExpHeap.h | 7 +- include/JSystem/JKernel/JKRHeap.h | 2 +- include/JSystem/JKernel/JKRMemArchive.h | 2 - include/JSystem/JKernel/JKRSolidHeap.h | 2 +- include/JSystem/JKernel/JKRThread.h | 57 +- src/JSystem/JKernel/JKRArchivePri.cpp | 219 +++++- src/JSystem/JKernel/JKRArchivePub.cpp | 341 ++++++-- src/JSystem/JKernel/JKRExpHeap.cpp | 944 +++++++++++++++++++++-- src/JSystem/JKernel/JKRFileLoader.cpp | 145 +++- src/JSystem/JKernel/JKRThread.cpp | 135 +++- 15 files changed, 1602 insertions(+), 271 deletions(-) diff --git a/configure.py b/configure.py index faa37f577..46395c26a 100644 --- a/configure.py +++ b/configure.py @@ -760,13 +760,13 @@ config.libs = [ Object(NonMatching, "JSystem/JKernel/JKRExpHeap.cpp"), Object(NonMatching, "JSystem/JKernel/JKRSolidHeap.cpp"), Object(Matching, "JSystem/JKernel/JKRDisposer.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRThread.cpp"), + Object(Matching, "JSystem/JKernel/JKRThread.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAram.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramHeap.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramBlock.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramPiece.cpp"), Object(NonMatching, "JSystem/JKernel/JKRAramStream.cpp"), - Object(NonMatching, "JSystem/JKernel/JKRFileLoader.cpp"), + Object(Matching, "JSystem/JKernel/JKRFileLoader.cpp"), Object(NonMatching, "JSystem/JKernel/JKRFileFinder.cpp"), Object(NonMatching, "JSystem/JKernel/JKRFileCache.cpp"), Object(NonMatching, "JSystem/JKernel/JKRArchivePub.cpp"), diff --git a/include/JSystem/JKernel/JKRAramArchive.h b/include/JSystem/JKernel/JKRAramArchive.h index 4c638dbdd..5f8d28413 100644 --- a/include/JSystem/JKernel/JKRAramArchive.h +++ b/include/JSystem/JKernel/JKRAramArchive.h @@ -27,8 +27,6 @@ public: private: /* 0x00 */ // vtable /* 0x04 */ // JKRArchive - /* 0x5C */ JKRCompression mCompression; - /* 0x60 */ EMountDirection mMountDirection; /* 0x64 */ JKRAramBlock* mBlock; /* 0x68 */ JKRDvdFile* mDvdFile; }; // Size = 0x6C diff --git a/include/JSystem/JKernel/JKRArchive.h b/include/JSystem/JKernel/JKRArchive.h index 4211d3edd..8ef03c411 100644 --- a/include/JSystem/JKernel/JKRArchive.h +++ b/include/JSystem/JKernel/JKRArchive.h @@ -5,6 +5,7 @@ #include "JSystem/JKernel/JKRFileLoader.h" #include "global.h" +class JKRArcFinder; class JKRHeap; struct SArcHeader { @@ -129,7 +130,8 @@ public: void* getResource(u16); u32 readIdxResource(void*, u32, u32); u32 readResource(void*, u32, u16); - u32 countResource(void) const; + u32 countResource(u32) const; + JKRArcFinder* getFirstResource(u32) const; u32 getFileAttribute(u32) const; SDIFileEntry* findNameResource(const char*) const; @@ -182,13 +184,16 @@ public: protected: /* 0x58 */ u32 field_0x58; + /* 0x5C */ JKRCompression mCompression; + /* 0x60 */ EMountDirection mMountDirection; public: - static JKRArchive* check_mount_already(s32, JKRHeap*); + static JKRArchive* check_mount_already(s32); static JKRArchive* mount(const char*, EMountMode, JKRHeap*, EMountDirection); static JKRArchive* mount(void*, JKRHeap*, EMountDirection); static JKRArchive* mount(s32, EMountMode, JKRHeap*, EMountDirection); static void* getGlbResource(u32, const char*, JKRArchive*); + static void readTypeResource(void*, u32, u32, const char*, JKRArchive*); static JKRCompression convertAttrToCompressionType(u32 attr) { #define JKRARCHIVE_ATTR_COMPRESSION 0x04 diff --git a/include/JSystem/JKernel/JKRCompArchive.h b/include/JSystem/JKernel/JKRCompArchive.h index 98da6327d..338332fb6 100644 --- a/include/JSystem/JKernel/JKRCompArchive.h +++ b/include/JSystem/JKernel/JKRCompArchive.h @@ -24,8 +24,6 @@ public: private: /* 0x00 */ // vtable /* 0x04 */ // JKRArchive - /* 0x5C */ int mCompression; - /* 0x60 */ EMountDirection mMountDirection; /* 0x64 */ int field_0x64; /* 0x68 */ JKRAramBlock* mAramPart; /* 0x6C */ int field_0x6c; diff --git a/include/JSystem/JKernel/JKRDvdArchive.h b/include/JSystem/JKernel/JKRDvdArchive.h index e2e6b408b..fe72cd8f3 100644 --- a/include/JSystem/JKernel/JKRDvdArchive.h +++ b/include/JSystem/JKernel/JKRDvdArchive.h @@ -23,8 +23,6 @@ public: private: /* 0x00 */ // vtable /* 0x04 */ // JKRArchive - /* 0x5C */ JKRCompression mCompression; - /* 0x60 */ EMountDirection mMountDirection; /* 0x64 */ s32 field_0x64; /* 0x68 */ JKRDvdFile* mDvdFile; }; diff --git a/include/JSystem/JKernel/JKRExpHeap.h b/include/JSystem/JKernel/JKRExpHeap.h index 3d566c03c..6a89271e9 100644 --- a/include/JSystem/JKernel/JKRExpHeap.h +++ b/include/JSystem/JKernel/JKRExpHeap.h @@ -56,11 +56,12 @@ protected: void removeUsedBlock(CMemBlock* block); void recycleFreeBlock(CMemBlock* block); void joinTwoBlocks(CMemBlock* block); + bool dump_sort_by_address(); public: s32 getUsedSize(u8 groupId) const; s32 getTotalUsedSize(void) const; - + CMemBlock* getHeadUsedList() const { return mHeadUsedList; } void setAllocationMode(EAllocMode mode) { mAllocMode = mode; @@ -76,7 +77,7 @@ public: /* vt[10] */ virtual void do_free(void* ptr); /* override */ /* vt[11] */ virtual void do_freeAll(); /* override */ /* vt[12] */ virtual void do_freeTail(); /* override */ - /* vt[13] */ virtual void do_fillFreeArea(); /* override */ + /* vt[13] */ virtual void do_freeFill(); /* override */ /* vt[14] */ virtual s32 do_resize(void* ptr, u32 size); /* override */ /* vt[15] */ virtual s32 do_getSize(void* ptr); /* override */ /* vt[16] */ virtual s32 do_getFreeSize(); /* override */ @@ -84,7 +85,7 @@ public: /* vt[18] */ virtual s32 do_getTotalFreeSize(); /* override */ /* vt[19] */ virtual s32 do_changeGroupID(u8 newGroupID); /* override */ /* vt[20] */ virtual u8 do_getCurrentGroupId(); /* override */ - /* vt[21] */ virtual u32 state_register(JKRHeap::TState* p, u32 id) const; /* override */ + /* vt[21] */ virtual void state_register(JKRHeap::TState* p, u32 id) const; /* override */ /* vt[22] */ virtual bool state_compare(JKRHeap::TState const& r1, JKRHeap::TState const& r2) const; /* override */ diff --git a/include/JSystem/JKernel/JKRHeap.h b/include/JSystem/JKernel/JKRHeap.h index f8703af86..be6ea956e 100644 --- a/include/JSystem/JKernel/JKRHeap.h +++ b/include/JSystem/JKernel/JKRHeap.h @@ -67,7 +67,7 @@ public: /* vt[10] */ virtual void do_free(void* ptr) = 0; /* vt[11] */ virtual void do_freeAll() = 0; /* vt[12] */ virtual void do_freeTail() = 0; - /* vt[13] */ virtual void do_fillFreeArea() = 0; + /* vt[13] */ virtual void do_freeFill() = 0; /* vt[14] */ virtual s32 do_resize(void* ptr, u32 size) = 0; /* vt[15] */ virtual s32 do_getSize(void* ptr) = 0; /* vt[16] */ virtual s32 do_getFreeSize() = 0; diff --git a/include/JSystem/JKernel/JKRMemArchive.h b/include/JSystem/JKernel/JKRMemArchive.h index ba76ab1ea..eb09c0b20 100644 --- a/include/JSystem/JKernel/JKRMemArchive.h +++ b/include/JSystem/JKernel/JKRMemArchive.h @@ -31,8 +31,6 @@ public: private: /* 0x00 */ // vtable /* 0x04 */ // JKRArchive - /* 0x5C */ JKRCompression mCompression; - /* 0x60 */ EMountDirection mMountDirection; /* 0x64 */ SArcHeader* mArcHeader; /* 0x68 */ u8* mArchiveData; /* 0x6C */ bool mIsOpen; diff --git a/include/JSystem/JKernel/JKRSolidHeap.h b/include/JSystem/JKernel/JKRSolidHeap.h index 069b87ea5..83a6e918a 100644 --- a/include/JSystem/JKernel/JKRSolidHeap.h +++ b/include/JSystem/JKernel/JKRSolidHeap.h @@ -32,7 +32,7 @@ public: /* vt[10] */ virtual void do_free(void*); /* override */ /* vt[11] */ virtual void do_freeAll(void); /* override */ /* vt[12] */ virtual void do_freeTail(void); /* override */ - /* vt[13] */ virtual void do_fillFreeArea(void); /* override */ + /* vt[13] */ virtual void do_freeFill(void); /* override */ /* vt[14] */ virtual s32 do_resize(void*, u32); /* override */ /* vt[15] */ virtual s32 do_getSize(void*); /* override */ /* vt[16] */ virtual s32 do_getFreeSize(void); /* override */ diff --git a/include/JSystem/JKernel/JKRThread.h b/include/JSystem/JKernel/JKRThread.h index f56a9231e..ca4e85678 100644 --- a/include/JSystem/JKernel/JKRThread.h +++ b/include/JSystem/JKernel/JKRThread.h @@ -14,53 +14,11 @@ struct JKRThreadName_ { class JUTConsole; class JKRThread : JKRDisposer { public: - class TLoad { - public: - TLoad() { - clear(); - mValid = false; - mThreadId = 0; - } - - bool isValid() const { return mValid; } - u32 getCost() const { return mCost; } - u32 getCount() const { return mSwitchCount; } - s32 getId() const { return mThreadId; } - - void setValid(bool valid) { mValid = valid; } - void setId(s32 id) { mThreadId = id; } - void setCurrentTime() { mLastTick = OSGetTick(); } - - void resetCost() { mCost = 0; } - void resetCount() { mSwitchCount = 0; } - - void incCount() { mSwitchCount++; } - void addCurrentCost() { mCost = mCost + (OSGetTick() - mLastTick); } - - void clear() { - resetCount(); - resetCost(); - mLastTick = 0; - } - - private: - /* 0x00 */ bool mValid; - /* 0x01 */ u8 padding_0x61[3]; - /* 0x04 */ u32 mCost; - /* 0x08 */ u32 mSwitchCount; - /* 0x0C */ OSTick mLastTick; - /* 0x10 */ s32 mThreadId; - }; - JKRThread(u32 stack_size, int message_count, int param_3); - JKRThread(JKRHeap* heap, u32 stack_size, int message_count, int param_4); JKRThread(OSThread* thread, int message_count); virtual ~JKRThread(); - /* vt[03] */ virtual void* run(); - - void setCommon_mesgQueue(JKRHeap* heap, int message_count); - void setCommon_heapSpecified(JKRHeap* heap, u32 stack_size, int param_3); + /* vt[03] */ virtual void* run() { return NULL; } OSThread* getThreadRecord() const { return mThreadRecord; } void* getStack() const { return mStackMemory; } @@ -122,9 +80,6 @@ typedef void (*JKRThreadSwitch_PostCallback)(OSThread* current, OSThread* next); class JKRThreadSwitch { public: JKRThreadSwitch(JKRHeap*); - virtual void draw(JKRThreadName_* param_1, JUTConsole* param_2); - virtual void draw(JKRThreadName_* param_1); - virtual ~JKRThreadSwitch(); static JKRThreadSwitch* createManager(JKRHeap* heap); @@ -145,13 +100,9 @@ private: /* 0x00 */ // vtable /* 0x04 */ JKRHeap* mHeap; /* 0x08 */ bool mSetNextHeap; - /* 0x09 */ u8 field_0x9[3]; - /* 0x0C */ u32 field_0xC; - /* 0x10 */ u32 field_0x10; - /* 0x14 */ u8 field_0x14[4]; - /* 0x18 */ s64 field_0x18; - /* 0x20 */ u32 field_0x20; - /* 0x24 */ u32 field_0x24; + +public: + virtual ~JKRThreadSwitch() {} }; struct JKRTask { diff --git a/src/JSystem/JKernel/JKRArchivePri.cpp b/src/JSystem/JKernel/JKRArchivePri.cpp index 48f232b24..133fbb8c8 100644 --- a/src/JSystem/JKernel/JKRArchivePri.cpp +++ b/src/JSystem/JKernel/JKRArchivePri.cpp @@ -3,85 +3,238 @@ // Translation Unit: JKRArchivePri.cpp // -#include "JSystem/JKernel/JKRArchivePri.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "MSL_C/MSL_Common/Src/ctype.h" +#include "MSL_C/string.h" #include "dolphin/types.h" +u32 JKRArchive::sCurrentDirID; + /* 802B8DFC-802B8E48 .text __ct__10JKRArchiveFv */ JKRArchive::JKRArchive() { - /* Nonmatching */ + mIsMounted = false; + mMountDirection = MOUNT_DIRECTION_HEAD; } /* 802B8E48-802B8EE8 .text __ct__10JKRArchiveFlQ210JKRArchive10EMountMode */ -JKRArchive::JKRArchive(long, JKRArchive::EMountMode) { - /* Nonmatching */ +JKRArchive::JKRArchive(s32 entryNumber, JKRArchive::EMountMode mountMode) { + mIsMounted = false; + mMountMode = mountMode; + mMountCount = 1; + field_0x58 = 1; + + mHeap = JKRHeap::findFromRoot(this); + if (mHeap == NULL) { + mHeap = JKRHeap::getCurrentHeap(); + } + + mEntryNum = entryNumber; + if (getCurrentVolume() == NULL) { + setCurrentVolume(this); + setCurrentDirID(0); + } } /* 802B8EE8-802B8F48 .text __dt__10JKRArchiveFv */ -JKRArchive::~JKRArchive() { - /* Nonmatching */ -} +JKRArchive::~JKRArchive() {} /* 802B8F48-802B8F94 .text isSameName__10JKRArchiveCFRQ210JKRArchive8CArcNameUlUs */ -void JKRArchive::isSameName(JKRArchive::CArcName&, unsigned long, unsigned short) const { - /* Nonmatching */ +bool JKRArchive::isSameName(JKRArchive::CArcName& name, u32 nameOffset, u16 nameHash) const { + u16 hash = name.getHash(); + if (hash != nameHash) + return false; + return strcmp(mStringTable + nameOffset, name.getString()) == 0; } /* 802B8F94-802B8FD0 .text findResType__10JKRArchiveCFUl */ -void JKRArchive::findResType(unsigned long) const { - /* Nonmatching */ +JKRArchive::SDIDirEntry* JKRArchive::findResType(u32 type) const { + SDIDirEntry* node = mNodes; + u32 count = 0; + while (count < mArcInfoBlock->num_nodes) { + if (node->type == type) { + return node; + } + + node++; + count++; + } + + return NULL; } /* 802B8FD0-802B90A8 .text findDirectory__10JKRArchiveCFPCcUl */ -void JKRArchive::findDirectory(const char*, unsigned long) const { - /* Nonmatching */ +JKRArchive::SDIDirEntry* JKRArchive::findDirectory(const char* name, u32 directoryId) const { + if (name == NULL) { + return mNodes + directoryId; + } + + CArcName arcName(&name, '/'); + SDIDirEntry* dirEntry = mNodes + directoryId; + SDIFileEntry* fileEntry = mFiles + dirEntry->first_file_index; + + for (int i = 0; i < dirEntry->num_entries; fileEntry++, i++) { + if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->name_hash)) { + if (fileEntry->isDirectory()) { + return findDirectory(name, fileEntry->data_offset); + } + break; + } + } + + return NULL; } /* 802B90A8-802B9158 .text findTypeResource__10JKRArchiveCFUlPCc */ -void JKRArchive::findTypeResource(unsigned long, const char*) const { - /* Nonmatching */ +JKRArchive::SDIFileEntry* JKRArchive::findTypeResource(u32 type, const char* name) const { + if (type) { + CArcName arcName(name); + SDIDirEntry* dirEntry = findResType(type); + + if (dirEntry) { + SDIFileEntry* fileEntry = mFiles + dirEntry->first_file_index; + for (int i = 0; i < dirEntry->num_entries; fileEntry++, i++) { + if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->getNameHash())) { + return fileEntry; + } + } + } + } + + return NULL; } /* 802B9158-802B9238 .text findFsResource__10JKRArchiveCFPCcUl */ -void JKRArchive::findFsResource(const char*, unsigned long) const { - /* Nonmatching */ +JKRArchive::SDIFileEntry* JKRArchive::findFsResource(const char* name, u32 directoryId) const { + if (name) { + CArcName arcName(&name, '/'); + SDIDirEntry* dirEntry = mNodes + directoryId; + SDIFileEntry* fileEntry = mFiles + dirEntry->first_file_index; + + for (int i = 0; i < dirEntry->num_entries; fileEntry++, i++) { + if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->name_hash)) { + if (fileEntry->isDirectory()) { + return findFsResource(name, fileEntry->data_offset); + } + + if (name == NULL) { + return fileEntry; + } + + return NULL; + } + } + } + + return NULL; } /* 802B9238-802B9260 .text findIdxResource__10JKRArchiveCFUl */ -void JKRArchive::findIdxResource(unsigned long) const { - /* Nonmatching */ +JKRArchive::SDIFileEntry* JKRArchive::findIdxResource(u32 fileIndex) const { + if (fileIndex < mArcInfoBlock->num_file_entries) { + return mFiles + fileIndex; + } + + return NULL; } /* 802B9260-802B92E8 .text findNameResource__10JKRArchiveCFPCc */ -void JKRArchive::findNameResource(const char*) const { - /* Nonmatching */ +JKRArchive::SDIFileEntry* JKRArchive::findNameResource(const char* name) const { + SDIFileEntry* fileEntry = mFiles; + + CArcName arcName(name); + for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) { + if (isSameName(arcName, fileEntry->getNameOffset(), fileEntry->getNameHash())) { + return fileEntry; + } + } + + return NULL; } /* 802B92E8-802B9324 .text findPtrResource__10JKRArchiveCFPCv */ -void JKRArchive::findPtrResource(const void*) const { - /* Nonmatching */ +JKRArchive::SDIFileEntry* JKRArchive::findPtrResource(const void* resource) const { + SDIFileEntry* fileEntry = mFiles; + for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) { + if (fileEntry->data == resource) { + return fileEntry; + } + } + + return NULL; } /* 802B9324-802B93A4 .text findIdResource__10JKRArchiveCFUs */ -void JKRArchive::findIdResource(unsigned short) const { - /* Nonmatching */ +JKRArchive::SDIFileEntry* JKRArchive::findIdResource(u16 id) const { + if (id != 0xFFFF) { + SDIFileEntry* fileEntry = mFiles + id; + if (fileEntry->file_id == id && fileEntry->isUnknownFlag1()) { + return fileEntry; + } + + fileEntry = mFiles; + for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) { + if (fileEntry->file_id == id && fileEntry->isUnknownFlag1()) { + return fileEntry; + } + } + } + + return NULL; } /* 802B93A4-802B9434 .text store__Q210JKRArchive8CArcNameFPCc */ -void JKRArchive::CArcName::store(const char*) { - /* Nonmatching */ +void JKRArchive::CArcName::store(const char* name) { + mHash = 0; + s32 length = 0; + while (*name) { + s32 ch = tolower(*name); + mHash = ch + mHash * 3; + if (length < (s32)ARRAY_SIZE(mData)) { + mData[length++] = ch; + } + name++; + } + + mLength = (u16)length; + mData[length] = 0; } /* 802B9434-802B94EC .text store__Q210JKRArchive8CArcNameFPCcc */ -void JKRArchive::CArcName::store(const char*, char) { - /* Nonmatching */ +const char* JKRArchive::CArcName::store(const char* name, char endChar) { + mHash = 0; + s32 length = 0; + while (*name && *name != endChar) { + s32 lch = tolower((int)*name); + mHash = lch + mHash * 3; + if (length < (s32)ARRAY_SIZE(mData)) { + mData[length++] = lch; + } + name++; + } + + mLength = (u16)length; + mData[length] = 0; + + if (*name == 0) + return NULL; + return name + 1; } /* 802B94EC-802B9528 .text setExpandSize__10JKRArchiveFPQ210JKRArchive12SDIFileEntryUl */ -void JKRArchive::setExpandSize(JKRArchive::SDIFileEntry*, unsigned long) { - /* Nonmatching */ +void JKRArchive::setExpandSize(SDIFileEntry* fileEntry, u32 expandSize) { + int index = fileEntry - mFiles; + if (!mExpandedSize || index >= mArcInfoBlock->num_file_entries) + return; + + mExpandedSize[index] = expandSize; } /* 802B9528-802B9568 .text getExpandSize__10JKRArchiveCFPQ210JKRArchive12SDIFileEntry */ -void JKRArchive::getExpandSize(JKRArchive::SDIFileEntry*) const { - /* Nonmatching */ +u32 JKRArchive::getExpandSize(SDIFileEntry* fileEntry) const { + int index = fileEntry - mFiles; + if (!mExpandedSize || index >= mArcInfoBlock->num_file_entries) + return 0; + + return mExpandedSize[index]; } diff --git a/src/JSystem/JKernel/JKRArchivePub.cpp b/src/JSystem/JKernel/JKRArchivePub.cpp index edcaf0679..f080e84ad 100644 --- a/src/JSystem/JKernel/JKRArchivePub.cpp +++ b/src/JSystem/JKernel/JKRArchivePub.cpp @@ -3,115 +3,368 @@ // Translation Unit: JKRArchivePub.cpp // -#include "JSystem/JKernel/JKRArchivePub.h" -#include "dolphin/types.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JKernel/JKRAramArchive.h" +#include "JSystem/JKernel/JKRCompArchive.h" +#include "JSystem/JKernel/JKRDvdArchive.h" +#include "JSystem/JKernel/JKRFileFinder.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JKernel/JKRMemArchive.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "dolphin/dvd/dvd.h" /* 802B7FB4-802B8008 .text check_mount_already__10JKRArchiveFl */ -void JKRArchive::check_mount_already(long) { - /* Nonmatching */ +JKRArchive* JKRArchive::check_mount_already(s32 entryNum) { + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (iterator->getVolumeType() == 'RARC') { + JKRArchive* archive = (JKRArchive*)iterator.getObject(); + if (archive->mEntryNum == entryNum) { + archive->mMountCount++; + return archive; + } + } + } + + return NULL; } /* 802B8008-802B8064 .text mount__10JKRArchiveFPCcQ210JKRArchive10EMountModeP7JKRHeapQ210JKRArchive15EMountDirection */ -void JKRArchive::mount(const char*, JKRArchive::EMountMode, JKRHeap*, JKRArchive::EMountDirection) { - /* Nonmatching */ +JKRArchive* JKRArchive::mount(const char* path, JKRArchive::EMountMode mountMode, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) { + s32 entryNum = DVDConvertPathToEntrynum(path); + if (entryNum < 0) + return NULL; + + return mount(entryNum, mountMode, heap, mountDirection); } /* 802B8064-802B81D0 .text mount__10JKRArchiveFlQ210JKRArchive10EMountModeP7JKRHeapQ210JKRArchive15EMountDirection */ -void JKRArchive::mount(long, JKRArchive::EMountMode, JKRHeap*, JKRArchive::EMountDirection) { - /* Nonmatching */ +JKRArchive* JKRArchive::mount(s32 entryNum, JKRArchive::EMountMode mountMode, JKRHeap* heap, JKRArchive::EMountDirection mountDirection) { + JKRArchive* archive = check_mount_already(entryNum); + if (archive != NULL) { + return archive; + } else { + int alignment; + if (mountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) { + alignment = 4; + } else { + alignment = -4; + } + + JKRArchive* archive; + switch (mountMode) { + case JKRArchive::MOUNT_MEM: + archive = new (heap, alignment) JKRMemArchive(entryNum, mountDirection); + break; + case JKRArchive::MOUNT_ARAM: + archive = new (heap, alignment) JKRAramArchive(entryNum, mountDirection); + break; + case JKRArchive::MOUNT_DVD: + archive = new (heap, alignment) JKRDvdArchive(entryNum, mountDirection); + break; + case JKRArchive::MOUNT_COMP: + archive = new (heap, alignment) JKRCompArchive(entryNum, mountDirection); + break; + } + + if (archive && archive->getMountMode() == JKRArchive::UNKNOWN_MOUNT_MODE) { + delete archive; + archive = NULL; + } + + return archive; + } } /* 802B81D0-802B8258 .text becomeCurrent__10JKRArchiveFPCc */ -void JKRArchive::becomeCurrent(const char*) { - /* Nonmatching */ +bool JKRArchive::becomeCurrent(const char* path) { + SDIDirEntry* dirEntry; + if (*path == '/') { + path++; + + if (*path == '\0') + path = NULL; + dirEntry = findDirectory(path, 0); + } else { + dirEntry = findDirectory(path, getCurrentDirID()); + } + + bool found = dirEntry != NULL; + if (found) { + setCurrentVolume(this); + setCurrentDirID(dirEntry - mNodes); + } + + return found; } /* 802B8258-802B82D0 .text getDirEntry__10JKRArchiveCFPQ210JKRArchive9SDirEntryUl */ -void JKRArchive::getDirEntry(JKRArchive::SDirEntry*, unsigned long) const { - /* Nonmatching */ +bool JKRArchive::getDirEntry(SDirEntry* dirEntry, u32 index) const { + SDIFileEntry* fileEntry = findIdxResource(index); + if (!fileEntry) { + return false; + } + + dirEntry->flags = fileEntry->getFlags(); + dirEntry->id = fileEntry->getFileID(); + dirEntry->name = mStringTable + fileEntry->getNameOffset(); + return true; } /* 802B82D0-802B8380 .text getGlbResource__10JKRArchiveFUlPCcP10JKRArchive */ -void JKRArchive::getGlbResource(unsigned long, const char*, JKRArchive*) { - /* Nonmatching */ +void* JKRArchive::getGlbResource(u32 param_0, const char* path, JKRArchive* archive) { + void* resource = NULL; + if (archive) { + return archive->getResource(param_0, path); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (iterator->getVolumeType() == 'RARC') { + resource = iterator->getResource(param_0, path); + if (resource) + break; + } + } + + return resource; } /* 802B8380-802B8450 .text getResource__10JKRArchiveFPCc */ -void JKRArchive::getResource(const char*) { - /* Nonmatching */ +void* JKRArchive::getResource(const char* path) { + JUT_ASSERT(285, isMounted()); + SDIFileEntry* fileEntry; + if (*path == '/') { + fileEntry = findFsResource(path + 1, 0); + } else { + fileEntry = findFsResource(path, getCurrentDirID()); + } + + if (fileEntry) { + return fetchResource(fileEntry, NULL); + } + + return NULL; } /* 802B8450-802B8528 .text getResource__10JKRArchiveFUlPCc */ -void JKRArchive::getResource(unsigned long, const char*) { - /* Nonmatching */ +void* JKRArchive::getResource(u32 type, const char* path) { + JUT_ASSERT(332, isMounted()); + SDIFileEntry* fileEntry; + if (type == 0 || type == '????') { + fileEntry = findNameResource(path); + } else { + fileEntry = findTypeResource(type, path); + } + + if (fileEntry) { + return fetchResource(fileEntry, NULL); + } + + return NULL; } /* 802B8528-802B85F0 .text readTypeResource__10JKRArchiveFPvUlUlPCcP10JKRArchive */ -void JKRArchive::readTypeResource(void*, unsigned long, unsigned long, const char*, JKRArchive*) { +// missing instructions +void JKRArchive::readTypeResource(void* buffer, u32 bufferSize, u32 type, const char* path, JKRArchive* archive) { /* Nonmatching */ + if (archive) { + archive->readResource(buffer, bufferSize, type, path); + return; + } + JSUListIterator iterator; + for (iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); iterator++) { + if (iterator->getVolumeType() == 'RARC') { + u32 result = iterator->readResource(buffer, bufferSize, type, path); + if (result != 0) { + return; + } + } + } } /* 802B85F0-802B86DC .text readResource__10JKRArchiveFPvUlUlPCc */ -void JKRArchive::readResource(void*, unsigned long, unsigned long, const char*) { - /* Nonmatching */ +u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u32 type, const char* path) { + JUT_ASSERT(491, isMounted()); + SDIFileEntry* fileEntry; + if (type == 0 || type == '????') { + fileEntry = findNameResource(path); + } else { + fileEntry = findTypeResource(type, path); + } + + if (fileEntry) { + u32 resourceSize; + fetchResource(buffer, bufferSize, fileEntry, &resourceSize); + return resourceSize; + } + + return 0; } /* 802B86DC-802B87C0 .text readResource__10JKRArchiveFPvUlPCc */ -void JKRArchive::readResource(void*, unsigned long, const char*) { - /* Nonmatching */ +u32 JKRArchive::readResource(void* buffer, u32 bufferSize, const char* path) { + JUT_ASSERT(537, isMounted()); + SDIFileEntry* fileEntry; + if (*path == '/') { + fileEntry = findFsResource(path + 1, 0); + } else { + fileEntry = findFsResource(path, getCurrentDirID()); + } + + if (fileEntry) { + u32 resourceSize; + fetchResource(buffer, bufferSize, fileEntry, &resourceSize); + return resourceSize; + } + + return 0; } /* 802B87C0-802B8878 .text readIdxResource__10JKRArchiveFPvUlUl */ -void JKRArchive::readIdxResource(void*, unsigned long, unsigned long) { - /* Nonmatching */ +u32 JKRArchive::readIdxResource(void* buffer, u32 bufferSize, u32 index) { + JUT_ASSERT(593, isMounted()); + SDIFileEntry* fileEntry = findIdxResource(index); + if (fileEntry) { + u32 resourceSize; + fetchResource(buffer, bufferSize, fileEntry, &resourceSize); + return resourceSize; + } + + return 0; } /* 802B8878-802B8930 .text readResource__10JKRArchiveFPvUlUs */ -void JKRArchive::readResource(void*, unsigned long, unsigned short) { - /* Nonmatching */ +u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u16 id) { + JUT_ASSERT(627, isMounted()); + SDIFileEntry* fileEntry = findIdResource(id); + if (fileEntry) { + u32 resourceSize; + fetchResource(buffer, bufferSize, fileEntry, &resourceSize); + return resourceSize; + } + + return 0; } /* 802B8930-802B89B8 .text removeResourceAll__10JKRArchiveFv */ void JKRArchive::removeResourceAll() { - /* Nonmatching */ + if (mArcInfoBlock && mMountMode != MOUNT_MEM) { + SDIFileEntry* fileEntry = mFiles; + for (int i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) { + if (fileEntry->data) { + JKRFreeToHeap(mHeap, fileEntry->data); + fileEntry->data = NULL; + } + } + } } /* 802B89B8-802B8A54 .text removeResource__10JKRArchiveFPv */ -void JKRArchive::removeResource(void*) { - /* Nonmatching */ +bool JKRArchive::removeResource(void* resource) { + JUT_ASSERT(687, resource != 0); + SDIFileEntry* fileEntry = findPtrResource(resource); + if (fileEntry == NULL) + return false; + + fileEntry->data = NULL; + JKRFreeToHeap(mHeap, resource); + return true; } /* 802B8A54-802B8AE4 .text detachResource__10JKRArchiveFPv */ -void JKRArchive::detachResource(void*) { - /* Nonmatching */ +bool JKRArchive::detachResource(void* resource) { + JUT_ASSERT(719, resource != 0); + SDIFileEntry* fileEntry = findPtrResource(resource); + if (fileEntry == NULL) + return false; + + fileEntry->data = NULL; + return true; } /* 802B8AE4-802B8B6C .text getResSize__10JKRArchiveCFPCv */ -void JKRArchive::getResSize(const void*) const { - /* Nonmatching */ +u32 JKRArchive::getResSize(const void* resource) const { + JUT_ASSERT(746, resource != 0); + SDIFileEntry* fileEntry = findPtrResource(resource); + if (fileEntry == NULL) + return -1; + + return fileEntry->data_size; } /* 802B8B6C-802B8BF0 .text countResource__10JKRArchiveCFUl */ -void JKRArchive::countResource(unsigned long) const { - /* Nonmatching */ +u32 JKRArchive::countResource(u32 type) const { + SDIDirEntry* dirEntry = findResType(type); + if (dirEntry) { + int count = 0; + for (int i = dirEntry->first_file_index; i < dirEntry->first_file_index + dirEntry->num_entries; i++) { + if (mFiles[i].isUnknownFlag1()) { + count++; + } + } + return count; + } + return 0; } /* 802B8BF0-802B8C50 .text countFile__10JKRArchiveCFPCc */ -void JKRArchive::countFile(const char*) const { - /* Nonmatching */ +u32 JKRArchive::countFile(const char* path) const { + SDIDirEntry* dirEntry; + if (*path == '/') { + path++; + + if (*path == '\0') + path = NULL; + dirEntry = findDirectory(path, 0); + } else { + dirEntry = findDirectory(path, sCurrentDirID); + } + + if (dirEntry) { + return dirEntry->num_entries; + } + + return 0; } /* 802B8C50-802B8CFC .text getFirstFile__10JKRArchiveCFPCc */ -void JKRArchive::getFirstFile(const char*) const { - /* Nonmatching */ +JKRFileFinder* JKRArchive::getFirstFile(const char* path) const { + SDIDirEntry* dirEntry; + if (*path == '/') { + path++; + + if (*path == '\0') + path = NULL; + dirEntry = findDirectory(path, 0); + } else { + dirEntry = findDirectory(path, sCurrentDirID); + } + + if (dirEntry) { + return new (JKRHeap::sSystemHeap, 0) JKRArcFinder((JKRArchive*)this, dirEntry->first_file_index, dirEntry->num_entries); + } + + return NULL; } /* 802B8CFC-802B8DC4 .text getFirstResource__10JKRArchiveCFUl */ -void JKRArchive::getFirstResource(unsigned long) const { - /* Nonmatching */ +JKRArcFinder* JKRArchive::getFirstResource(u32 type) const { + SDIDirEntry* dirEntry = findResType(type); + if (dirEntry && (getFileAttribute(dirEntry->first_file_index) & 1)) { + return new (JKRHeap::sSystemHeap, 0) JKRArcFinder((JKRArchive*)this, dirEntry->first_file_index, countResource(type)); + } + return new (JKRHeap::sSystemHeap, 0) JKRArcFinder((JKRArchive*)this, 0, 0); } /* 802B8DC4-802B8DFC .text getFileAttribute__10JKRArchiveCFUl */ -void JKRArchive::getFileAttribute(unsigned long) const { - /* Nonmatching */ +u32 JKRArchive::getFileAttribute(u32 index) const { + SDIFileEntry* fileEntry = findIdxResource(index); + if (fileEntry) { + return fileEntry->getFlags(); + } + + return 0; } diff --git a/src/JSystem/JKernel/JKRExpHeap.cpp b/src/JSystem/JKernel/JKRExpHeap.cpp index e09b03839..7cbc894e1 100644 --- a/src/JSystem/JKernel/JKRExpHeap.cpp +++ b/src/JSystem/JKernel/JKRExpHeap.cpp @@ -4,209 +4,1001 @@ // #include "JSystem/JKernel/JKRExpHeap.h" +#include "JSystem/JSupport/JSupport.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "JSystem/JUtility/JUTException.h" +#include "dolphin/os/OS.h" #include "dolphin/types.h" /* 802B1558-802B15D0 .text createRoot__10JKRExpHeapFib */ -void JKRExpHeap::createRoot(int, bool) { - /* Nonmatching */ +JKRExpHeap* JKRExpHeap::createRoot(int maxHeaps, bool errorFlag) { + JKRExpHeap* heap = NULL; + if (!sRootHeap) { + void* memory; + u32 memorySize; + initArena((char**)&memory, &memorySize, maxHeaps); + u8* start = (u8*)memory + OSRoundUp(sizeof(JKRExpHeap), 0x10); + u32 alignedSize = memorySize - OSRoundUp(sizeof(JKRExpHeap), 0x10); + heap = new (memory) JKRExpHeap(start, alignedSize, NULL, errorFlag); + sRootHeap = heap; + } + heap->field_0x6e = true; + return heap; } /* 802B15D0-802B16A4 .text create__10JKRExpHeapFUlP7JKRHeapb */ -void JKRExpHeap::create(unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRExpHeap* JKRExpHeap::create(u32 size, JKRHeap* parent, bool errorFlag) { + if (!parent) { + parent = sRootHeap; + } + + if (size == 0xffffffff) { + size = parent->getMaxAllocatableSize(0x10); + } + + u32 alignedSize = OSRoundDown(size, 0x10); + u32 expHeapSize = OSRoundUp(sizeof(JKRExpHeap), 0x10); + if (alignedSize < 0xa0) + return NULL; + + u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x10); + u8* dataPtr = (memory + expHeapSize); + if (!memory) { + return NULL; + } + + JKRExpHeap* newHeap = + new (memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag); + + if (newHeap == NULL) { + i_JKRFree(memory); + return NULL; + } + + newHeap->field_0x6e = false; + return newHeap; } /* 802B16A4-802B1728 .text do_destroy__10JKRExpHeapFv */ void JKRExpHeap::do_destroy() { - /* Nonmatching */ + if (!field_0x6e) { + JKRHeap* heap = mChildTree.getParent()->getObject(); + if (heap) { + this->~JKRExpHeap(); + JKRHeap::free(this, heap); + } + } else { + this->~JKRExpHeap(); + } } /* 802B1728-802B17B8 .text __ct__10JKRExpHeapFPvUlP7JKRHeapb */ -JKRExpHeap::JKRExpHeap(void*, unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRExpHeap::JKRExpHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag) : JKRHeap(data, size, parent, errorFlag) { + mAllocMode = 0; + mCurrentGroupId = 0xff; + mHeadFreeList = (CMemBlock*)data; + mTailFreeList = mHeadFreeList; + mHeadFreeList->initiate(NULL, NULL, size - sizeof(CMemBlock), 0, 0); + mHeadUsedList = NULL; + mTailUsedList = NULL; } /* 802B17B8-802B1820 .text __dt__10JKRExpHeapFv */ JKRExpHeap::~JKRExpHeap() { - /* Nonmatching */ + dispose(); } /* 802B1820-802B192C .text do_alloc__10JKRExpHeapFUli */ -void JKRExpHeap::do_alloc(unsigned long, int) { - /* Nonmatching */ +void* JKRExpHeap::do_alloc(u32 size, int alignment) { + void* ptr; + + lock(); + if (size < 4) { + size = 4; + } + + if (alignment >= 0) { + if (alignment <= 4) { + ptr = allocFromHead(size); + } else { + ptr = allocFromHead(size, alignment); + } + } else { + if (-alignment <= 4) { + ptr = allocFromTail(size); + } else { + ptr = allocFromTail(size, -alignment); + } + } + + if (ptr == NULL) { + JUTWarningConsole_f(":::cannot alloc memory (0x%x byte).\n", size); + if (mErrorFlag == true) { + callErrorHandler(this, size, alignment); + } + } + unlock(); + + return ptr; } +static u32 DBfoundSize; +static u32 DBfoundOffset; +static JKRExpHeap::CMemBlock* DBfoundBlock; +static JKRExpHeap::CMemBlock* DBnewFreeBlock; +static JKRExpHeap::CMemBlock* DBnewUsedBlock; + /* 802B192C-802B1B88 .text allocFromHead__10JKRExpHeapFUli */ -void JKRExpHeap::allocFromHead(unsigned long, int) { +// wrong register at end +void* JKRExpHeap::allocFromHead(u32 size, int align) { /* Nonmatching */ + u32 foundOffset; + int foundSize; + CMemBlock* newFreeBlock; + CMemBlock* newUsedBlock; + CMemBlock* foundBlock; + + size = ALIGN_NEXT(size, 4); + foundSize = -1; + foundOffset = 0; + foundBlock = NULL; + + for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + u32 offset = + ALIGN_PREV(align - 1 + (u32)block->getContent(), align) - (u32)block->getContent(); + if (block->size < size + offset) { + continue; + } + + if (foundSize <= (u32)block->size) { + continue; + } + + foundSize = block->size; + foundBlock = block; + foundOffset = offset; + if (mAllocMode != 0) { + break; + } + + u32 blockSize = block->size; + if (blockSize == size) { + break; + } + } + + DBfoundSize = foundSize; + DBfoundOffset = foundOffset; + DBfoundBlock = foundBlock; + + if (foundBlock) { + if (foundOffset >= sizeof(CMemBlock)) { + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + newUsedBlock = foundBlock->allocFore(foundOffset - sizeof(CMemBlock), 0, 0, 0, 0); + + if (newUsedBlock) { + newFreeBlock = newUsedBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + } else { + newFreeBlock = NULL; + } + + if (newFreeBlock) { + setFreeBlock(foundBlock, prev, newFreeBlock); + } else { + setFreeBlock(foundBlock, prev, next); + } + + if (newFreeBlock) { + setFreeBlock(newFreeBlock, foundBlock, next); + } + + appendUsedList(newUsedBlock); + DBnewFreeBlock = newFreeBlock; + DBnewUsedBlock = newUsedBlock; + return newUsedBlock->getContent(); + } else { + if (foundOffset != 0) { + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + removeFreeBlock(foundBlock); + newUsedBlock = (CMemBlock*)((u32)foundBlock + foundOffset); + newUsedBlock->size = foundBlock->size - foundOffset; + newFreeBlock = + newUsedBlock->allocFore(size, mCurrentGroupId, (u8)foundOffset, 0, 0); + if (newFreeBlock) { + setFreeBlock(newFreeBlock, prev, next); + } + appendUsedList(newUsedBlock); + return newUsedBlock->getContent(); + } else { + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + // Works but very fake match + /*size = (u32)foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + removeFreeBlock(foundBlock); + if (size) { + setFreeBlock((CMemBlock*)size, prev, next); + }*/ + newFreeBlock = foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + removeFreeBlock(foundBlock); + if (newFreeBlock) { + setFreeBlock(newFreeBlock, prev, next); + } + appendUsedList(foundBlock); + return foundBlock->getContent(); + } + } + } + + return NULL; } /* 802B1B88-802B1C6C .text allocFromHead__10JKRExpHeapFUl */ -void JKRExpHeap::allocFromHead(unsigned long) { - /* Nonmatching */ +void* JKRExpHeap::allocFromHead(u32 size) { + size = ALIGN_NEXT(size, 4); + s32 foundSize = -1; + CMemBlock* foundBlock = NULL; + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + if (block->getSize() < size) { + continue; + } + + if (foundSize <= block->getSize()) { + continue; + } + + foundSize = block->getSize(); + foundBlock = block; + if (mAllocMode != 0) { + break; + } + + if (foundSize == size) { + break; + } + } + + if (foundBlock) { + CMemBlock* newblock = foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + if (newblock) { + setFreeBlock(newblock, foundBlock->getPrevBlock(), foundBlock->getNextBlock()); + } else { + removeFreeBlock(foundBlock); + } + appendUsedList(foundBlock); + return foundBlock->getContent(); + } + return NULL; } /* 802B1C6C-802B1DCC .text allocFromTail__10JKRExpHeapFUli */ -void JKRExpHeap::allocFromTail(unsigned long, int) { - /* Nonmatching */ +void* JKRExpHeap::allocFromTail(u32 size, int align) { + u32 offset = 0; + CMemBlock* foundBlock = NULL; + CMemBlock* newBlock = NULL; + u32 usedSize; + u32 start; + + for (CMemBlock* block = mTailFreeList; block; block = block->mPrev) { + start = ALIGN_PREV((u32)block->getContent() + block->size - size, align); + usedSize = (u32)block->getContent() + block->size - start; + if (block->size >= usedSize) { + foundBlock = block; + offset = block->size - usedSize; + newBlock = (CMemBlock*)start - 1; + break; + } + } + + if (foundBlock != NULL) { + if (offset >= sizeof(CMemBlock)) { + newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, -0x80); + foundBlock->size = foundBlock->size - usedSize - sizeof(CMemBlock); + appendUsedList(newBlock); + return newBlock->getContent(); + } else { + if (offset != 0) { + removeFreeBlock(foundBlock); + newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, offset | 0x80); + appendUsedList(newBlock); + return newBlock->getContent(); + } else { + removeFreeBlock(foundBlock); + newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, -0x80); + appendUsedList(newBlock); + return newBlock->getContent(); + } + } + } + + return NULL; } /* 802B1DCC-802B1EA4 .text allocFromTail__10JKRExpHeapFUl */ -void JKRExpHeap::allocFromTail(unsigned long) { - /* Nonmatching */ +void* JKRExpHeap::allocFromTail(u32 size) { + u32 size2 = ALIGN_NEXT(size, 4); + CMemBlock* foundBlock = NULL; + for (CMemBlock* block = mTailFreeList; block; block = block->getPrevBlock()) { + if (block->getSize() >= size2) { + foundBlock = block; + break; + } + } + + if (foundBlock != NULL) { + CMemBlock* usedBlock = foundBlock->allocBack(size2, 0, 0, mCurrentGroupId, 0); + CMemBlock* freeBlock; + if (usedBlock) { + freeBlock = foundBlock; + } else { + removeFreeBlock(foundBlock); + usedBlock = foundBlock; + freeBlock = NULL; + } + + if (freeBlock) { + setFreeBlock(freeBlock, foundBlock->getPrevBlock(), foundBlock->getNextBlock()); + } + appendUsedList(usedBlock); + return usedBlock->getContent(); + } + return NULL; } /* 802B1EA4-802B1F44 .text do_free__10JKRExpHeapFPv */ -void JKRExpHeap::do_free(void*) { - /* Nonmatching */ +void JKRExpHeap::do_free(void* ptr) { + lock(); + if (getStartAddr() <= ptr && ptr <= getEndAddr()) { + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (block) { + block->free(this); + } + } else { + JUT_WARN(888, "free: memblock %x not in heap %x", ptr, this); + } + unlock(); } /* 802B1F44-802B1FC0 .text do_freeAll__10JKRExpHeapFv */ void JKRExpHeap::do_freeAll() { - /* Nonmatching */ + lock(); + JKRHeap::callAllDisposer(); + mHeadFreeList = (CMemBlock*)getStartAddr(); + mTailFreeList = mHeadFreeList; + mHeadFreeList->initiate(NULL, NULL, getSize() - 0x10, 0, 0); + mHeadUsedList = NULL; + mTailUsedList = NULL; + unlock(); } /* 802B1FC0-802B2048 .text do_freeTail__10JKRExpHeapFv */ void JKRExpHeap::do_freeTail() { - /* Nonmatching */ + lock(); + for (CMemBlock* block = mHeadUsedList; block != NULL;) { + if ((block->mFlags & 0x80) != 0) { + dispose(block + 1, block->size); + CMemBlock* temp = block->mNext; + block->free(this); + block = temp; + } else { + block = block->mNext; + } + } + unlock(); } /* 802B2048-802B2098 .text do_changeGroupID__10JKRExpHeapFUc */ -void JKRExpHeap::do_changeGroupID(unsigned char) { - /* Nonmatching */ +s32 JKRExpHeap::do_changeGroupID(u8 groupId) { + lock(); + u8 prev = mCurrentGroupId; + mCurrentGroupId = groupId; + unlock(); + return prev; } /* 802B2098-802B2244 .text do_resize__10JKRExpHeapFPvUl */ -void JKRExpHeap::do_resize(void*, unsigned long) { - /* Nonmatching */ +s32 JKRExpHeap::do_resize(void* ptr, u32 size) { + lock(); + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (block == NULL || ptr < mStart || mEnd < ptr) { + unlock(); + return -1; + } + + size = ALIGN_NEXT(size, 4); + if (size == block->size) { + unlock(); + return size; + } + + if (size > block->size) { + CMemBlock* foundBlock = NULL; + for (CMemBlock* freeBlock = mHeadFreeList; freeBlock; freeBlock = freeBlock->mNext) { + if (freeBlock == (CMemBlock*)((u32)(block + 1) + block->size)) { + foundBlock = freeBlock; + break; + } + } + + if (foundBlock == NULL) { + unlock(); + return -1; + } + + if (size > block->size + sizeof(CMemBlock) + foundBlock->size) { + unlock(); + return -1; + } + + removeFreeBlock(foundBlock); + block->size += foundBlock->size + sizeof(CMemBlock); + if (block->size - size > sizeof(CMemBlock)) { + CMemBlock* newBlock = block->allocFore(size, block->mGroupId, block->mFlags, 0, 0); + if (newBlock) { + recycleFreeBlock(newBlock); + } + } + } else { + if (block->size - size > sizeof(CMemBlock)) { + CMemBlock* freeBlock = block->allocFore(size, block->mGroupId, block->mFlags, 0, 0); + if (freeBlock) { + recycleFreeBlock(freeBlock); + } + } + } + + unlock(); + return block->size; } /* 802B2244-802B22C4 .text do_getSize__10JKRExpHeapFPv */ -void JKRExpHeap::do_getSize(void*) { - /* Nonmatching */ +s32 JKRExpHeap::do_getSize(void* ptr) { + lock(); + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (!block || ptr < getStartAddr() || getEndAddr() < ptr) { + unlock(); + return -1; + } + unlock(); + return block->getSize(); } /* 802B22C4-802B2330 .text do_getFreeSize__10JKRExpHeapFv */ -void JKRExpHeap::do_getFreeSize() { - /* Nonmatching */ +s32 JKRExpHeap::do_getFreeSize() { + lock(); + s32 size = 0; + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + if (size < (s32)block->getSize()) { + size = block->getSize(); + } + } + unlock(); + return size; } /* 802B2330-802B23A4 .text do_getMaxFreeBlock__10JKRExpHeapFv */ -void JKRExpHeap::do_getMaxFreeBlock() { - /* Nonmatching */ +void* JKRExpHeap::do_getMaxFreeBlock() { + lock(); + s32 size = 0; + CMemBlock* res = NULL; + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + if (size < (s32)block->getSize()) { + size = block->getSize(); + res = block; + } + } + unlock(); + return res; } /* 802B23A4-802B2408 .text do_getTotalFreeSize__10JKRExpHeapFv */ -void JKRExpHeap::do_getTotalFreeSize() { - /* Nonmatching */ +s32 JKRExpHeap::do_getTotalFreeSize() { + u32 size = 0; + lock(); + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + size += block->getSize(); + } + unlock(); + return size; } /* 802B2408-802B2484 .text getUsedSize__10JKRExpHeapCFUc */ -void JKRExpHeap::getUsedSize(unsigned char) const { - /* Nonmatching */ +s32 JKRExpHeap::getUsedSize(u8 groupId) const { + JKRExpHeap* this2 = const_cast(this); + this2->lock(); + u32 size = 0; + + for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) { + u8 blockGroupId = block->getGroupId(); + if (blockGroupId == groupId) { + size += block->getSize() + sizeof(CMemBlock); + } + } + + this2->unlock(); + return size; } /* 802B2484-802B24EC .text getTotalUsedSize__10JKRExpHeapCFv */ -void JKRExpHeap::getTotalUsedSize() const { - /* Nonmatching */ +s32 JKRExpHeap::getTotalUsedSize() const { + JKRExpHeap* this2 = const_cast(this); + this2->lock(); + u32 size = 0; + + for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) { + size += block->getSize() + sizeof(CMemBlock); + } + + this2->unlock(); + return size; +} + +static void dummy1() { + OSReport("newSize > 0"); + OSReport("Halt"); } /* 802B24EC-802B2584 .text appendUsedList__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::appendUsedList(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::appendUsedList(CMemBlock* newblock) { + if (!newblock) { + OSPanic(__FILE__, 1466, ":::ERROR! appendUsedList\n"); + } + + CMemBlock* block = mTailUsedList; + newblock->mMagic = 'HM'; + + if (block) { + block->mNext = newblock; + newblock->mPrev = block; + } else { + newblock->mPrev = NULL; + } + + mTailUsedList = newblock; + if (!mHeadUsedList) { + mHeadUsedList = newblock; + } + newblock->mNext = NULL; } /* 802B2584-802B25D0 .text setFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::setFreeBlock(JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::setFreeBlock(CMemBlock* block, CMemBlock* prev, CMemBlock* next) { + if (prev == NULL) { + mHeadFreeList = block; + block->mPrev = NULL; + } else { + prev->mNext = block; + block->mPrev = prev; + } + + if (next == NULL) { + mTailFreeList = block; + block->mNext = NULL; + } else { + next->mPrev = block; + block->mNext = next; + } + + block->mMagic = 0; } /* 802B25D0-802B2604 .text removeFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::removeFreeBlock(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::removeFreeBlock(CMemBlock* block) { + CMemBlock* prev = block->mPrev; + CMemBlock* next = block->mNext; + + if (prev == NULL) { + mHeadFreeList = next; + } else { + prev->mNext = next; + } + + if (next == NULL) { + mTailFreeList = prev; + } else { + next->mPrev = prev; + } } /* 802B2604-802B2638 .text removeUsedBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::removeUsedBlock(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::removeUsedBlock(CMemBlock* block) { + CMemBlock* prev = block->mPrev; + CMemBlock* next = block->mNext; + + if (prev == NULL) { + mHeadUsedList = next; + } else { + prev->mNext = next; + } + + if (next == NULL) { + mTailUsedList = prev; + } else { + next->mPrev = prev; + } } /* 802B2638-802B27D0 .text recycleFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::recycleFreeBlock(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::recycleFreeBlock(CMemBlock* block) { + JKRExpHeap::CMemBlock* newBlock = block; + int size = block->size; + void* blockEnd = (u8*)block + size; + block->mMagic = 0; + + if ((block->mFlags & 0x7f) != 0) { + newBlock = (CMemBlock*)((u8*)block - (block->mFlags & 0x7f)); + size += (block->mFlags & 0x7f); + blockEnd = (u8*)newBlock + size; + newBlock->mGroupId = 0; + newBlock->mFlags = 0; + newBlock->size = size; + } + + if (!mHeadFreeList) { + newBlock->initiate(NULL, NULL, size, 0, 0); + mHeadFreeList = newBlock; + mTailFreeList = newBlock; + setFreeBlock(newBlock, NULL, NULL); + return; + } + + if (mHeadFreeList >= blockEnd) { + newBlock->initiate(NULL, NULL, size, 0, 0); + setFreeBlock(newBlock, NULL, mHeadFreeList); + joinTwoBlocks(newBlock); + return; + } + + if (mTailFreeList <= newBlock) { + newBlock->initiate(NULL, NULL, size, 0, 0); + setFreeBlock(newBlock, mTailFreeList, NULL); + joinTwoBlocks(newBlock->mPrev); + return; + } + + for (CMemBlock* freeBlock = mHeadFreeList; freeBlock; freeBlock = freeBlock->mNext) { + if (freeBlock >= newBlock || newBlock >= freeBlock->mNext) { + continue; + } + newBlock->mNext = freeBlock->mNext; + newBlock->mPrev = freeBlock; + freeBlock->mNext = newBlock; + newBlock->mNext->mPrev = newBlock; + newBlock->mGroupId = 0; + joinTwoBlocks(newBlock); + joinTwoBlocks(freeBlock); + return; + } } /* 802B27D0-802B291C .text joinTwoBlocks__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::joinTwoBlocks(JKRExpHeap::CMemBlock*) { +// regalloc +void JKRExpHeap::joinTwoBlocks(CMemBlock* block) { /* Nonmatching */ + u32 endAddr = (u32)(block + 1) + block->size; + CMemBlock* next = block->mNext; + u32 nextAddr = (u32)next - (next->mFlags & 0x7f); + if (endAddr > nextAddr) { + JUTWarningConsole_f(":::Heap may be broken. (block = %x)", block); + OSReport(":::block = %x\n", block); + OSReport(":::joinTwoBlocks [%x %x %x][%x %x %x]\n", block, block->mFlags, block->size, block->mNext, block->mNext->mFlags, block->mNext->size); + OSReport(":::: endAddr = %x\n", endAddr); + OSReport(":::: nextAddr = %x\n", nextAddr); + JKRGetCurrentHeap()->dump(); + OSPanic(__FILE__, 1718, ":::: Bad Block\n"); + } + + if (endAddr == nextAddr) { + block->size = next->size + sizeof(CMemBlock) + next->getAlignment() + block->size; + setFreeBlock(block, block->mPrev, next->mNext); + } } /* 802B291C-802B2B44 .text check__10JKRExpHeapFv */ -void JKRExpHeap::check() { - /* Nonmatching */ +bool JKRExpHeap::check() { + lock(); + int totalBytes = 0; + bool ok = true; + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) { + if (!block->isValid()) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad heap signature. (%c%c)\n", block, + JSUHiByte(block->mMagic), JSULoByte(block->mMagic)); + } + + if (block->mNext) { + if (!block->mNext->isValid()) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad next pointer (%08x)\nabort\n", block, + block->mNext); + break; + } + if (block->mNext->mPrev != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, + block->mNext->mPrev); + } + } else { + if (mTailUsedList != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block, + mTailUsedList); + } + } + totalBytes += sizeof(CMemBlock) + block->size + block->getAlignment(); + } + + for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + totalBytes += block->size + sizeof(CMemBlock); + if (block->mNext) { + if (block->mNext->mPrev != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, + block->mNext->mPrev); + } + + if ((u32)block + block->size + sizeof(CMemBlock) > (u32)block->mNext) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad block size (%08x)\n", block, block->size); + } + } else { + if (mTailFreeList != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block, + mTailFreeList); + } + } + } + + if (totalBytes != mSize) { + ok = false; + JUTWarningConsole_f(":::bad total memory block size (%08X, %08X)\n", mSize, totalBytes); + } + + if (!ok) { + JUTWarningConsole(":::there is some error in this heap!\n"); + } + + unlock(); + return ok; } /* 802B2B44-802B2B48 .text do_freeFill__10JKRExpHeapFv */ -void JKRExpHeap::do_freeFill() { - /* Nonmatching */ -} +void JKRExpHeap::do_freeFill() {} /* 802B2B48-802B2D5C .text dump__10JKRExpHeapFv */ -void JKRExpHeap::dump() { - /* Nonmatching */ +bool JKRExpHeap::dump() { + lock(); + bool result = check(); + u32 usedBytes = 0; + u32 usedCount = 0; + u32 freeCount = 0; + + JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n"); + JUTReportConsole("(Used Blocks)\n"); + if (!mHeadUsedList) { + JUTReportConsole(" NONE\n"); + } + + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) { + if (!block->isValid()) { + JUTReportConsole_f("xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", + block); + break; + } + + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", + block->_isTempMemBlock() ? " temp" : "alloc", block->getContent(), + block->size, block->mGroupId, block->getAlignment(), block->mPrev, + block->mNext); + usedBytes += sizeof(CMemBlock) + block->size + block->getAlignment(); + usedCount++; + } + + JUTReportConsole("(Free Blocks)\n"); + if (!mHeadFreeList) { + JUTReportConsole(" NONE\n"); + } + + for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), + block->size, block->mGroupId, block->getAlignment(), block->mPrev, + block->mNext); + freeCount++; + } + + float percent = ((float)usedBytes / (float)mSize) * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", usedBytes, mSize, percent, + usedCount, freeCount); + unlock(); + return result; } /* 802B2D5C-802B2F5C .text dump_sort_by_address__10JKRExpHeapFv */ -void JKRExpHeap::dump_sort_by_address() { +// regalloc, stack +bool JKRExpHeap::dump_sort_by_address() { /* Nonmatching */ + lock(); + bool result = check(); + u32 usedBytes = 0; + u32 usedCount = 0; + u32 freeCount = 0; + JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n"); + + CMemBlock* block; + for (CMemBlock* var1 = NULL; true; var1 = block) { + CMemBlock* block = (CMemBlock*)0xffffffff; + for (CMemBlock* iterBlock = mHeadFreeList; iterBlock; iterBlock = iterBlock->getNextBlock()) { + if (var1 < iterBlock && iterBlock < block) { + block = iterBlock; + } + } + + for (CMemBlock* iterBlock = mHeadUsedList; iterBlock; iterBlock = iterBlock->getNextBlock()) { + if (var1 < iterBlock && iterBlock < block) { + block = iterBlock; + } + } + + if (block == (CMemBlock*)0xffffffff) { + break; + } + + if (block->mMagic == 0) { + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), block->getSize(), block->getGroupId(), block->getAlignment(), block->getPrevBlock(), block->getNextBlock()); + freeCount += 1; + continue; + } + + if (!block->isValid()) { + JUTReportConsole_f("xxxxx %08x: -------- --- --- (-------- --------)\nabort\n"); + break; + } + + int offset = block->getAlignment(); + void* content = block->getContent(); + const char* type = block->_isTempMemBlock() ? " temp" : "alloc"; + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", type, content, block->getSize(), + block->getGroupId(), offset, block->getPrevBlock(), block->getNextBlock()); + usedBytes += sizeof(CMemBlock) + block->size + block->getAlignment(); + usedCount++; + } + + float percent = ((float)usedBytes / (float)mSize) * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", usedBytes, mSize, percent, + usedCount, freeCount); + unlock(); + return result; } /* 802B2F5C-802B2F7C .text dump_sort__10JKRExpHeapFv */ -void JKRExpHeap::dump_sort() { - /* Nonmatching */ +bool JKRExpHeap::dump_sort() { + return dump_sort_by_address(); } /* 802B2F7C-802B2F9C .text initiate__Q210JKRExpHeap9CMemBlockFPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlockUlUcUc */ -void JKRExpHeap::CMemBlock::initiate(JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*, unsigned long, unsigned char, unsigned char) { - /* Nonmatching */ +void JKRExpHeap::CMemBlock::initiate(CMemBlock* prev, CMemBlock* next, u32 size, u8 groupId, u8 alignment) { + mMagic = 'HM'; + mFlags = alignment; + mGroupId = groupId; + this->size = size; + mPrev = prev; + mNext = next; } /* 802B2F9C-802B2FE0 .text allocFore__Q210JKRExpHeap9CMemBlockFUlUcUcUcUc */ -void JKRExpHeap::CMemBlock::allocFore(unsigned long, unsigned char, unsigned char, unsigned char, unsigned char) { - /* Nonmatching */ +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocFore(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) { + CMemBlock* block = NULL; + mGroupId = groupId1; + mFlags = alignment1; + if (getSize() >= size + sizeof(CMemBlock)) { + block = (CMemBlock*)(size + (u32)this); + block[1].mGroupId = groupId2; + block[1].mFlags = alignment2; + block[1].size = this->size - (size + sizeof(CMemBlock)); + this->size = size; + block = block + 1; + } + return block; } /* 802B2FE0-802B3038 .text allocBack__Q210JKRExpHeap9CMemBlockFUlUcUcUcUc */ -void JKRExpHeap::CMemBlock::allocBack(unsigned long, unsigned char, unsigned char, unsigned char, unsigned char) { - /* Nonmatching */ +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocBack(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) { + CMemBlock* newblock = NULL; + if (getSize() >= size + sizeof(CMemBlock)) { + newblock = (CMemBlock*)((u32)this + getSize() - size); + newblock->mGroupId = groupId2; + newblock->mFlags = alignment2 | 0x80; + newblock->size = size; + mGroupId = groupId1; + mFlags = alignment1; + this->size -= size + sizeof(CMemBlock); + } else { + mGroupId = groupId2; + mFlags = 0x80; + } + return newblock; } /* 802B3038-802B3088 .text free__Q210JKRExpHeap9CMemBlockFP10JKRExpHeap */ -void JKRExpHeap::CMemBlock::free(JKRExpHeap*) { - /* Nonmatching */ +int JKRExpHeap::CMemBlock::free(JKRExpHeap* heap) { + heap->removeUsedBlock(this); + heap->recycleFreeBlock(this); + return 0; } /* 802B3088-802B30A4 .text getHeapBlock__Q210JKRExpHeap9CMemBlockFPv */ -void JKRExpHeap::CMemBlock::getHeapBlock(void*) { - /* Nonmatching */ +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::getHeapBlock(void* ptr) { + if (ptr) { + CMemBlock* block = (CMemBlock*)ptr - 1; + if (block->isValid()) { + return block; + } + } + return NULL; +} + +static void dummy2() { + OSReport("+---------------JKRExpHeap\n"); + OSReport("| Align Group size ( prev , next )\n"); + OSReport("| ---- FreeFirst\n"); + OSReport("| %08x "); + OSReport("%2x %3d %6x (%08x %08x)\n"); + OSReport("| ---- FreeLast\n"); + OSReport("| ---- UsedFirst\n"); + OSReport("| ---- UsedLast\n"); + OSReport("+---------------End\n"); } /* 802B30A4-802B31D4 .text state_register__10JKRExpHeapCFPQ27JKRHeap6TStateUl */ -void JKRExpHeap::state_register(JKRHeap::TState*, unsigned long) const { - /* Nonmatching */ +void JKRExpHeap::state_register(TState* p, u32 param_1) const { + JUT_ASSERT(2423, p != 0); + JUT_ASSERT(2424, p->getHeap() == this); + p->mId = param_1; + if (param_1 <= 0xff) { + p->mUsedSize = getUsedSize(param_1); + } else { + s32 freeSize = const_cast(this)->getTotalFreeSize(); + p->mUsedSize = getSize() - freeSize; + } + + u32 checkCode = 0; + for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) { + if (param_1 <= 0xff) { + u8 groupId = block->getGroupId(); + if (groupId == param_1) { + checkCode += (u32)block * 3; + } + } else { + checkCode += (u32)block * 3; + } + } + p->mCheckCode = checkCode; } /* 802B31D4-802B327C .text state_compare__10JKRExpHeapCFRCQ27JKRHeap6TStateRCQ27JKRHeap6TState */ -void JKRExpHeap::state_compare(const JKRHeap::TState&, const JKRHeap::TState&) const { - /* Nonmatching */ +bool JKRExpHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const { + JUT_ASSERT(2471, r1.getHeap() == r2.getHeap()); + bool result = true; + if (r1.mCheckCode != r2.mCheckCode) { + result = false; + } + + if (r1.mUsedSize != r2.mUsedSize) { + result = false; + } + + return result; } /* 802B327C-802B3288 .text getHeapType__10JKRExpHeapFv */ -void JKRExpHeap::getHeapType() { - /* Nonmatching */ +u32 JKRExpHeap::getHeapType() { + return 'EXPH'; } /* 802B3288-802B3290 .text do_getCurrentGroupId__10JKRExpHeapFv */ -void JKRExpHeap::do_getCurrentGroupId() { - /* Nonmatching */ +u8 JKRExpHeap::do_getCurrentGroupId() { + return mCurrentGroupId; } diff --git a/src/JSystem/JKernel/JKRFileLoader.cpp b/src/JSystem/JKernel/JKRFileLoader.cpp index a3d027f31..397d3e3fc 100644 --- a/src/JSystem/JKernel/JKRFileLoader.cpp +++ b/src/JSystem/JKernel/JKRFileLoader.cpp @@ -4,54 +4,157 @@ // #include "JSystem/JKernel/JKRFileLoader.h" -#include "dolphin/types.h" +#include "MSL_C/string.h" +#include "MSL_C/MSL_Common/Src/ctype.h" +#include "global.h" + +JKRFileLoader* JKRFileLoader::sCurrentVolume; +JSUList JKRFileLoader::sVolumeList; /* 802B6770-802B67C8 .text __ct__13JKRFileLoaderFv */ -JKRFileLoader::JKRFileLoader() { - /* Nonmatching */ +JKRFileLoader::JKRFileLoader() : mFileLoaderLink(this) { + mVolumeName = NULL; + mVolumeType = 0; + mMountCount = 0; } /* 802B67C8-802B6854 .text __dt__13JKRFileLoaderFv */ JKRFileLoader::~JKRFileLoader() { - /* Nonmatching */ + if (getCurrentVolume() == this) { + setCurrentVolume(NULL); + } } /* 802B6854-802B68A4 .text unmount__13JKRFileLoaderFv */ void JKRFileLoader::unmount() { - /* Nonmatching */ + s32 count = mMountCount; + if (mMountCount != 0) { + count--; + mMountCount = count; + if (count == 0) { + delete this; + } + } } /* 802B68A4-802B68F0 .text getGlbResource__13JKRFileLoaderFPCc */ -void JKRFileLoader::getGlbResource(const char*) { - /* Nonmatching */ +void* JKRFileLoader::getGlbResource(const char* name) { + const char* name_reference[1]; + name_reference[0] = name; + + JKRFileLoader* fileLoader = findVolume(name_reference); + void* resource; + if (fileLoader == NULL) { + resource = NULL; + } else { + resource = fileLoader->getResource(name_reference[0]); + } + + return resource; } /* 802B68F0-802B6988 .text getGlbResource__13JKRFileLoaderFPCcP13JKRFileLoader */ -void JKRFileLoader::getGlbResource(const char*, JKRFileLoader*) { - /* Nonmatching */ +void* JKRFileLoader::getGlbResource(const char* name, JKRFileLoader* fileLoader) { + void* resource = NULL; + if (fileLoader) { + return fileLoader->getResource(0, name); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + resource = iterator->getResource(0, name); + if (resource) + break; + } + return resource; } /* 802B6988-802B6A20 .text removeResource__13JKRFileLoaderFPvP13JKRFileLoader */ -void JKRFileLoader::removeResource(void*, JKRFileLoader*) { - /* Nonmatching */ +bool JKRFileLoader::removeResource(void* resource, JKRFileLoader* fileLoader) { + if (fileLoader) { + return fileLoader->removeResource(resource); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (iterator->removeResource(resource)) { + return true; + } + } + + return false; } /* 802B6A20-802B6AB8 .text detachResource__13JKRFileLoaderFPvP13JKRFileLoader */ -void JKRFileLoader::detachResource(void*, JKRFileLoader*) { - /* Nonmatching */ +bool JKRFileLoader::detachResource(void* resource, JKRFileLoader* fileLoader) { + if (fileLoader) { + return fileLoader->detachResource(resource); + } + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (iterator->detachResource(resource)) { + return true; + } + } + + return false; } /* 802B6AB8-802B6B44 .text findVolume__13JKRFileLoaderFPPCc */ -void JKRFileLoader::findVolume(const char**) { - /* Nonmatching */ +JKRFileLoader* JKRFileLoader::findVolume(const char** volumeName) { + if (*volumeName[0] != '/') { + return getCurrentVolume(); + } + + char volumeNameBuffer[0x101]; + *volumeName = fetchVolumeName(volumeNameBuffer, ARRAY_SIZE(volumeNameBuffer), *volumeName); + + JSUList& volumeList = getVolumeList(); + JSUListIterator iterator; + for (iterator = volumeList.getFirst(); iterator != volumeList.getEnd(); ++iterator) { + if (strcmp(volumeNameBuffer, iterator->mVolumeName) == 0) { + return iterator.getObject(); + } + } + + return NULL; } +static char rootPath[2] = "/"; + /* 802B6B44-802B6C20 .text fetchVolumeName__13JKRFileLoaderFPclPCc */ -void JKRFileLoader::fetchVolumeName(char*, long, const char*) { - /* Nonmatching */ -} +const char* JKRFileLoader::fetchVolumeName(char* buffer, long bufferSize, const char* path) { + if (strcmp(path, "/") == 0) { + strcpy(buffer, rootPath); + return rootPath; + } -/* 802B6C64-802B6CB8 .text __dt__24JSUList<13JKRFileLoader>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ + path++; + while (*path != 0 && *path != '/') { + if (1 < bufferSize) { + int lower_char; + int ch = (int)*path; + if (ch == -1) { + lower_char = -1; + } else { + lower_char = __lower_map[ch & 0xFF]; + } + + *buffer = lower_char; + buffer++; + bufferSize--; + } + path++; + } + + *buffer = '\0'; + if (*path == '\0') { + path = rootPath; + } + + return path; } diff --git a/src/JSystem/JKernel/JKRThread.cpp b/src/JSystem/JKernel/JKRThread.cpp index cf539ab90..a8465beca 100644 --- a/src/JSystem/JKernel/JKRThread.cpp +++ b/src/JSystem/JKernel/JKRThread.cpp @@ -4,54 +4,135 @@ // #include "JSystem/JKernel/JKRThread.h" +#include "JSystem/JUtility/JUTAssert.h" #include "dolphin/types.h" +JSUList JKRThread::sThreadList; +JKRThreadSwitch* JKRThreadSwitch::sManager; +OSThread* preEnd; +JKRThreadSwitch_PreCallback JKRThreadSwitch::mUserPreCallback; +JKRThreadSwitch_PostCallback JKRThreadSwitch::mUserPostCallback; + /* 802B3D1C-802B3E38 .text __ct__9JKRThreadFUlii */ -JKRThread::JKRThread(unsigned long, int, int) { - /* Nonmatching */ +JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this) { + mHeap = JKRHeap::findFromRoot(this); + if (mHeap == NULL) { + mHeap = JKRGetSystemHeap(); + } + + mStackSize = stack_size & 0xffffffe0; + mStackMemory = JKRAllocFromHeap(mHeap, mStackSize, 0x20); + mThreadRecord = (OSThread*)JKRAllocFromHeap(mHeap, sizeof(OSThread), 0x20); + + void* stackBase = (void*)((int)mStackMemory + mStackSize); + OSCreateThread(mThreadRecord, start, this, stackBase, mStackSize, param_3, 1); + + mMessageCount = message_count; + mMessages = (OSMessage*)JKRAllocFromHeap(mHeap, mMessageCount * sizeof(OSMessage), 0); + + OSInitMessageQueue(&mMessageQueue, mMessages, mMessageCount); + getList().append(&mThreadListLink); + + mCurrentHeap = NULL; + mCurrentHeapError = NULL; } /* 802B3E38-802B3EFC .text __ct__9JKRThreadFP8OSThreadi */ -JKRThread::JKRThread(OSThread*, int) { - /* Nonmatching */ +JKRThread::JKRThread(OSThread* thread, int message_count) : mThreadListLink(this) { + mHeap = NULL; + mThreadRecord = thread; + mStackSize = (u32)thread->stack_end - (u32)thread->stack_base; + mStackMemory = thread->stack_base; + + mMessageCount = message_count; + mMessages = (OSMessage*)JKRGetSystemHeap()->alloc(mMessageCount * sizeof(OSMessage), 4); + + OSInitMessageQueue(&mMessageQueue, mMessages, mMessageCount); + getList().append(&mThreadListLink); + + mCurrentHeap = NULL; + mCurrentHeapError = NULL; } /* 802B3EFC-802B3FD4 .text __dt__9JKRThreadFv */ JKRThread::~JKRThread() { - /* Nonmatching */ + getList().remove(&mThreadListLink); + + if (mHeap) { + BOOL result = OSIsThreadTerminated(mThreadRecord); + if (result == FALSE) { + OSDetachThread(mThreadRecord); + OSCancelThread(mThreadRecord); + } + JKRFreeToHeap(mHeap, mStackMemory); + JKRFreeToHeap(mHeap, mThreadRecord); + } + i_JKRFree(mMessages); } /* 802B3FD4-802B4000 .text start__9JKRThreadFPv */ -void JKRThread::start(void*) { - /* Nonmatching */ +void* JKRThread::start(void* param) { + JKRThread* thread = (JKRThread*)param; + return thread->run(); } /* 802B4000-802B4050 .text __ct__15JKRThreadSwitchFP7JKRHeap */ -JKRThreadSwitch::JKRThreadSwitch(JKRHeap*) { - /* Nonmatching */ +JKRThreadSwitch::JKRThreadSwitch(JKRHeap* param_0) { + mHeap = param_0; + OSSetSwitchThreadCallback(JKRThreadSwitch::callback); + mSetNextHeap = true; } /* 802B4050-802B40EC .text createManager__15JKRThreadSwitchFP7JKRHeap */ -void JKRThreadSwitch::createManager(JKRHeap*) { - /* Nonmatching */ +JKRThreadSwitch* JKRThreadSwitch::createManager(JKRHeap* heap) { + JUT_ASSERT(184, sManager == 0); + + if (!heap) { + heap = JKRGetCurrentHeap(); + } + + sManager = new (heap, 0) JKRThreadSwitch(heap); + return sManager; } /* 802B40EC-802B41DC .text callback__15JKRThreadSwitchFP8OSThreadP8OSThread */ -void JKRThreadSwitch::callback(OSThread*, OSThread*) { - /* Nonmatching */ +void JKRThreadSwitch::callback(OSThread* current, OSThread* next) { + if (mUserPreCallback) { + (*mUserPreCallback)(current, next); + } + + if (!current && !next) { + preEnd = current; + current = NULL; + } + + if (!current && !next) { + current = preEnd; + preEnd = NULL; + } + + JSUList& threadList = JKRThread::getList(); + JSUListIterator iterator; + for (iterator = threadList.getFirst(); iterator != threadList.getEnd(); ++iterator) { + JKRThread* thread = iterator.getObject(); + + if (thread->getThreadRecord() == current) { + thread->setCurrentHeap(JKRHeap::getCurrentHeap()); + } + + if (thread->getThreadRecord() == next) { + if (sManager->mSetNextHeap) { + thread->getCurrentHeap()->becomeCurrentHeap(); + } + } + } + + if (mUserPostCallback) { + (*mUserPostCallback)(current, next); + } } -/* 802B41DC-802B41E4 .text run__9JKRThreadFv */ -void JKRThread::run() { - /* Nonmatching */ -} - -/* 802B41E4-802B422C .text __dt__15JKRThreadSwitchFv */ -JKRThreadSwitch::~JKRThreadSwitch() { - /* Nonmatching */ -} - -/* 802B4270-802B42C4 .text __dt__19JSUList<9JKRThread>Fv */ -JSUList::~JSUList() { - /* Nonmatching */ -} +static void dummy() { + OSReport("Cannot create JKRTask Manager."); + OSReport("sManager != 0"); +} \ No newline at end of file