diff --git a/include/JSystem/JKernel/JKRArchive.h b/include/JSystem/JKernel/JKRArchive.h index 2a2212efb5..c9cdd97f72 100644 --- a/include/JSystem/JKernel/JKRArchive.h +++ b/include/JSystem/JKernel/JKRArchive.h @@ -51,6 +51,12 @@ inline u16 read_big_endian_u16(void* ptr) { extern u32 sCurrentDirID__10JKRArchive; // JKRArchive::sCurrentDirID +#if TARGET_PC +#define JKAR_DATA(entry) getFileDataPointer(entry->index) +#else +#define JKAR_DATA(entry) entry->data +#endif + /** * @ingroup jsystem-jkernel * @@ -78,7 +84,16 @@ public: BE(u32) type_flags_and_name_offset; BE(u32) data_offset; BE(u32) data_size; +#if TARGET_PC + // Yes, they store the data pointer in the datastructure that's directly loaded from + // archive files. + // We can't expand this struct to fit a 64-bit pointer, so instead + // we'll need to store this data in a separate array. + // Store the *index* of this entry (!= file_id), so we can look up the real pointer easily. + u32 index; +#else void* data; +#endif u32 getNameOffset() const { return type_flags_and_name_offset & 0xFFFFFF; } u16 getNameHash() const { return name_hash; } @@ -131,6 +146,11 @@ protected: JKRArchive(); JKRArchive(s32, EMountMode); +#if TARGET_PC + void*& getFileDataPointer(int idx) const; + void initFileDataPointers(); +#endif + public: bool getDirEntry(SDirEntry*, u32) const; void* getIdxResource(u32); @@ -189,6 +209,10 @@ public: /* 0x50 */ s32* mExpandedSize; /* 0x54 */ const char* mStringTable; +#if TARGET_PC + void** mFileData; +#endif + protected: /* 0x58 */ u32 field_0x58; /* 0x5C */ JKRCompression mCompression; diff --git a/include/JSystem/JKernel/JKRCompArchive.h b/include/JSystem/JKernel/JKRCompArchive.h index d5eb60448b..dd6dc5e1fc 100644 --- a/include/JSystem/JKernel/JKRCompArchive.h +++ b/include/JSystem/JKernel/JKRCompArchive.h @@ -28,7 +28,7 @@ public: private: /* 0x00 */ // vtable /* 0x04 */ // JKRArchive - /* 0x64 */ int field_0x64; + /* 0x64 */ intptr_t field_0x64; /* 0x68 */ JKRAramBlock* mAramPart; /* 0x6C */ int field_0x6c; /* 0x70 */ JKRDvdFile* mDvdFile; diff --git a/src/JSystem/JKernel/JKRAramArchive.cpp b/src/JSystem/JKernel/JKRAramArchive.cpp index 811978caa0..f8818c7eca 100644 --- a/src/JSystem/JKernel/JKRAramArchive.cpp +++ b/src/JSystem/JKernel/JKRAramArchive.cpp @@ -31,8 +31,8 @@ JKRAramArchive::~JKRAramArchive() { if (mArcInfoBlock != NULL) { SDIFileEntry* entry = mFiles; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (entry->data != NULL) { - JKRFreeToHeap(mHeap, entry->data); + if (JKAR_DATA(entry) != NULL) { + JKRFreeToHeap(mHeap, JKAR_DATA(entry)); } entry++; } @@ -135,6 +135,9 @@ bool JKRAramArchive::open(s32 entryNum) { mFiles = (SDIFileEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->file_entry_offset); mStringTable = (char*)((u8*)mArcInfoBlock + mArcInfoBlock->string_table_offset); mExpandedSize = NULL; +#if TARGET_PC + initFileDataPointers(); +#endif u8 compressedFiles = 0; // maybe a check for if the last file is compressed? @@ -199,7 +202,7 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) { } JKRCompression compression = JKRConvertAttrToCompressionType(u8(pEntry->type_flags_and_name_offset >> 24)); - if (pEntry->data == NULL) { + if (JKAR_DATA(pEntry) == NULL) { u32 size = JKRAramArchive::fetchResource_subroutine( pEntry->data_offset + mBlock->getAddress(), pEntry->data_size, mHeap, compression, &outBuf); @@ -209,7 +212,7 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) { return NULL; } - pEntry->data = outBuf; + JKAR_DATA(pEntry) = outBuf; if (compression == COMPRESSION_YAZ0) { this->setExpandSize(pEntry, *pOutSize); } @@ -221,7 +224,7 @@ void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) { } } - return pEntry->data; + return JKAR_DATA(pEntry); } void* JKRAramArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* pEntry, @@ -233,7 +236,7 @@ void* JKRAramArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* } JKRCompression compression = JKRConvertAttrToCompressionType(u8(pEntry->type_flags_and_name_offset >> 24)); - if (pEntry->data == NULL) { + if (JKAR_DATA(pEntry) == NULL) { bufferSize = (s32)ALIGN_PREV(bufferSize, 0x20); size = JKRAramArchive::fetchResource_subroutine(pEntry->data_offset + mBlock->getAddress(), size, (u8*)buffer, bufferSize, compression); @@ -247,7 +250,7 @@ void* JKRAramArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* if (size > bufferSize) { size = bufferSize; } - JKRHeap::copyMemory(buffer, pEntry->data, size); + JKRHeap::copyMemory(buffer, JKAR_DATA(pEntry), size); } if (resourceSize != NULL) { diff --git a/src/JSystem/JKernel/JKRArchivePri.cpp b/src/JSystem/JKernel/JKRArchivePri.cpp index 375e297c37..21ad688a44 100644 --- a/src/JSystem/JKernel/JKRArchivePri.cpp +++ b/src/JSystem/JKernel/JKRArchivePri.cpp @@ -5,6 +5,10 @@ #include #include +#if TARGET_PC +#include +#endif + u32 JKRArchive::sCurrentDirID; JKRArchive::JKRArchive() { @@ -30,7 +34,14 @@ JKRArchive::JKRArchive(s32 entryNumber, JKRArchive::EMountMode mountMode) { } } -JKRArchive::~JKRArchive() {} +JKRArchive::~JKRArchive() { +#if TARGET_PC + if (mFileData != nullptr) { + mHeap->free(mFileData); + mFileData = nullptr; + } +#endif +} bool JKRArchive::isSameName(JKRArchive::CArcName& name, u32 nameOffset, u16 nameHash) const { u16 hash = name.getHash(); @@ -143,7 +154,7 @@ JKRArchive::SDIFileEntry* JKRArchive::findNameResource(const char* name) const { JKRArchive::SDIFileEntry* JKRArchive::findPtrResource(const void* resource) const { SDIFileEntry* fileEntry = mFiles; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntry->data == resource) { + if (JKAR_DATA(fileEntry) == resource) { return fileEntry; } fileEntry++; @@ -225,3 +236,31 @@ u32 JKRArchive::getExpandSize(SDIFileEntry* fileEntry) const { return mExpandedSize[index]; } + +#if TARGET_PC +void*& JKRArchive::getFileDataPointer(int idx) const { + assert(mArcInfoBlock); + assert(idx < mArcInfoBlock->num_file_entries); + assert(mFileData); + + return mFileData[idx]; +} + +void JKRArchive::initFileDataPointers() { + assert(mArcInfoBlock); + assert(mFiles); + + if (mFileData != nullptr) { + mHeap->free(mFileData); + } + + mFileData = static_cast( + mHeap->alloc(mArcInfoBlock->num_file_entries * sizeof(void*), alignof(void*))); + + memset(mFileData, 0, mArcInfoBlock->num_file_entries * sizeof(void*)); + + for (u32 i = 0; i < mArcInfoBlock->num_file_entries; i++) { + mFiles[i].index = i; + } +} +#endif \ No newline at end of file diff --git a/src/JSystem/JKernel/JKRArchivePub.cpp b/src/JSystem/JKernel/JKRArchivePub.cpp index 1d7f2accba..912fb16c6b 100644 --- a/src/JSystem/JKernel/JKRArchivePub.cpp +++ b/src/JSystem/JKernel/JKRArchivePub.cpp @@ -248,9 +248,9 @@ void JKRArchive::removeResourceAll() { if (mArcInfoBlock && mMountMode != MOUNT_MEM) { SDIFileEntry* fileEntry = mFiles; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntry->data) { - JKRFreeToHeap(mHeap, fileEntry->data); - fileEntry->data = NULL; + if (JKAR_DATA(fileEntry)) { + JKRFreeToHeap(mHeap, JKAR_DATA(fileEntry)); + JKAR_DATA(fileEntry) = NULL; } fileEntry++; } @@ -263,7 +263,7 @@ bool JKRArchive::removeResource(void* resource) { if (fileEntry == NULL) return false; - fileEntry->data = NULL; + JKAR_DATA(fileEntry) = NULL; JKRFreeToHeap(mHeap, resource); return true; } @@ -274,7 +274,7 @@ bool JKRArchive::detachResource(void* resource) { if (fileEntry == NULL) return false; - fileEntry->data = NULL; + JKAR_DATA(fileEntry) = NULL; return true; } diff --git a/src/JSystem/JKernel/JKRCompArchive.cpp b/src/JSystem/JKernel/JKRCompArchive.cpp index 8a1577f592..7c5217684b 100644 --- a/src/JSystem/JKernel/JKRCompArchive.cpp +++ b/src/JSystem/JKernel/JKRCompArchive.cpp @@ -33,8 +33,8 @@ JKRCompArchive::~JKRCompArchive() { SDIFileEntry* file = mFiles; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { u32 flags = file->type_flags_and_name_offset >> 24; - if ((flags & 16) == 0 && file->data != NULL) { - JKRFreeToHeap(mHeap, file->data); + if ((flags & 16) == 0 && JKAR_DATA(file) != NULL) { + JKRFreeToHeap(mHeap, JKAR_DATA(file)); } file++; @@ -176,6 +176,11 @@ bool JKRCompArchive::open(s32 entryNum) { field_0x6c = arcHeader->header_length + arcHeader->file_data_offset; break; } + +#if TARGET_PC + initFileDataPointers(); +#endif + mExpandedSize = NULL; u8 compressedFiles = 0; SDIFileEntry *fileEntry = mFiles; @@ -229,17 +234,17 @@ void* JKRCompArchive::fetchResource(SDIFileEntry *fileEntry, u32 *pSize) { pSize = &ptrSize; // this makes barely any sense but ok } - if (fileEntry->data == NULL) { + if (JKAR_DATA(fileEntry) == NULL) { u32 flag = fileEntry->type_flags_and_name_offset >> 0x18; if(flag & 0x10) { - fileEntry->data = (void *)(field_0x64 + fileEntry->data_offset); + JKAR_DATA(fileEntry) = (void *)(field_0x64 + fileEntry->data_offset); *pSize = size; } else if (flag & 0x20) { u8 *data; size = JKRAramArchive::fetchResource_subroutine(fileEntry->data_offset + mAramPart->getAddress() - mSizeOfMemPart, size, mHeap, compression, &data); *pSize = size; - fileEntry->data = data; + JKAR_DATA(fileEntry) = data; if(compression == COMPRESSION_YAZ0) { setExpandSize(fileEntry, *pSize); } @@ -250,7 +255,7 @@ void* JKRCompArchive::fetchResource(SDIFileEntry *fileEntry, u32 *pSize) { if (pSize != NULL) { *pSize = resSize; } - fileEntry->data = data; + JKAR_DATA(fileEntry) = data; if (compression == COMPRESSION_YAZ0) { setExpandSize(fileEntry, *pSize); } @@ -261,7 +266,7 @@ void* JKRCompArchive::fetchResource(SDIFileEntry *fileEntry, u32 *pSize) { *pSize = fileEntry->data_size; } } - return fileEntry->data; + return JKAR_DATA(fileEntry); } @@ -274,7 +279,7 @@ void *JKRCompArchive::fetchResource(void *data, u32 compressedSize, SDIFileEntry u32 fileFlag = fileEntry->type_flags_and_name_offset >> 0x18; int compression = JKRConvertAttrToCompressionType(u8(fileFlag)); - if(fileEntry->data != NULL) { + if(JKAR_DATA(fileEntry) != NULL) { if (compression == COMPRESSION_YAZ0) { u32 expandSize = getExpandSize(fileEntry); if (expandSize != 0) { @@ -286,7 +291,7 @@ void *JKRCompArchive::fetchResource(void *data, u32 compressedSize, SDIFileEntry fileSize = compressedSize; } - JKRHeap::copyMemory(data, fileEntry->data, fileSize); + JKRHeap::copyMemory(data, JKAR_DATA(fileEntry), fileSize); size = fileSize; } else { @@ -318,12 +323,12 @@ void JKRCompArchive::removeResourceAll() { for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { int tmp = fileEntry->type_flags_and_name_offset >> 0x18; - if (fileEntry->data != NULL) { + if (JKAR_DATA(fileEntry) != NULL) { if (!(tmp & 0x10)) { - JKRFreeToHeap(mHeap, fileEntry->data); + JKRFreeToHeap(mHeap, JKAR_DATA(fileEntry)); } - fileEntry->data = NULL; + JKAR_DATA(fileEntry) = NULL; } } fileEntry++; @@ -340,7 +345,7 @@ bool JKRCompArchive::removeResource(void* resource) { JKRFreeToHeap(mHeap, resource); } - fileEntry->data = NULL; + JKAR_DATA(fileEntry) = NULL; return true; } diff --git a/src/JSystem/JKernel/JKRDvdArchive.cpp b/src/JSystem/JKernel/JKRDvdArchive.cpp index ed88d791e7..dd4d504868 100644 --- a/src/JSystem/JKernel/JKRDvdArchive.cpp +++ b/src/JSystem/JKernel/JKRDvdArchive.cpp @@ -29,8 +29,8 @@ JKRDvdArchive::~JKRDvdArchive() { SDIFileEntry* fileEntry = mFiles; int i = 0; for (; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntry->data) { - JKRFreeToHeap(mHeap, fileEntry->data); + if (JKAR_DATA(fileEntry)) { + JKRFreeToHeap(mHeap, JKAR_DATA(fileEntry)); } fileEntry++; } @@ -96,6 +96,10 @@ bool JKRDvdArchive::open(s32 entryNum) { mStringTable = (char*)((intptr_t)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); mExpandedSize = NULL; +#if TARGET_PC + initFileDataPointers(); +#endif + u8 useCompression; useCompression = 0; SDIFileEntry* fileEntry; @@ -148,7 +152,7 @@ void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) { } JKRCompression fileCompression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 24)); - if (!fileEntry->data) { + if (!JKAR_DATA(fileEntry)) { u8* resourcePtr; u32 resourceSize = fetchResource_subroutine( mEntryNum, mDataOffset + fileEntry->data_offset, fileEntry->data_size, mHeap, @@ -158,7 +162,7 @@ void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) { return NULL; } - fileEntry->data = resourcePtr; + JKAR_DATA(fileEntry) = resourcePtr; if (fileCompression == COMPRESSION_YAZ0) { setExpandSize(fileEntry, *returnSize); } @@ -170,7 +174,7 @@ void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) { } } - return fileEntry->data; + return JKAR_DATA(fileEntry); } void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry, @@ -179,7 +183,7 @@ void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* f u32 size = fileEntry->data_size; JKRCompression fileCompression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 24)); - if (!fileEntry->data) { + if (!JKAR_DATA(fileEntry)) { bufferSize = (s32)ALIGN_PREV(bufferSize, 0x20); size = fetchResource_subroutine(mEntryNum, mDataOffset + fileEntry->data_offset, fileEntry->data_size, (u8*)buffer, bufferSize, fileCompression, @@ -196,7 +200,7 @@ void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* f size = bufferSize; } - JKRHeap::copyMemory(buffer, fileEntry->data, size); + JKRHeap::copyMemory(buffer, JKAR_DATA(fileEntry), size); } if (returnSize) { diff --git a/src/JSystem/JKernel/JKRMemArchive.cpp b/src/JSystem/JKernel/JKRMemArchive.cpp index 0c0ef4887c..9a594cd6f8 100644 --- a/src/JSystem/JKernel/JKRMemArchive.cpp +++ b/src/JSystem/JKernel/JKRMemArchive.cpp @@ -95,6 +95,10 @@ bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirectio mFiles = (SDIFileEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset); mStringTable = (char *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset); +#if TARGET_PC + initFileDataPointers(); +#endif + mArchiveData = (u8 *)((uintptr_t)mArcHeader + mArcHeader->header_length + mArcHeader->file_data_offset); mIsOpen = true; @@ -120,20 +124,25 @@ bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) { mIsOpen = (flag == JKRMEMBREAK_FLAG_UNKNOWN1) ? true : false; // mIsOpen might be u8 mHeap = JKRHeap::findFromRoot(buffer); mCompression = COMPRESSION_NONE; + +#if TARGET_PC + initFileDataPointers(); +#endif + return true; } void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) { JUT_ASSERT(555, isMounted()); - if (!fileEntry->data) { - fileEntry->data = mArchiveData + fileEntry->data_offset; + if (!JKAR_DATA(fileEntry)) { + JKAR_DATA(fileEntry) = mArchiveData + fileEntry->data_offset; } if (resourceSize) { *resourceSize = fileEntry->data_size; } - return fileEntry->data; + return JKAR_DATA(fileEntry); } void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry, @@ -144,8 +153,8 @@ void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* f srcLength = bufferSize; } - if (fileEntry->data != NULL) { - memcpy(buffer, fileEntry->data, srcLength); + if (JKAR_DATA(fileEntry) != NULL) { + memcpy(buffer, JKAR_DATA(fileEntry), srcLength); } else { u8 flags = fileEntry->type_flags_and_name_offset >> 24; JKRCompression compression = JKRConvertAttrToCompressionType(flags); @@ -172,8 +181,8 @@ void JKRMemArchive::removeResourceAll(void) { // first fileEntry will clear/remove the resource data. SDIFileEntry* fileEntry = mFiles; for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) { - if (fileEntry->data) { - fileEntry->data = NULL; + if (JKAR_DATA(fileEntry)) { + JKAR_DATA(fileEntry) = NULL; } } fileEntry++; @@ -186,7 +195,7 @@ bool JKRMemArchive::removeResource(void* resource) { if (!fileEntry) return false; - fileEntry->data = NULL; + JKAR_DATA(fileEntry) = NULL; return true; }