Fix JKRArchive on 64-bit

They store the data address in the same struct that's directly loaded from archive files. This means it's impossible to expand to 64-bit directly, and instead we need to allocate the data pointers in a separate array.
This commit is contained in:
PJB3005
2026-02-24 19:55:15 +01:00
parent 6d47b43766
commit e2dacba262
8 changed files with 127 additions and 43 deletions
+24
View File
@@ -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;
+1 -1
View File
@@ -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;
+10 -7
View File
@@ -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) {
+41 -2
View File
@@ -5,6 +5,10 @@
#include <cctype>
#include <string>
#if TARGET_PC
#include <cassert>
#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<void**>(
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
+5 -5
View File
@@ -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;
}
+18 -13
View File
@@ -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;
}
+11 -7
View File
@@ -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) {
+17 -8
View File
@@ -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;
}