Reorganize library code into libs/ (#3119)

* Reorganize files into libs/{dolphin,JSystem,PowerPC_EABI_Support,revolution,TRK_MINNOW_DOLPHIN}

* Update configure.py and project.py for new libs structure

* Refactor `#include <dolphin/x.h>` -> `<x.h>`

* Remove `__REVOLUTION_SDK__` forwards from dolphin

* Fix dolphin/ references in revolution

* Wrap `#include <dolphin.h>` in `!__REVOLUTION_SDK__`

* Always build TRK against dolphin headers

* Resolve revolution SDK header resolution issues
This commit is contained in:
Luke Street
2026-03-01 15:35:36 -07:00
committed by GitHub
parent c9a46bd65b
commit 4df8ccc871
1740 changed files with 583 additions and 825 deletions
+504
View File
@@ -0,0 +1,504 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAram.h"
#include "JSystem/JKernel/JKRAramPiece.h"
#include "JSystem/JKernel/JKRAramStream.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRExpHeap.h"
#include "JSystem/JUtility/JUTException.h"
#ifdef __REVOLUTION_SDK__
#include <revolution/aralt.h>
#include <revolution/os.h>
#else
#include <dolphin/ar.h>
#include <dolphin/os.h>
#endif
#include <cstring>
#if PLATFORM_GCN
const u32 stack_size = 0xc00;
#else
const u32 stack_size = 0x4000;
#endif
static u8* firstSrcData();
static u8* nextSrcData(u8* param_0);
static int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLength,
u32 offset, u32* resourceSize);
int decompSZS_subroutine(u8* src, u8* dest);
JKRAram* JKRAram::sAramObject;
JKRAram* JKRAram::create(u32 aram_audio_buffer_size, u32 aram_audio_graph_size, s32 stream_priority,
s32 decomp_priority, s32 piece_priority) {
if (!sAramObject) {
sAramObject = new (JKRGetSystemHeap(), 0)
JKRAram(aram_audio_buffer_size, aram_audio_graph_size, piece_priority);
}
JKRCreateAramStreamManager(stream_priority);
JKRCreateDecompManager(decomp_priority);
sAramObject->resume();
return sAramObject;
}
OSMessage JKRAram::sMessageBuffer[4] = {
NULL,
NULL,
NULL,
NULL,
};
OSMessageQueue JKRAram::sMessageQueue = {0};
JKRAram::JKRAram(u32 audio_buffer_size, u32 audio_graph_size, s32 priority)
: JKRThread(stack_size, 0x10, priority) {
u32 aramBase = ARInit(mStackArray, ARRAY_SIZEU(mStackArray));
ARQInit();
u32 aramSize = ARGetSize();
OS_REPORT("ARAM size = %08x\n", aramSize);
mAudioMemorySize = audio_buffer_size;
if (audio_graph_size == 0xFFFFFFFF) {
mGraphMemorySize = (aramSize - audio_buffer_size) - aramBase;
mAramMemorySize = 0;
} else {
mGraphMemorySize = audio_graph_size;
mAramMemorySize = (aramSize - (audio_buffer_size + audio_graph_size)) - aramBase;
}
mAudioMemoryPtr = ARAlloc(mAudioMemorySize);
mGraphMemoryPtr = ARAlloc(mGraphMemorySize);
if (mAramMemorySize) {
mAramMemoryPtr = ARAlloc(mAramMemorySize);
} else {
mAramMemoryPtr = 0;
}
OS_REPORT("ARAM audio area %08x: %08x\n", mAudioMemoryPtr, mAudioMemorySize);
OS_REPORT("ARAM graph area %08x: %08x\n", mGraphMemoryPtr, mGraphMemorySize);
OS_REPORT("ARAM user area %08x: %08x\n", mAramMemoryPtr, mAramMemorySize);
mAramHeap = new (JKRGetSystemHeap(), 0) JKRAramHeap(mGraphMemoryPtr, mGraphMemorySize);
}
JKRAram::~JKRAram() {
sAramObject = NULL;
if (mAramHeap)
delete mAramHeap;
}
void* JKRAram::run(void) {
OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 4);
do {
OSMessage msg;
OSReceiveMessage(&sMessageQueue, &msg, OS_MESSAGE_BLOCK);
JKRAramCommand* message = (JKRAramCommand*)msg;
int result = message->field_0x00;
JKRAMCommand* command = (JKRAMCommand*)message->command;
delete message;
switch (result) {
case 1:
JKRAramPiece::startDMA(command);
break;
}
} while (true);
}
void JKRAram::checkOkAddress(u8* addr, u32 size, JKRAramBlock* block, u32 param_4) {
if (!IS_ALIGNED((uintptr_t)addr, 0x20) && !IS_ALIGNED(size, 0x20)) {
JUTException::panic(__FILE__, 219, ":::address not 32Byte aligned.");
}
if (block && !IS_ALIGNED((uintptr_t)block->getAddress() + param_4, 0x20)) {
JUTException::panic(__FILE__, 227, ":::address not 32Byte aligned.");
}
}
void JKRAram::changeGroupIdIfNeed(u8* data, int groupId) {
JKRHeap* currentHeap = JKRGetCurrentHeap();
if (currentHeap->getHeapType() == 'EXPH' && groupId >= 0) {
JKRExpHeap::CMemBlock* block = (JKRExpHeap::CMemBlock*)(data - sizeof(JKRExpHeap::CMemBlock));
block->newGroupId(groupId);
}
}
JKRAramBlock* JKRAram::mainRamToAram(u8* buf, u32 bufSize, u32 alignedSize,
JKRExpandSwitch expandSwitch, u32 fileSize, JKRHeap* heap,
int id, u32* pSize) {
JKRAramBlock* block = NULL;
checkOkAddress(buf, bufSize, NULL, 0);
if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) {
expandSwitch = (JKRCheckCompressed_noASR(buf) == COMPRESSION_NONE) ?
EXPAND_SWITCH_UNKNOWN0 :
EXPAND_SWITCH_UNKNOWN1;
}
if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) {
u32 expandSize = JKRDecompExpandSize(buf);
if (fileSize == 0 || fileSize > expandSize) {
fileSize = ALIGN_NEXT(expandSize, 32);
}
if (bufSize == 0) {
block = JKRAllocFromAram(fileSize, JKRAramHeap::HEAD);
if (block == NULL) {
return NULL;
}
block->newGroupID(decideAramGroupId(id));
bufSize = block->getAddress();
}
if (alignedSize == 0 || alignedSize > expandSize) {
alignedSize = ALIGN_NEXT(expandSize, 32);
}
if (alignedSize > fileSize) {
alignedSize = fileSize;
}
void* allocatedMem = JKRAllocFromHeap(heap, fileSize, -32);
if (allocatedMem == NULL) {
if (block != NULL) {
JKRFreeToAram(block);
}
return NULL;
}
JKRDecompress(buf, (u8*)allocatedMem, fileSize, 0);
JKRAramPcs(0, (uintptr_t)allocatedMem, bufSize, alignedSize, block);
JKRFreeToHeap(heap, allocatedMem);
block = block == NULL ? (JKRAramBlock*)-1 : block;
if (pSize != NULL) {
*pSize = alignedSize;
}
return block;
}
if (fileSize != 0 && alignedSize > fileSize) {
alignedSize = fileSize;
}
if (bufSize == 0) {
block = JKRAllocFromAram(alignedSize, JKRAramHeap::HEAD);
block->newGroupID(decideAramGroupId(id));
if (block == NULL) {
return NULL;
}
bufSize = block->getAddress();
}
JKRAramPcs(0, (uintptr_t)buf, bufSize, alignedSize, block);
block = block == NULL ? (JKRAramBlock*)-1 : block;
if (pSize != NULL) {
*pSize = alignedSize;
}
return block;
}
u8* JKRAram::aramToMainRam(u32 address, u8* buf, u32 p3, JKRExpandSwitch expandSwitch, u32 p5,
JKRHeap* heap, int id, u32* pSize) {
JKRCompression compression = COMPRESSION_NONE;
if (pSize != NULL)
*pSize = 0;
checkOkAddress(buf, address, NULL, 0);
u32 expandSize;
if (expandSwitch == EXPAND_SWITCH_UNKNOWN1) {
u8 buffer[64];
u8* bufPtr = (u8*)ALIGN_NEXT((uintptr_t)buffer, 32);
JKRAramPcs(1, address, (uintptr_t)bufPtr, sizeof(buffer) / 2,
NULL); // probably change sizeof(buffer) / 2 to 32
compression = JKRCheckCompressed_noASR(bufPtr);
expandSize = JKRDecompExpandSize(bufPtr);
}
if (compression == COMPRESSION_YAZ0) { // SZS
if (p5 != 0 && p5 < expandSize)
expandSize = p5;
u8* r26 = !buf ? (u8*)JKRAllocFromHeap(heap, expandSize, 32) : buf;
if (r26 == NULL)
return NULL;
else {
changeGroupIdIfNeed(r26, id);
JKRDecompressFromAramToMainRam(address, r26, p3, expandSize, 0, pSize);
return r26;
}
} else if (compression == COMPRESSION_YAY0) { // SZP
u8* szpSpace = (u8*)JKRAllocFromHeap(heap, p3, -32);
if (szpSpace == NULL) {
return NULL;
} else {
JKRAramPcs(1, address, (uintptr_t)szpSpace, p3, NULL);
if (p5 != 0 && p5 < expandSize)
expandSize = p5;
u8* rv = !buf ? (u8*)JKRAllocFromHeap(heap, expandSize, 32) : buf;
if (rv == NULL) {
JKRFree(szpSpace);
return NULL;
} else {
changeGroupIdIfNeed(rv, id);
JKRDecompress(szpSpace, rv, expandSize, 0);
JKRFreeToHeap(heap, szpSpace);
if (pSize != NULL) {
*pSize = expandSize;
}
return rv;
}
}
} else { // Not compressed or ASR
u8* r24 = !buf ? (u8*)JKRAllocFromHeap(heap, p3, 32) : buf;
if (r24 == NULL) {
return NULL;
} else {
changeGroupIdIfNeed(r24, id);
JKRAramPcs(1, address, (uintptr_t)r24, p3, NULL);
if (pSize != NULL) {
*pSize = p3;
}
return r24;
}
}
}
JSUList<JKRAMCommand> JKRAram::sAramCommandList;
static OSMutex decompMutex;
u32 JKRAram::sSZSBufferSize = 0x00000400;
static u8* szpBuf;
static u8* szpEnd;
static u8* refBuf;
static u8* refEnd;
static u8* refCurrent;
static u32 srcOffset;
static u32 transLeft;
static u8* srcLimit;
static u32 srcAddress;
static u32 fileOffset;
static u32 readCount;
static u32 maxDest;
static bool s_is_decompress_mutex_initialized;
static u32* tsPtr;
static u32 tsArea;
static int JKRDecompressFromAramToMainRam(u32 src, void* dst, u32 srcLength, u32 dstLength,
u32 offset, u32* resourceSize) {
BOOL interrupts = OSDisableInterrupts();
if (s_is_decompress_mutex_initialized == false) {
OSInitMutex(&decompMutex);
s_is_decompress_mutex_initialized = true;
}
OSRestoreInterrupts(interrupts);
OSLockMutex(&decompMutex);
u32 szsBufferSize = JKRAram::getSZSBufferSize();
szpBuf = (u8*)JKRAllocFromSysHeap(szsBufferSize, 32);
JUT_ASSERT(1114, szpBuf != NULL);
szpEnd = szpBuf + szsBufferSize;
if (offset != 0) {
refBuf = (u8*)JKRAllocFromSysHeap(0x1120, 0);
JUT_ASSERT(1123, refBuf != NULL)
refEnd = refBuf + 0x1120;
refCurrent = refBuf;
} else {
refBuf = NULL;
}
srcAddress = src;
srcOffset = 0;
transLeft = (srcLength != 0) ? srcLength : -1;
fileOffset = offset;
readCount = 0;
maxDest = dstLength;
tsPtr = (resourceSize != 0) ? resourceSize : &tsArea;
*tsPtr = 0;
u8* first = firstSrcData();
int r25 = decompSZS_subroutine(first, (u8*)dst);
JKRFree(szpBuf);
if (refBuf) {
JKRFree(refBuf);
}
DCStoreRangeNoSync(dst, *tsPtr);
OSUnlockMutex(&decompMutex);
return 0;
}
int decompSZS_subroutine(u8* src, u8* dest) {
u8* endPtr;
s32 validBitCount = 0;
s32 currCodeByte = 0;
u32 ts = 0;
if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') {
return -1;
}
SYaz0Header* header = (SYaz0Header*)src;
endPtr = dest + (header->length - fileOffset);
if (endPtr > dest + maxDest) {
endPtr = dest + maxDest;
}
src += 0x10;
s32 b1;
u32 dist;
s32 numBytes;
u8* copySource;
do {
if (validBitCount == 0) {
if ((src > srcLimit) && transLeft) {
src = nextSrcData(src);
}
currCodeByte = *src++;
validBitCount = 8;
}
if (currCodeByte & 0x80) {
if (fileOffset != 0) {
if (readCount >= fileOffset) {
*dest = *src;
dest++;
ts++;
if (dest == endPtr) {
break;
}
}
*(refCurrent++) = *src;
if (refCurrent == refEnd) {
refCurrent = refBuf;
}
src++;
} else {
*dest++ = *src++;
ts++;
if (dest == endPtr) {
break;
}
}
readCount++;
} else {
b1 = src[0];
dist = src[1] | ((b1 & 0x0f) << 8);
numBytes = b1 >> 4;
src += 2;
if (fileOffset != 0) {
copySource = refCurrent - dist - 1;
if (copySource < refBuf) {
copySource += refEnd - refBuf;
}
} else {
copySource = dest - dist - 1;
}
if (numBytes == 0) {
numBytes = (*src++) + 0x12;
} else {
numBytes += 2;
}
if (fileOffset != 0) {
do {
if (readCount >= fileOffset) {
*dest = *copySource;
dest++;
ts++;
if (dest == endPtr) {
break;
}
}
*(refCurrent++) = *copySource;
if (refCurrent == refEnd) {
refCurrent = refBuf;
}
copySource++;
if (copySource == refEnd) {
copySource = refBuf;
}
readCount++;
numBytes--;
} while (numBytes != 0);
} else {
do {
*dest = *copySource;
dest++;
ts++;
if (dest == endPtr) {
break;
}
copySource++;
readCount++;
numBytes--;
} while (numBytes != 0);
}
}
currCodeByte <<= 1;
validBitCount--;
} while (dest < endPtr);
*tsPtr = ts;
return 0;
}
static u8* firstSrcData() {
srcLimit = szpEnd - 0x19;
u8* buffer = szpBuf;
u32 size = szpEnd - buffer;
u32 length = transLeft < size ? transLeft : size;
JKRAramPcs(1, srcAddress + srcOffset, uintptr_t(buffer), ALIGN_NEXT(length, 0x20), NULL);
srcOffset += length;
transLeft -= length;
if (!transLeft) {
srcLimit = buffer + length;
}
return buffer;
}
static u8* nextSrcData(u8* current) {
u8* dest;
u32 left = (uintptr_t)(szpEnd - current);
if (IS_NOT_ALIGNED(left, 0x20)) {
dest = szpBuf + 0x20 - (left & (0x20 - 1));
} else {
dest = szpBuf;
}
memcpy(dest, current, left);
u32 transSize = (uintptr_t)(szpEnd - (dest + left));
if (transSize > transLeft)
transSize = transLeft;
JUT_ASSERT(1403, transSize > 0);
JKRAramPcs(1, (uintptr_t)(srcAddress + srcOffset), ((uintptr_t)dest + left), ALIGN_NEXT(transSize, 0x20),
NULL);
srcOffset += transSize;
transLeft -= transSize;
if (transLeft == 0)
srcLimit = (dest + left) + transSize;
return dest;
}
static const char* stringBase_8039D0A6 = "bad aramSync\n";
+359
View File
@@ -0,0 +1,359 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAramArchive.h"
#include "JSystem/JKernel/JKRAram.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRDvdAramRipper.h"
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTException.h"
#include <cmath>
#include <cstring>
JKRAramArchive::JKRAramArchive() {}
JKRAramArchive::JKRAramArchive(s32 entryNumber, JKRArchive::EMountDirection mountDirection)
: JKRArchive(entryNumber, MOUNT_ARAM) {
mMountDirection = mountDirection;
if (!this->open(entryNumber)) {
return;
}
mVolumeType = 'RARC';
mVolumeName = mStringTable + mNodes->name_offset;
JKRFileLoader::sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
}
JKRAramArchive::~JKRAramArchive() {
if (mIsMounted == true) {
if (mArcInfoBlock != NULL) {
SDIFileEntry* entry = mFiles;
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
if (entry->data != NULL) {
JKRFreeToHeap(mHeap, entry->data);
}
entry++;
}
JKRFreeToHeap(mHeap, mArcInfoBlock);
mArcInfoBlock = NULL;
}
if (mExpandedSize != NULL) {
JKRFree(mExpandedSize);
mExpandedSize = NULL;
}
if (mDvdFile != NULL) {
delete mDvdFile;
}
if (mBlock != NULL) {
delete mBlock;
}
JKRFileLoader::sVolumeList.remove(&mFileLoaderLink);
mIsMounted = false;
}
}
void JKRAramArchive::fixedInit(s32 entryNumber, JKRArchive::EMountDirection mountDirection) {
mIsMounted = false;
mMountDirection = mountDirection;
mMountMode = 2;
mMountCount = 1;
field_0x58 = 2;
mHeap = JKRHeap::getCurrentHeap();
mEntryNum = entryNumber;
if (sCurrentVolume == NULL) {
sCurrentVolume = this;
sCurrentDirID = 0;
}
}
BOOL JKRAramArchive::mountFixed(s32 entryNumber, JKRArchive::EMountDirection mountDirection) {
if (entryNumber < 0) {
return FALSE;
}
if (check_mount_already(entryNumber, JKRGetCurrentHeap())) {
return FALSE;
}
fixedInit(entryNumber, mountDirection);
if (!open(entryNumber)) {
return FALSE;
}
mVolumeType = 'RARC';
mVolumeName = mStringTable + mNodes->name_offset;
sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
return TRUE;
}
static void dummy() {
OS_REPORT(__FILE__);
OS_REPORT("isMounted()");
OS_REPORT("mMountCount == 1");
}
bool JKRAramArchive::open(s32 entryNum) {
mArcInfoBlock = NULL;
mNodes = NULL;
mFiles = NULL;
mStringTable = NULL;
mBlock = NULL;
mDvdFile = new (JKRGetSystemHeap(), mMountDirection == MOUNT_DIRECTION_HEAD ? 4 : -4)
JKRDvdFile(entryNum);
if (mDvdFile == NULL) {
mMountMode = 0;
return 0;
}
// NOTE: a different struct is used here for sure, unfortunately i can't get any hits on this
// address, so gonna leave it like this for now
SArcHeader* mem = NULL;
mem = (SArcHeader*)JKRAllocFromSysHeap(32, -32);
if (mem == NULL) {
mMountMode = 0;
} else {
JKRDvdToMainRam(entryNum, (u8*)mem, EXPAND_SWITCH_UNKNOWN1, 32, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0, &mCompression, NULL);
DCInvalidateRange(mem, 32);
int alignment = mMountDirection == MOUNT_DIRECTION_HEAD ? 32 : -32;
u32 alignedSize = ALIGN_NEXT(mem->file_data_offset, 32);
mArcInfoBlock = (SArcDataInfo*)JKRAllocFromHeap(mHeap, alignedSize, alignment);
if (mArcInfoBlock == NULL) {
mMountMode = 0;
} else {
JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_UNKNOWN1, alignedSize, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 32, NULL, NULL);
DCInvalidateRange(mArcInfoBlock, alignedSize);
mNodes = (SDIDirEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->node_offset);
mFiles = (SDIFileEntry*)((u8*)mArcInfoBlock + mArcInfoBlock->file_entry_offset);
mStringTable = (char*)((u8*)mArcInfoBlock + mArcInfoBlock->string_table_offset);
mExpandedSize = NULL;
u8 compressedFiles = 0; // maybe a check for if the last file is compressed?
SDIFileEntry* fileEntry = mFiles;
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
u8 flag = fileEntry->type_flags_and_name_offset >> 24;
if ((flag & 1)) {
compressedFiles |= u8(flag & JKRARCHIVE_ATTR_COMPRESSION);
}
fileEntry++;
}
if (compressedFiles != 0) {
mExpandedSize = (s32*)JKRAllocFromHeap(mHeap, mArcInfoBlock->num_file_entries << 2,
abs(alignment));
if (mExpandedSize == NULL) {
JKRFree(mArcInfoBlock);
mMountMode = 0;
goto cleanup;
}
memset(mExpandedSize, 0, mArcInfoBlock->num_file_entries << 2);
}
u32 aramSize = ALIGN_NEXT(mem->file_data_length, 32);
mBlock = (JKRAramBlock*)JKRAllocFromAram(
aramSize,
mMountDirection == MOUNT_DIRECTION_HEAD ? JKRAramHeap::HEAD : JKRAramHeap::TAIL);
if (mBlock == NULL) {
if (mArcInfoBlock) {
JKRFree(mArcInfoBlock);
}
if (mExpandedSize) {
JKRFree(mExpandedSize);
}
mMountMode = 0;
} else {
JKRDvdToAram(entryNum, mBlock->getAddress(), EXPAND_SWITCH_UNKNOWN1,
mem->header_length + mem->file_data_offset, 0, NULL);
}
}
}
cleanup:
if (mem != NULL) {
JKRFreeToSysHeap(mem);
}
if (mMountMode == 0) {
OS_REPORT(":::[%s: %d] Cannot alloc memory\n", __FILE__, 415);
if (mDvdFile != NULL) {
delete mDvdFile;
}
return false;
}
return true;
}
void* JKRAramArchive::fetchResource(SDIFileEntry* pEntry, u32* pOutSize) {
JUT_ASSERT(442, isMounted());
u32 outSize;
u8* outBuf;
if (pOutSize == NULL) {
pOutSize = &outSize;
}
JKRCompression compression = JKRConvertAttrToCompressionType(u8(pEntry->type_flags_and_name_offset >> 24));
if (pEntry->data == NULL) {
u32 size = JKRAramArchive::fetchResource_subroutine(
pEntry->data_offset + mBlock->getAddress(), pEntry->data_size, mHeap, compression,
&outBuf);
*pOutSize = size;
if (size == 0) {
return NULL;
}
pEntry->data = outBuf;
if (compression == COMPRESSION_YAZ0) {
this->setExpandSize(pEntry, *pOutSize);
}
} else {
if (compression == COMPRESSION_YAZ0) {
*pOutSize = this->getExpandSize(pEntry);
} else {
*pOutSize = pEntry->data_size;
}
}
return pEntry->data;
}
void* JKRAramArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* pEntry,
u32* resourceSize) {
JUT_ASSERT(515, isMounted());
u32 size = pEntry->data_size;
if (size > bufferSize) {
size = bufferSize;
}
JKRCompression compression = JKRConvertAttrToCompressionType(u8(pEntry->type_flags_and_name_offset >> 24));
if (pEntry->data == NULL) {
bufferSize = (s32)ALIGN_PREV(bufferSize, 0x20);
size = JKRAramArchive::fetchResource_subroutine(pEntry->data_offset + mBlock->getAddress(),
size, (u8*)buffer, bufferSize, compression);
} else {
if (compression == COMPRESSION_YAZ0) {
u32 expandSize = this->getExpandSize(pEntry);
if (expandSize != 0) {
size = expandSize;
}
}
if (size > bufferSize) {
size = bufferSize;
}
JKRHeap::copyMemory(buffer, pEntry->data, size);
}
if (resourceSize != NULL) {
*resourceSize = size;
}
return buffer;
}
u32 JKRAramArchive::getAramAddress_Entry(SDIFileEntry* pEntry) {
JUT_ASSERT(572, isMounted());
if (pEntry == NULL) {
return 0;
} else {
return pEntry->data_offset + mBlock->getAddress();
}
}
u32 JKRAramArchive::getAramAddress(char const* name) {
SDIFileEntry* entry = this->findFsResource(name, 0);
return JKRAramArchive::getAramAddress_Entry(entry);
}
u32 JKRAramArchive::fetchResource_subroutine(u32 srcAram, u32 srcLength, u8* dst, u32 dstLength,
int compression) {
JUT_ASSERT(628, ( srcAram & 0x1f ) == 0);
u32 outLen;
u32 srcSize = ALIGN_NEXT(srcLength, 0x20);
u32 dstSize = ALIGN_PREV(dstLength, 0x20);
switch (compression) {
case COMPRESSION_NONE:
if (srcSize > dstSize) {
srcSize = dstSize;
}
JKRAramToMainRam(srcAram, dst, srcSize, EXPAND_SWITCH_UNKNOWN0, dstSize, NULL, -1, &outLen);
return outLen;
case COMPRESSION_YAY0:
case COMPRESSION_YAZ0:
JKRAramToMainRam(srcAram, dst, srcSize, EXPAND_SWITCH_UNKNOWN1, dstSize, NULL, -1, &outLen);
return outLen;
default:
JUTException::panic(__FILE__, 655, "??? bad sequence\n");
return 0;
}
}
u32 JKRAramArchive::fetchResource_subroutine(u32 entryNum, u32 length, JKRHeap* pHeap,
int compression, u8** out) {
u32 alignedLen = ALIGN_NEXT(length, 0x20);
u8* buffer;
switch (compression) {
case COMPRESSION_NONE:
{
buffer = (u8*)(JKRAllocFromHeap(pHeap, alignedLen, 0x20));
JUT_ASSERT(677, buffer != NULL);
JKRAramToMainRam(entryNum, buffer, alignedLen, EXPAND_SWITCH_UNKNOWN0, alignedLen, NULL, -1, NULL);
*out = buffer;
return length;
}
case COMPRESSION_YAY0:
case COMPRESSION_YAZ0:
{
u8 headerBuf[0x40];
u8* alignHeader = (u8*)ALIGN_NEXT((s32)&headerBuf[0], sizeof(SArcHeader));
JKRAramToMainRam(entryNum, alignHeader, sizeof(SArcHeader), EXPAND_SWITCH_UNKNOWN0, 0, NULL, -1, NULL);
u32 decompressedLen = ALIGN_NEXT(JKRDecompExpandSize(alignHeader), sizeof(SArcHeader));
buffer = (u8*)(JKRAllocFromHeap(pHeap, decompressedLen, sizeof(SArcHeader)));
JUT_ASSERT(703, buffer);
u32 readLen;
JKRAramToMainRam(entryNum, buffer, alignedLen, EXPAND_SWITCH_UNKNOWN1, decompressedLen, pHeap, -1, &readLen);
*out = buffer;
return readLen;
}
default:
JUTException::panic(__FILE__, 713, "??? bad sequence\n");
return 0;
}
}
u32 JKRAramArchive::getExpandedResSize(const void* ptr) const {
if (mExpandedSize == NULL) {
return this->getResSize(ptr);
}
JKRArchive::SDIFileEntry* entry = this->findPtrResource(ptr);
if (entry == NULL) {
return 0xFFFFFFFF;
}
u8 flags = entry->type_flags_and_name_offset >> 24;
if ((flags & 4) == 0) {
return this->getResSize(ptr);
}
u32 expandSize = this->getExpandSize(entry);
if (expandSize != 0) {
return expandSize;
}
u8 tmpBuf[0x40];
u8* buf = (u8*)ALIGN_PREV((s32)&tmpBuf[0x1F], 0x20);
JKRAramToMainRam(entry->data_offset + mBlock->getAddress(), buf, 0x20, EXPAND_SWITCH_UNKNOWN0,
0, NULL, -1, NULL);
u32 expandSize2 = JKRDecompExpandSize(buf);
// ??? casting away const?
((JKRArchive*)this)->setExpandSize(entry, expandSize2);
return expandSize2;
}
+50
View File
@@ -0,0 +1,50 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAramBlock.h"
#include "JSystem/JKernel/JKRAramHeap.h"
#include "JSystem/JKernel/JKRHeap.h"
JKRAramBlock::JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupId, bool isTempMemory)
: mBlockLink(this) {
mAddress = address;
mSize = size;
mFreeSize = freeSize;
mGroupId = groupId;
mIsTempMemory = isTempMemory;
}
JKRAramBlock::~JKRAramBlock() {
JSUList<JKRAramBlock>* list = mBlockLink.getSupervisor();
JSULink<JKRAramBlock>* prev = mBlockLink.getPrev();
if (prev) {
prev->getObject()->mFreeSize += mSize + mFreeSize;
list->remove(&mBlockLink);
} else {
mFreeSize = mFreeSize + mSize;
mSize = 0;
}
}
JKRAramBlock* JKRAramBlock::allocHead(u32 size, u8 groupId, JKRAramHeap* aramHeap) {
u32 nextAddress = mAddress + mSize;
u32 nextFreeSize = mFreeSize - size;
JKRAramBlock* block = new (aramHeap->getMgrHeap(), 0)
JKRAramBlock(nextAddress, size, nextFreeSize, groupId, false);
mFreeSize = 0;
mBlockLink.getSupervisor()->insert(mBlockLink.getNext(), &block->mBlockLink);
return block;
}
JKRAramBlock* JKRAramBlock::allocTail(u32 size, u8 groupId, JKRAramHeap* aramHeap) {
u32 tailAddress = mAddress + mSize + mFreeSize - size;
JKRAramBlock* block =
new (aramHeap->getMgrHeap(), 0) JKRAramBlock(tailAddress, size, 0, groupId, true);
mFreeSize -= size;
mBlockLink.getSupervisor()->insert(mBlockLink.getNext(), &block->mBlockLink);
return block;
}
+137
View File
@@ -0,0 +1,137 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAramHeap.h"
#include "JSystem/JKernel/JKRHeap.h"
#include "global.h"
#include <climits>
JSUList<JKRAramBlock> JKRAramHeap::sAramList;
JKRAramHeap::JKRAramHeap(u32 startAddress, u32 size) {
OSInitMutex(&mMutex);
mHeap = JKRHeap::findFromRoot(this);
mSize = ALIGN_PREV(size, 0x20);
mHeadAddress = ALIGN_NEXT(startAddress, 0x20);
mTailAddress = mHeadAddress + mSize;
mGroupId = -1;
JKRAramBlock* block = new (mHeap, 0) JKRAramBlock(mHeadAddress, 0, mSize, -1, false);
sAramList.append(&block->mBlockLink);
}
JKRAramHeap::~JKRAramHeap() {
for (JSUListIterator<JKRAramBlock> iterator = sAramList.getFirst(); iterator != sAramList.getEnd(); delete (iterator++).getObject()) {}
}
JKRAramBlock* JKRAramHeap::alloc(u32 size, JKRAramHeap::EAllocMode allocationMode) {
lock();
JKRAramBlock* block;
if (allocationMode == JKRAramHeap::HEAD) {
block = allocFromHead(size);
} else {
block = allocFromTail(size);
}
unlock();
return block;
}
JKRAramBlock* JKRAramHeap::allocFromHead(u32 size) {
u32 alignedSize = ALIGN_NEXT(size, 0x20);
u32 bestFreeSize = UINT_MAX;
JKRAramBlock* bestBlock = NULL;
for (JSUListIterator<JKRAramBlock> iterator = sAramList.getFirst(); iterator != sAramList.getEnd(); ++iterator) {
JKRAramBlock* block = iterator.getObject();
if (block->mFreeSize < alignedSize) {
continue;
}
if (bestFreeSize <= block->mFreeSize) {
continue;
}
bestFreeSize = block->mFreeSize;
bestBlock = block;
if (bestFreeSize == alignedSize) {
break;
}
}
if (bestBlock) {
return bestBlock->allocHead(alignedSize, mGroupId, this);
}
return NULL;
}
JKRAramBlock* JKRAramHeap::allocFromTail(u32 size) {
u32 alignedSize = ALIGN_NEXT(size, 0x20);
JKRAramBlock* tailBlock = NULL;
for (JSUListIterator<JKRAramBlock> iterator = sAramList.getLast(); iterator != sAramList.getEnd(); --iterator) {
JKRAramBlock* block = iterator.getObject();
if (block->mFreeSize >= alignedSize) {
tailBlock = block;
break;
}
}
if (tailBlock) {
return tailBlock->allocTail(alignedSize, mGroupId, this);
}
return NULL;
}
u32 JKRAramHeap::getFreeSize(void) {
u32 maxFreeSize = 0;
lock();
for (JSUListIterator<JKRAramBlock> iterator = sAramList.getFirst(); iterator != sAramList.getEnd(); ++iterator) {
if (iterator->mFreeSize > maxFreeSize) {
maxFreeSize = iterator->mFreeSize;
}
}
unlock();
return maxFreeSize;
}
u32 JKRAramHeap::getTotalFreeSize(void) {
u32 totalFreeSize = 0;
lock();
for (JSUListIterator<JKRAramBlock> iterator = sAramList.getFirst(); iterator != sAramList.getEnd(); ++iterator) {
totalFreeSize += iterator->mFreeSize;
}
unlock();
return totalFreeSize;
}
void JKRAramHeap::dump(void) {
lock();
OS_REPORT("\nJKRAramHeap dump\n");
OS_REPORT(" attr address: size gid\n");
u32 usedBytes = 0;
for (JSUListIterator<JKRAramBlock> it = sAramList.getFirst(); it != sAramList.getEnd(); ++it) {
if (it->mSize) {
OS_REPORT("%s %08x: %08x %3d\n", it->isTempMemory() ? " temp" : "alloc", it->mAddress, it->mSize, it->mGroupId);
}
if (it->mFreeSize) {
OS_REPORT(" free %08x: %08x 0\n", it->mAddress + it->mSize, it->mFreeSize);
}
usedBytes += it->mSize;
}
OS_REPORT("%d / %d bytes (%6.2f%%) used\n", usedBytes, mSize, f32(usedBytes) / f32(mSize) * 100.0f);
unlock();
}
+141
View File
@@ -0,0 +1,141 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAramPiece.h"
#include "JSystem/JKernel/JKRAram.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JUtility/JUTException.h"
#include <os.h>
JKRAMCommand* JKRAramPiece::prepareCommand(int direction, u32 src, u32 dst, u32 length,
JKRAramBlock* block,
JKRAMCommand::AsyncCallback callback) {
JKRAMCommand* command = new (JKRGetSystemHeap(), -4) JKRAMCommand();
command->mTransferDirection = direction;
command->mSrc = src;
command->mDst = dst;
command->mAramBlock = block;
command->mDataLength = length;
command->mCallback = callback;
return command;
}
void JKRAramPiece::sendCommand(JKRAMCommand* command) {
startDMA(command);
}
JSUList<JKRAMCommand> JKRAramPiece::sAramPieceCommandList;
OSMutex JKRAramPiece::mMutex;
JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destination, u32 length,
JKRAramBlock* block, JKRAMCommand::AsyncCallback callback) {
lock();
if ((source & 0x1f) != 0 || (destination & 0x1f) != 0) {
OSReport("direction = %x\n", direction);
OSReport("source = %x\n", source);
OSReport("destination = %x\n", destination);
OSReport("length = %x\n", length);
JUTException::panic(__FILE__, 108, "illegal address. abort.");
}
JKRAramCommand* message = new (JKRGetSystemHeap(), -4) JKRAramCommand();
JKRAMCommand* command =
JKRAramPiece::prepareCommand(direction, source, destination, length, block, callback);
message->setting(1, command);
OSSendMessage(&JKRAram::sMessageQueue, message, OS_MESSAGE_BLOCK);
if (command->mCallback != NULL) {
sAramPieceCommandList.append(&command->mPieceLink);
}
unlock();
return command;
}
BOOL JKRAramPiece::sync(JKRAMCommand* command, int is_non_blocking) {
OSMessage message;
lock();
if (is_non_blocking == 0) {
OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCK);
sAramPieceCommandList.remove(&command->mPieceLink);
unlock();
return TRUE;
}
if (!OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NOBLOCK)) {
unlock();
return FALSE;
}
sAramPieceCommandList.remove(&command->mPieceLink);
unlock();
return TRUE;
}
BOOL JKRAramPiece::orderSync(int direction, u32 source, u32 destination, u32 length,
JKRAramBlock* block) {
lock();
JKRAMCommand* command =
JKRAramPiece::orderAsync(direction, source, destination, length, block, NULL);
BOOL result = JKRAramPiece::sync(command, 0);
delete command;
unlock();
return result;
}
void JKRAramPiece::startDMA(JKRAMCommand* command) {
if (command->mTransferDirection == 1) {
DCInvalidateRange((void*)command->mDst, command->mDataLength);
} else {
DCStoreRange((void*)command->mSrc, command->mDataLength);
}
ARQPostRequest(&command->mRequest, 0, command->mTransferDirection, 0, command->mSrc,
command->mDst, command->mDataLength, JKRAramPiece::doneDMA);
}
void JKRAramPiece::doneDMA(u32 requestAddress) {
JKRAMCommand* command = (JKRAMCommand*)requestAddress;
if (command->mTransferDirection == 1) {
DCInvalidateRange((void*)command->mDst, command->mDataLength);
}
if (command->field_0x60 != 0) {
if (command->field_0x60 == 2) {
JKRDecompress_SendCommand(command->mDecompCommand);
}
return;
}
if (command->mCallback) {
(*command->mCallback)(requestAddress);
} else if (command->field_0x5C) {
OSSendMessage(command->field_0x5C, command, OS_MESSAGE_NOBLOCK);
} else {
OSSendMessage(&command->mMessageQueue, command, OS_MESSAGE_NOBLOCK);
}
}
JKRAMCommand::JKRAMCommand() : mPieceLink(this), field_0x30(this) {
OSInitMessageQueue(&mMessageQueue, &mMessage, 1);
mCallback = NULL;
field_0x5C = NULL;
field_0x60 = 0;
field_0x8C = NULL;
field_0x90 = NULL;
field_0x94 = NULL;
}
JKRAMCommand::~JKRAMCommand() {
if (field_0x8C)
delete field_0x8C;
if (field_0x90)
delete field_0x90;
if (field_0x94)
JKRFree(field_0x94);
}
+208
View File
@@ -0,0 +1,208 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAramStream.h"
#include "JSystem/JKernel/JKRAramPiece.h"
#include "JSystem/JSupport/JSUFileStream.h"
#include "JSystem/JUtility/JUTException.h"
#include <stdint.h>
#if PLATFORM_GCN
const u32 stack_size = 0xc00;
#else
const u32 stack_size = 0x4000;
#endif
JKRAramStream* JKRAramStream::sAramStreamObject;
JKRAramStream* JKRAramStream::create(s32 priority) {
if (!sAramStreamObject) {
sAramStreamObject = new (JKRGetSystemHeap(), 0) JKRAramStream(priority);
JKRResetAramTransferBuffer();
}
return sAramStreamObject;
}
void* JKRAramStream::sMessageBuffer[4] = {
NULL,
NULL,
NULL,
NULL,
};
OSMessageQueue JKRAramStream::sMessageQueue = {0};
JKRAramStream::JKRAramStream(s32 priority) : JKRThread(stack_size, 0x10, priority) {
resume();
}
JKRAramStream::~JKRAramStream() {}
void* JKRAramStream::run() {
OSInitMessageQueue(&sMessageQueue, sMessageBuffer, ARRAY_SIZEU(sMessageBuffer));
for (;;) {
OSMessage message;
OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK);
JKRAramStreamCommand* command = (JKRAramStreamCommand*)message;
switch (command->mType) {
case JKRAramStreamCommand::READ:
readFromAram();
break;
case JKRAramStreamCommand::WRITE:
writeToAram(command);
break;
}
}
}
s32 JKRAramStream::readFromAram() {
return 1;
}
s32 JKRAramStream::writeToAram(JKRAramStreamCommand* command) {
u32 dstSize = command->mSize;
u32 offset = command->mOffset;
u32 writtenLength = 0;
u32 destination = command->mAddress;
u8* buffer = command->mTransferBuffer;
u32 bufferSize = command->mTransferBufferSize;
JKRHeap* heap = command->mHeap;
if (buffer) {
bufferSize = bufferSize == 0 ? 0x8000 : bufferSize;
command->mTransferBufferSize = bufferSize;
command->mAllocatedTransferBuffer = false;
} else {
bufferSize = bufferSize == 0 ? 0x8000 : bufferSize;
if (heap) {
buffer = (u8*)JKRAllocFromHeap(heap, bufferSize, -0x20);
command->mTransferBuffer = buffer;
} else {
buffer = (u8*)JKRAllocFromSysHeap(bufferSize, -0x20);
command->mTransferBuffer = buffer;
}
command->mTransferBufferSize = bufferSize;
command->mAllocatedTransferBuffer = true;
}
if (!buffer) {
if (!heap) {
JKRGetCurrentHeap()->dump();
} else {
heap->dump();
}
JUTException::panic(__FILE__, 172, ":::Cannot alloc memory\n");
}
if (buffer) {
command->mStream->seek(offset, JSUStreamSeekFrom_SET);
while (dstSize != 0) {
u32 length = (dstSize > bufferSize) ? bufferSize : dstSize;
s32 readLength = command->mStream->read(buffer, length);
if (readLength == 0) {
writtenLength = 0;
break;
}
JKRAramPcs(0, (uintptr_t)buffer, destination, length, NULL);
dstSize -= length;
offset += length;
writtenLength += length;
destination += length;
if (command->mReturnSize) {
*command->mReturnSize += length;
}
}
if (command->mAllocatedTransferBuffer) {
JKRFree(buffer);
command->mAllocatedTransferBuffer = false;
}
}
OSSendMessage(&command->mMessageQueue, (OSMessage)writtenLength, OS_MESSAGE_NOBLOCK);
return writtenLength;
}
u8* JKRAramStream::transBuffer;
u32 JKRAramStream::transSize;
JKRHeap* JKRAramStream::transHeap;
JKRAramStreamCommand* JKRAramStream::write_StreamToAram_Async(JSUFileInputStream* stream, u32 addr,
u32 size, u32 offset,
u32* returnSize) {
JKRAramStreamCommand* command = new (JKRGetSystemHeap(), -4) JKRAramStreamCommand();
command->mType = JKRAramStreamCommand::WRITE;
command->mAddress = addr;
command->mSize = size;
command->mStream = stream;
command->field_0x2c = 0;
command->mOffset = offset;
command->mTransferBuffer = transBuffer;
command->mHeap = transHeap;
command->mTransferBufferSize = transSize;
command->mReturnSize = returnSize;
if (returnSize) {
*returnSize = 0;
}
OSInitMessageQueue(&command->mMessageQueue, &command->mMessage, 1);
OSSendMessage(&sMessageQueue, command, OS_MESSAGE_BLOCK);
return command;
}
JKRAramStreamCommand* JKRAramStream::sync(JKRAramStreamCommand* command, BOOL isNonBlocking) {
OSMessage message;
if (isNonBlocking == 0) {
OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCK);
if (message == NULL) {
return NULL;
} else {
return command;
}
} else {
if (OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NOBLOCK) == FALSE) {
return NULL;
} else if (message == NULL) {
return NULL;
} else {
return command;
}
}
}
void JKRAramStream::setTransBuffer(u8* buffer, u32 bufferSize, JKRHeap* heap) {
transBuffer = NULL;
transSize = 0x8000;
transHeap = NULL;
if (buffer) {
transBuffer = (u8*)ALIGN_NEXT((uintptr_t)buffer, 0x20);
}
if (bufferSize) {
transSize = ALIGN_PREV(bufferSize, 0x20);
}
if (heap && !buffer) {
transHeap = heap;
}
}
JKRAramStreamCommand::JKRAramStreamCommand() {
mAllocatedTransferBuffer = false;
}
static void dummy(JSURandomInputStream* stream) {
stream->getAvailable();
}
+227
View File
@@ -0,0 +1,227 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRArchive.h"
#include "JSystem/JKernel/JKRHeap.h"
#include <cctype>
#include <cstring>
u32 JKRArchive::sCurrentDirID;
JKRArchive::JKRArchive() {
mIsMounted = false;
mMountDirection = MOUNT_DIRECTION_HEAD;
}
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 (sCurrentVolume == NULL) {
sCurrentVolume = this;
sCurrentDirID = 0;
}
}
JKRArchive::~JKRArchive() {}
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;
}
JKRArchive::SDIDirEntry* JKRArchive::findResType(u32 type) const {
SDIDirEntry* node = mNodes;
for (u32 count = 0; count < mArcInfoBlock->num_nodes; count++) {
if (node->type == type) {
return node;
}
node++;
}
return NULL;
}
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; i++) {
if (isSameName(arcName, fileEntry->type_flags_and_name_offset & 0xFFFFFF, fileEntry->name_hash)) {
if ((fileEntry->type_flags_and_name_offset >> 24) & 2) {
return findDirectory(name, fileEntry->data_offset);
}
break;
}
fileEntry++;
}
return NULL;
}
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; i++) {
if (isSameName(arcName, fileEntry->type_flags_and_name_offset & 0xFFFFFF, fileEntry->name_hash)) {
return fileEntry;
}
fileEntry++;
}
}
}
return NULL;
}
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; i++) {
if (isSameName(arcName, fileEntry->type_flags_and_name_offset & 0xFFFFFF, fileEntry->name_hash)) {
if ((fileEntry->type_flags_and_name_offset >> 24) & 2) {
return findFsResource(name, fileEntry->data_offset);
}
if (name == NULL) {
return fileEntry;
}
return NULL;
}
fileEntry++;
}
}
return NULL;
}
JKRArchive::SDIFileEntry* JKRArchive::findIdxResource(u32 fileIndex) const {
if (fileIndex < mArcInfoBlock->num_file_entries) {
return mFiles + fileIndex;
}
return NULL;
}
JKRArchive::SDIFileEntry* JKRArchive::findNameResource(const char* name) const {
SDIFileEntry* fileEntry = mFiles;
CArcName arcName(name);
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
if (isSameName(arcName, fileEntry->type_flags_and_name_offset & 0xFFFFFF, fileEntry->name_hash)) {
return fileEntry;
}
fileEntry++;
}
return NULL;
}
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) {
return fileEntry;
}
fileEntry++;
}
return NULL;
}
JKRArchive::SDIFileEntry* JKRArchive::findIdResource(u16 id) const {
if (id != 0xFFFF) {
SDIFileEntry* fileEntry;
if (id < mArcInfoBlock->num_file_entries) {
fileEntry = mFiles + id;
if (fileEntry->file_id == id && ((fileEntry->type_flags_and_name_offset >> 24) & 1)) {
return fileEntry;
}
}
fileEntry = mFiles;
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
if (fileEntry->file_id == id && ((fileEntry->type_flags_and_name_offset >> 24) & 1)) {
return fileEntry;
}
fileEntry++;
}
}
return NULL;
}
void JKRArchive::CArcName::store(const char* name) {
mHash = 0;
s32 length = 0;
while (*name) {
s32 ch = tolower(*name);
mHash = ch + mHash * 3;
if (length < ARRAY_SIZE(mData)) {
mData[length++] = ch;
}
name++;
}
mLength = (u16)length;
mData[length] = 0;
}
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 < ARRAY_SIZE(mData)) {
mData[length++] = lch;
}
name++;
}
mLength = (u16)length;
mData[length] = 0;
if (*name == 0)
return NULL;
return name + 1;
}
void JKRArchive::setExpandSize(SDIFileEntry* fileEntry, u32 expandSize) {
int index = fileEntry - mFiles;
if (!mExpandedSize || index >= mArcInfoBlock->num_file_entries)
return;
mExpandedSize[index] = expandSize;
}
u32 JKRArchive::getExpandSize(SDIFileEntry* fileEntry) const {
int index = fileEntry - mFiles;
if (!mExpandedSize || index >= mArcInfoBlock->num_file_entries)
return 0;
return mExpandedSize[index];
}
+347
View File
@@ -0,0 +1,347 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAramArchive.h"
#include "JSystem/JKernel/JKRArchive.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"
JKRArchive* JKRArchive::check_mount_already(s32 entryNum, JKRHeap* heap) {
if (heap == NULL) {
heap = JKRGetCurrentHeap();
}
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
if (iterator->getVolumeType() == 'RARC') {
JKRArchive* archive = (JKRArchive*)iterator.operator->();
if (archive->mEntryNum == entryNum && archive->mHeap == heap) {
archive->mMountCount++;
return archive;
}
}
}
return NULL;
}
JKRArchive* JKRArchive::mount(const char* path, EMountMode mountMode, JKRHeap* heap,
EMountDirection mountDirection) {
s32 entryNum = DVDConvertPathToEntrynum(path);
if (entryNum < 0)
return NULL;
return mount(entryNum, mountMode, heap, mountDirection);
}
JKRArchive* JKRArchive::mount(void* ptr, JKRHeap* heap,
EMountDirection mountDirection) {
JKRArchive* archive = check_mount_already((s32)ptr, heap);
if (archive) {
return archive;
}
int alignment = mountDirection == MOUNT_DIRECTION_HEAD ? 4 : -4;
JKRArchive* newArchive = new (heap, alignment) JKRMemArchive(ptr, 0xFFFF, JKRMEMBREAK_FLAG_UNKNOWN0);
return newArchive;
}
JKRArchive* JKRArchive::mount(s32 entryNum, JKRArchive::EMountMode mountMode, JKRHeap* heap,
JKRArchive::EMountDirection mountDirection) {
JKRArchive* archive = check_mount_already(entryNum, heap);
if (archive != NULL) {
return archive;
}
int alignment = mountDirection == MOUNT_DIRECTION_HEAD ? 4 : -4;
JKRArchive* newArchive;
switch (mountMode) {
case JKRArchive::MOUNT_MEM:
newArchive = new (heap, alignment) JKRMemArchive(entryNum, mountDirection);
break;
case JKRArchive::MOUNT_ARAM:
newArchive = new (heap, alignment) JKRAramArchive(entryNum, mountDirection);
break;
case JKRArchive::MOUNT_DVD:
newArchive = new (heap, alignment) JKRDvdArchive(entryNum, mountDirection);
break;
case JKRArchive::MOUNT_COMP:
newArchive = new (heap, alignment) JKRCompArchive(entryNum, mountDirection);
break;
}
if (newArchive && newArchive->mMountMode == JKRArchive::UNKNOWN_MOUNT_MODE) {
delete newArchive;
newArchive = NULL;
}
return newArchive;
}
bool JKRArchive::becomeCurrent(const char* path) {
SDIDirEntry* dirEntry = NULL;
if (*path == '/') {
path++;
if (*path == '\0')
path = NULL;
dirEntry = findDirectory(path, 0);
} else {
dirEntry = findDirectory(path, sCurrentDirID);
}
bool found = dirEntry != NULL;
if (found) {
sCurrentVolume = this;
sCurrentDirID = dirEntry - mNodes;
}
return found;
}
bool JKRArchive::getDirEntry(SDirEntry* dirEntry, u32 index) const {
SDIFileEntry* fileEntry = findIdxResource(index);
if (!fileEntry)
return false;
dirEntry->flags = fileEntry->type_flags_and_name_offset >> 24;
dirEntry->id = fileEntry->file_id;
dirEntry->name = mStringTable + (fileEntry->type_flags_and_name_offset & 0xFFFFFF);
return true;
}
void* JKRArchive::getGlbResource(u32 param_1, const char* path, JKRArchive* archive) {
void* resource = NULL;
if (archive) {
return archive->getResource(param_1, path);
}
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
if (iterator->getVolumeType() == 'RARC') {
JKRFileLoader* fileLoader = iterator.operator->();
resource = fileLoader->getResource(param_1, path);
if (resource) {
break;
}
}
}
return resource;
}
void* JKRArchive::getResource(const char* path) {
JUT_ASSERT(303, isMounted());
SDIFileEntry* fileEntry = NULL;
if (*path == '/') {
fileEntry = findFsResource(path + 1, 0);
} else {
fileEntry = findFsResource(path, sCurrentDirID);
}
if (fileEntry) {
return fetchResource(fileEntry, NULL);
}
return NULL;
}
void* JKRArchive::getResource(u32 type, const char* path) {
JUT_ASSERT(347, isMounted());
SDIFileEntry* fileEntry;
if (type == 0 || type == '????') {
fileEntry = findNameResource(path);
} else {
fileEntry = findTypeResource(type, path);
}
if (fileEntry) {
return fetchResource(fileEntry, NULL);
}
return NULL;
}
void* JKRArchive::getIdxResource(u32 index) {
JUT_ASSERT(384, isMounted());
SDIFileEntry* fileEntry = findIdxResource(index);
if (fileEntry) {
return fetchResource(fileEntry, NULL);
}
return NULL;
}
void* JKRArchive::getResource(u16 id) {
JUT_ASSERT(409, isMounted());
SDIFileEntry* fileEntry = findIdResource(id);
if (fileEntry) {
return fetchResource(fileEntry, NULL);
}
return NULL;
}
u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u32 type, const char* path) {
JUT_ASSERT(493, 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;
}
u32 JKRArchive::readResource(void* buffer, u32 bufferSize, const char* path) {
JUT_ASSERT(539, isMounted());
SDIFileEntry* fileEntry = NULL;
if (*path == '/') {
fileEntry = findFsResource(path + 1, 0);
} else {
fileEntry = findFsResource(path, sCurrentDirID);
}
if (fileEntry) {
u32 resourceSize;
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
return resourceSize;
}
return 0;
}
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;
}
u32 JKRArchive::readResource(void* buffer, u32 bufferSize, u16 id) {
JUT_ASSERT(625, isMounted());
SDIFileEntry* fileEntry = findIdResource(id);
if (fileEntry) {
u32 resourceSize;
fetchResource(buffer, bufferSize, fileEntry, &resourceSize);
return resourceSize;
}
return 0;
}
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;
}
fileEntry++;
}
}
}
bool JKRArchive::removeResource(void* resource) {
JUT_ASSERT(678, resource != NULL);
SDIFileEntry* fileEntry = findPtrResource(resource);
if (fileEntry == NULL)
return false;
fileEntry->data = NULL;
JKRFreeToHeap(mHeap, resource);
return true;
}
bool JKRArchive::detachResource(void* resource) {
JUT_ASSERT(707, resource != NULL);
SDIFileEntry* fileEntry = findPtrResource(resource);
if (fileEntry == NULL)
return false;
fileEntry->data = NULL;
return true;
}
u32 JKRArchive::getResSize(const void* resource) const {
JUT_ASSERT(732, resource != NULL);
SDIFileEntry* fileEntry = findPtrResource(resource);
if (fileEntry == NULL)
return -1;
return fileEntry->data_size;
}
u32 JKRArchive::countResource() const {
u32 count = 0;
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
if ((mFiles[i].type_flags_and_name_offset >> 24) & 1) {
count++;
}
}
return count;
}
u32 JKRArchive::countFile(const char* path) const {
SDIDirEntry* dirEntry = NULL;
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;
}
JKRFileFinder* JKRArchive::getFirstFile(const char* path) const {
SDIDirEntry* dirEntry = NULL;
if (*path == '/') {
path++;
if (*path == '\0')
path = NULL;
dirEntry = findDirectory(path, 0);
} else {
dirEntry = findDirectory(path, sCurrentDirID);
}
if (dirEntry) {
// don't know what is correct here... for now we're casting away const
return new (JKRGetSystemHeap(), 0)
JKRArcFinder((JKRArchive*)this, dirEntry->first_file_index, (u32)dirEntry->num_entries);
}
return NULL;
}
u8 JKRArchive::getFileAttribute(u32 index) const {
SDIFileEntry* fileEntry = findIdxResource(index);
if (fileEntry) {
return fileEntry->type_flags_and_name_offset >> 24;
}
return 0;
}
@@ -0,0 +1,45 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRAssertHeap.h"
JKRAssertHeap::JKRAssertHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag)
: JKRHeap(data, size, parent, errorFlag) {}
JKRAssertHeap::~JKRAssertHeap() {
this->dispose();
}
JKRAssertHeap* JKRAssertHeap::create(JKRHeap* parent) {
if (!parent) {
parent = sRootHeap;
}
u32 size = ALIGN_NEXT(sizeof(JKRAssertHeap), 16);
void* ptr = JKRAllocFromHeap(parent, size, 16);
if (!ptr)
return NULL;
JKRAssertHeap* heap = new (ptr) JKRAssertHeap(NULL, 0, parent, false);
return heap;
}
void JKRAssertHeap::do_destroy() {
this->~JKRAssertHeap();
}
u32 JKRAssertHeap::getHeapType() {
return 'ASTH';
}
bool JKRAssertHeap::check() {
return true;
}
bool JKRAssertHeap::dump() {
return true;
}
bool JKRAssertHeap::dump_sort() {
return true;
}
+385
View File
@@ -0,0 +1,385 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRCompArchive.h"
#include "JSystem/JKernel/JKRAram.h"
#include "JSystem/JKernel/JKRAramArchive.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRDvdAramRipper.h"
#include "JSystem/JKernel/JKRDvdArchive.h"
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JKernel/JKRMemArchive.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTException.h"
#include <cmath>
#include <cstring>
#include <stdint.h>
JKRCompArchive::JKRCompArchive(s32 entryNum, JKRArchive::EMountDirection eMountDirection)
: JKRArchive(entryNum, MOUNT_COMP) {
mMountDirection = eMountDirection;
if (!open(entryNum)) {
return;
}
mVolumeType = 'RARC';
mVolumeName = &mStringTable[mNodes->name_offset];
sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
}
JKRCompArchive::~JKRCompArchive() {
if (mArcInfoBlock != NULL) {
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);
}
file++;
}
JKRFreeToHeap(mHeap, mArcInfoBlock);
mArcInfoBlock = NULL;
}
if (mAramPart != NULL) {
JKRFreeToAram(mAramPart);
}
if (mExpandedSize != NULL) {
JKRFree(mExpandedSize);
mExpandedSize = NULL;
}
if (mDvdFile != NULL) {
delete mDvdFile;
}
sVolumeList.remove(&mFileLoaderLink);
mIsMounted = false;
}
bool JKRCompArchive::open(s32 entryNum) {
mArcInfoBlock = NULL;
field_0x64 = 0;
mAramPart = NULL;
field_0x6c = 0;
mSizeOfMemPart = 0;
mSizeOfAramPart = 0;
field_0x7c = 0;
mNodes = NULL;
mFiles = NULL;
mStringTable = NULL;
mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum);
if(mDvdFile == NULL) {
mMountMode = 0;
return 0;
}
SArcHeader *arcHeader = NULL;
arcHeader = (SArcHeader *)JKRAllocFromSysHeap(sizeof(SArcHeader), -32); // NOTE: unconfirmed if this struct is used
if(arcHeader == NULL) {
mMountMode = 0;
}
else {
int alignment;
JKRDvdToMainRam(entryNum, (u8 *)arcHeader, EXPAND_SWITCH_UNKNOWN1, 32, NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0, &mCompression, NULL);
DCInvalidateRange(arcHeader, 32);
mSizeOfMemPart = arcHeader->field_0x14;
mSizeOfAramPart = arcHeader->field_0x18;
JUT_ASSERT(352, ( mSizeOfMemPart & 0x1f ) == 0);
JUT_ASSERT(353, ( mSizeOfAramPart & 0x1f ) == 0);
switch (mCompression)
{
case COMPRESSION_NONE:
case COMPRESSION_YAZ0:
alignment = mMountDirection == 1 ? 32 : -32;
mArcInfoBlock = (SArcDataInfo *)JKRAllocFromHeap(mHeap, arcHeader->file_data_offset + mSizeOfMemPart, alignment);
if (mArcInfoBlock == NULL) {
mMountMode = 0;
}
else
{
JKRDvdToMainRam(entryNum, (u8 *)mArcInfoBlock, EXPAND_SWITCH_UNKNOWN1, (uintptr_t)arcHeader->file_data_offset + mSizeOfMemPart,
NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0x20, NULL, NULL);
DCInvalidateRange(mArcInfoBlock, (uintptr_t)arcHeader->file_data_offset + mSizeOfMemPart);
field_0x64 = (uintptr_t)mArcInfoBlock + arcHeader->file_data_offset;
if (mSizeOfAramPart != 0) {
mAramPart = (JKRAramBlock*)JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::HEAD);
if(mAramPart == NULL) {
mMountMode = 0;
break;
}
JKRDvdToAram(entryNum, mAramPart->getAddress(), EXPAND_SWITCH_UNKNOWN1, arcHeader->header_length + arcHeader->file_data_offset + mSizeOfMemPart, 0, NULL);
}
mNodes = (SDIDirEntry*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->node_offset);
mFiles = (SDIFileEntry *)((uintptr_t)mArcInfoBlock + mArcInfoBlock->file_entry_offset);
mStringTable = (char*)((uintptr_t)mArcInfoBlock + mArcInfoBlock->string_table_offset);
field_0x6c = arcHeader->header_length + arcHeader->file_data_offset;
}
break;
case COMPRESSION_YAY0:
u32 alignedSize = ALIGN_NEXT(mDvdFile->getFileSize(), 32);
alignment = ((mMountDirection == 1) ? 32 : -32);
u8 *buf = (u8 *)JKRAllocFromSysHeap(alignedSize, -alignment);
if(buf == NULL) {
mMountMode = 0;
}
else {
JKRDvdToMainRam(entryNum, buf, EXPAND_SWITCH_UNKNOWN2, alignedSize, NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0, NULL, NULL);
DCInvalidateRange(buf, alignedSize);
u32 expandSize = ALIGN_NEXT(JKRDecompExpandSize(buf), 32);
u8 *mem = (u8 *)JKRAllocFromHeap(mHeap, expandSize, -alignment);
if(mem == NULL) {
mMountMode = 0;
}
else {
arcHeader = (SArcHeader *)mem;
JKRDecompress((u8 *)buf, (u8 *)mem, expandSize, 0);
JKRFreeToSysHeap(buf);
mArcInfoBlock = (SArcDataInfo *)JKRAllocFromHeap(mHeap, arcHeader->file_data_offset + mSizeOfMemPart, alignment);
if(mArcInfoBlock == NULL) {
mMountMode = 0;
}
else {
// arcHeader + 1 should lead to 0x20, which is the data after the header
JKRHeap::copyMemory((u8 *)mArcInfoBlock, arcHeader + 1, (arcHeader->file_data_offset + mSizeOfMemPart));
field_0x64 = (uintptr_t)mArcInfoBlock + arcHeader->file_data_offset;
if (mSizeOfAramPart != 0) {
mAramPart = (JKRAramBlock*)JKRAllocFromAram(mSizeOfAramPart, JKRAramHeap::HEAD);
if(mAramPart == NULL) {
mMountMode = 0;
}
else {
JKRMainRamToAram((u8 *)mem + arcHeader->header_length + arcHeader->file_data_offset + mSizeOfMemPart,
mAramPart->getAddress(), mSizeOfAramPart, EXPAND_SWITCH_UNKNOWN0, 0, NULL, -1, NULL);
}
}
}
}
}
mNodes = (SDIDirEntry *)((uintptr_t)mArcInfoBlock + mArcInfoBlock->node_offset);
mFiles = (SDIFileEntry *)((uintptr_t)mArcInfoBlock + mArcInfoBlock->file_entry_offset);
mStringTable = (char *)((uintptr_t)mArcInfoBlock + mArcInfoBlock->string_table_offset);
field_0x6c = arcHeader->header_length + arcHeader->file_data_offset;
break;
}
mExpandedSize = NULL;
u8 compressedFiles = 0;
SDIFileEntry *fileEntry = mFiles;
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++)
{
u8 flag = fileEntry->type_flags_and_name_offset >> 0x18;
if (((flag & 0x1) != 0) && (((flag)&0x10) == 0))
{
compressedFiles |= (flag & 4);
}
fileEntry++;
}
if (compressedFiles != 0)
{
mExpandedSize = (s32 *)JKRAllocFromHeap(mHeap, mArcInfoBlock->num_file_entries * 4, abs(alignment));
if (mExpandedSize == NULL)
{
JKRFreeToSysHeap(mArcInfoBlock);
mMountMode = 0;
}
else
{
memset(mExpandedSize, 0, mArcInfoBlock->num_file_entries * 4);
}
}
}
if (arcHeader != NULL)
{
JKRFreeToSysHeap(arcHeader);
}
if (mMountMode == 0) {
OS_REPORT(":::[%s: %d] Cannot alloc memory in mounting CompArchive\n", __FILE__, 567);
if(mDvdFile != NULL) {
delete mDvdFile;
}
return false;
}
return true;
}
void* JKRCompArchive::fetchResource(SDIFileEntry *fileEntry, u32 *pSize) {
JUT_ASSERT(597, isMounted());
u32 ptrSize;
u32 size = fileEntry->data_size;
int compression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 0x18));
if(pSize == NULL) {
pSize = &ptrSize; // this makes barely any sense but ok
}
if (fileEntry->data == NULL) {
u32 flag = fileEntry->type_flags_and_name_offset >> 0x18;
if(flag & 0x10) {
fileEntry->data = (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;
if(compression == COMPRESSION_YAZ0) {
setExpandSize(fileEntry, *pSize);
}
}
else if (flag & 0x40) {
u8 *data;
u32 resSize = JKRDvdArchive::fetchResource_subroutine(mEntryNum, field_0x6c + fileEntry->data_offset, fileEntry->data_size, mHeap, compression, mCompression, &data);
if (pSize != NULL) {
*pSize = resSize;
}
fileEntry->data = data;
if (compression == COMPRESSION_YAZ0) {
setExpandSize(fileEntry, *pSize);
}
}
}
else {
if (pSize != NULL) {
*pSize = fileEntry->data_size;
}
}
return fileEntry->data;
}
void *JKRCompArchive::fetchResource(void *data, u32 compressedSize, SDIFileEntry *fileEntry, u32 *pSize)
{
u32 size = 0;
JUT_ASSERT(708, isMounted());
u32 fileSize = fileEntry->data_size;
u32 alignedSize = ALIGN_NEXT(fileSize, 32);
u32 fileFlag = fileEntry->type_flags_and_name_offset >> 0x18;
int compression = JKRConvertAttrToCompressionType(u8(fileFlag));
if(fileEntry->data != NULL) {
if (compression == COMPRESSION_YAZ0) {
u32 expandSize = getExpandSize(fileEntry);
if (expandSize != 0) {
fileSize = expandSize;
}
}
if (fileSize > compressedSize) {
fileSize = compressedSize;
}
JKRHeap::copyMemory(data, fileEntry->data, fileSize);
size = fileSize;
}
else {
if (fileFlag & 0x10) {
size = JKRMemArchive::fetchResource_subroutine((u8 *)(field_0x64 + fileEntry->data_offset), alignedSize, (u8 *)data,
compressedSize & ~31, compression);
}
else if (fileFlag & 0x20) {
size = JKRAramArchive::fetchResource_subroutine(fileEntry->data_offset + mAramPart->getAddress() - mSizeOfMemPart,
alignedSize, (u8 *)data, compressedSize & ~31, compression);
}
else if (fileFlag & 0x40){
size = JKRDvdArchive::fetchResource_subroutine(mEntryNum, field_0x6c + fileEntry->data_offset, alignedSize, (u8 *)data,
compressedSize & ~31, compression, mCompression);
} else {
JUTException::panic(__FILE__, 776, "illegal archive.");
}
}
if(pSize != NULL) {
*pSize = size;
}
return data;
}
void JKRCompArchive::removeResourceAll() {
if (mArcInfoBlock != NULL && mMountMode != MOUNT_MEM) {
SDIFileEntry* fileEntry = mFiles;
for (int i = 0; i < mArcInfoBlock->num_file_entries; i++) {
int tmp = fileEntry->type_flags_and_name_offset >> 0x18;
if (fileEntry->data != NULL) {
if (!(tmp & 0x10)) {
JKRFreeToHeap(mHeap, fileEntry->data);
}
fileEntry->data = NULL;
}
}
fileEntry++;
}
}
bool JKRCompArchive::removeResource(void* resource) {
SDIFileEntry* fileEntry = findPtrResource(resource);
if (!fileEntry)
return false;
u32 flags = fileEntry->type_flags_and_name_offset >> 24;
if ((flags & 0x10) == 0) {
JKRFreeToHeap(mHeap, resource);
}
fileEntry->data = NULL;
return true;
}
u32 JKRCompArchive::getExpandedResSize(const void *resource) const
{
if (mExpandedSize == NULL) {
return getResSize(resource);
}
SDIFileEntry *fileEntry = findPtrResource(resource);
if(!fileEntry) {
return 0xffffffff;
}
u8 flags = (fileEntry->type_flags_and_name_offset >> 0x18);
if((flags & 4) == 0) { // not compressed
return getResSize(resource);
}
if ((flags & 0x10) != 0) {
u32 expandSize = JKRDecompExpandSize((u8*)resource);
return expandSize;
}
u8 buf[64];
u8 *bufPtr = (u8 *)ALIGN_NEXT((uintptr_t)buf, 32);
if ((flags & 0x20) != 0) {
JKRAramToMainRam(fileEntry->data_offset + mAramPart->getAddress(), bufPtr, sizeof(buf) / 2, EXPAND_SWITCH_UNKNOWN0, 0, NULL, -1, NULL);
DCInvalidateRange(bufPtr, sizeof(buf) / 2);
}
else if ((flags & 0x40) != 0) {
JKRDvdToMainRam(mEntryNum, bufPtr, EXPAND_SWITCH_UNKNOWN2, sizeof(buf) / 2, NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, field_0x6c + fileEntry->data_offset, NULL, NULL);
DCInvalidateRange(bufPtr, sizeof(buf) / 2);
}
else {
JUTException::panic(__FILE__, 943, "illegal resource.");
}
u32 expandSize = JKRDecompExpandSize(bufPtr);
const_cast<JKRCompArchive *>(this)->setExpandSize(fileEntry, expandSize);
return expandSize;
}
+292
View File
@@ -0,0 +1,292 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRAramPiece.h"
#include "global.h"
#if PLATFORM_GCN
const u32 stack_size = 0x800;
#else
const u32 stack_size = 0x4000;
#endif
JKRDecomp* JKRDecomp::sDecompObject;
JKRDecomp* JKRDecomp::create(s32 priority) {
if (!sDecompObject) {
sDecompObject = new (JKRGetSystemHeap(), 0) JKRDecomp(priority);
}
return sDecompObject;
}
OSMessage JKRDecomp::sMessageBuffer[8] = {0};
OSMessageQueue JKRDecomp::sMessageQueue = {0};
JKRDecomp::JKRDecomp(s32 priority) : JKRThread(stack_size, 0x10, priority) {
resume();
}
JKRDecomp::~JKRDecomp() {}
void* JKRDecomp::run() {
OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 8);
for (;;) {
OSMessage message;
OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK);
JKRDecompCommand* command = (JKRDecompCommand*)message;
decode(command->mSrcBuffer, command->mDstBuffer, command->mSrcLength, command->mDstLength);
if (command->field_0x20 != 0) {
if (command->field_0x20 == 1) {
JKRAramPcs_SendCommand(command->mAMCommand);
}
continue;
}
if (command->mCallback) {
(*command->mCallback)((u32)command);
continue;
}
if (command->field_0x1c) {
OSSendMessage(command->field_0x1c, (OSMessage)1, OS_MESSAGE_NOBLOCK);
} else {
OSSendMessage(&command->mMessageQueue, (OSMessage)1, OS_MESSAGE_NOBLOCK);
}
}
}
JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 srcLength,
u32 dstLength,
JKRDecompCommand::AsyncCallback callback) {
JKRDecompCommand* command = new (JKRGetSystemHeap(), -4) JKRDecompCommand();
command->mSrcBuffer = srcBuffer;
command->mDstBuffer = dstBuffer;
command->mSrcLength = srcLength;
command->mDstLength = dstLength;
command->mCallback = callback;
return command;
}
void JKRDecomp::sendCommand(JKRDecompCommand* command) {
int result = OSSendMessage(&sMessageQueue, command, OS_MESSAGE_NOBLOCK);
JUT_ASSERT_MSG(142, result, "Decomp MesgBuf FULL!");
}
JKRDecompCommand* JKRDecomp::orderAsync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength,
JKRDecompCommand::AsyncCallback callback) {
JKRDecompCommand* command =
prepareCommand(srcBuffer, dstBuffer, srcLength, dstLength, callback);
sendCommand(command);
return command;
}
bool JKRDecomp::sync(JKRDecompCommand* command, int isNonBlocking) {
OSMessage message;
if (isNonBlocking == JKRDECOMP_SYNC_BLOCKING) {
OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCK);
return true;
}
bool result;
if (!OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NOBLOCK)) {
result = false;
} else {
result = true;
}
return result;
}
bool JKRDecomp::orderSync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength) {
JKRDecompCommand* command = orderAsync(srcBuffer, dstBuffer, srcLength, dstLength, NULL);
bool result = sync(command, JKRDECOMP_SYNC_BLOCKING);
delete command;
return result;
}
void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength) {
JKRCompression compression = checkCompressed(srcBuffer);
if (compression == COMPRESSION_YAY0) {
decodeSZP(srcBuffer, dstBuffer, srcLength, dstLength);
} else if (compression == COMPRESSION_YAZ0) {
decodeSZS(srcBuffer, dstBuffer, srcLength, dstLength);
}
}
void JKRDecomp::decodeSZP(u8* src, u8* dst, u32 srcLength, u32 dstLength) {
int srcChunkOffset;
int count;
int dstOffset;
u32 length = srcLength;
int linkInfo;
int offset;
int i;
int decodedSize = READU32_BE(src, 4);
int linkTableOffset = READU32_BE(src, 8);
int srcDataOffset = READU32_BE(src, 12);
dstOffset = 0;
u32 counter = 0;
srcChunkOffset = 16;
u32 chunkBits;
if (srcLength == 0)
return;
if (dstLength > decodedSize)
return;
do
{
if (counter == 0)
{
chunkBits = READU32_BE(src, srcChunkOffset);
srcChunkOffset += sizeof(u32);
counter = sizeof(u32) * 8;
}
if (chunkBits & 0x80000000)
{
if (dstLength == 0)
{
dst[dstOffset] = src[srcDataOffset];
length--;
if (length == 0)
return;
}
else
{
dstLength--;
}
dstOffset++;
srcDataOffset++;
}
else
{
linkInfo = src[linkTableOffset] << 8 | src[linkTableOffset + 1];
linkTableOffset += sizeof(u16);
offset = dstOffset - (linkInfo & 0xFFF);
count = (linkInfo >> 12);
if (count == 0)
{
count = (u32)src[srcDataOffset++] + 0x12;
}
else
count += 2;
if (count > decodedSize - dstOffset)
count = decodedSize - dstOffset;
for (i = 0; i < count; i++, dstOffset++, offset++)
{
if (dstLength == 0)
{
dst[dstOffset] = dst[offset - 1];
length--;
if (length == 0)
return;
}
else
dstLength--;
}
}
chunkBits <<= 1;
counter--;
} while (dstOffset < decodedSize);
}
void JKRDecomp::decodeSZS(u8* src_buffer, u8* dst_buffer, u32 srcSize, u32 dstSize) {
u8* decompEnd;
u8* copyStart;
s32 copyByteCount;
s32 chunkBitsLeft = 0;
s32 chunkBits;
decompEnd = dst_buffer + *(int*)(src_buffer + 4) - dstSize;
if (srcSize == 0) {
return;
}
if (dstSize > *(u32*)src_buffer) {
return;
}
u8* curSrcPos = src_buffer + 0x10;
do {
if (chunkBitsLeft == 0) {
chunkBits = curSrcPos[0];
chunkBitsLeft = 8;
curSrcPos++;
}
if ((chunkBits & 0x80) != 0) {
if (dstSize == 0) {
dst_buffer[0] = curSrcPos[0];
srcSize--;
dst_buffer++;
if (srcSize == 0)
return;
} else {
dstSize--;
}
curSrcPos++;
} else {
u32 local_28 = curSrcPos[1] | (curSrcPos[0] & 0xF) << 8;
u32 r31 = curSrcPos[0] >> 4;
curSrcPos += 2;
copyStart = dst_buffer - local_28;
if (r31 == 0) {
copyByteCount = curSrcPos[0] + 0x12;
curSrcPos++;
} else {
copyByteCount = r31 + 2;
}
do {
if (dstSize == 0) {
dst_buffer[0] = copyStart[-1];
srcSize--;
dst_buffer++;
if (srcSize == 0)
return;
} else {
dstSize--;
}
copyByteCount--;
copyStart++;
} while (copyByteCount != 0);
}
chunkBits <<= 1;
chunkBitsLeft--;
} while (dst_buffer != decompEnd);
}
JKRCompression JKRDecomp::checkCompressed(u8* src) {
if ((src[0] == 'Y') && (src[1] == 'a') && (src[3] == '0')) {
if (src[2] == 'y') {
return COMPRESSION_YAY0;
}
if (src[2] == 'z') {
return COMPRESSION_YAZ0;
}
}
if ((src[0] == 'A') && (src[1] == 'S') && (src[2] == 'R')) {
return COMPRESSION_ASR;
}
return COMPRESSION_NONE;
}
JKRDecompCommand::JKRDecompCommand() {
OSInitMessageQueue(&mMessageQueue, &mMessage, 1);
mCallback = NULL;
field_0x1c = NULL;
mThis = this;
field_0x20 = 0;
}
JKRDecompCommand::~JKRDecompCommand() {}
+17
View File
@@ -0,0 +1,17 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRDisposer.h"
#include "JSystem/JKernel/JKRHeap.h"
JKRDisposer::JKRDisposer() : mLink(this) {
mHeap = JKRHeap::findFromRoot(this);
if (mHeap) {
mHeap->appendDisposer(this);
}
}
JKRDisposer::~JKRDisposer() {
if (mHeap) {
mHeap->removeDisposer(this);
}
}
@@ -0,0 +1,477 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRDvdAramRipper.h"
#include "JSystem/JKernel/JKRAram.h"
#include "JSystem/JKernel/JKRAramPiece.h"
#include "JSystem/JKernel/JKRAramStream.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JSupport/JSUFileStream.h"
#include <os.h>
#include <os.h>
#include <vi.h>
#include "global.h"
#include <cstring>
static int JKRDecompressFromDVDToAram(JKRDvdFile*, u32, u32, u32, u32, u32, u32*);
static int decompSZS_subroutine(u8*, u32);
static u8* firstSrcData();
static u8* nextSrcData(u8*);
static u32 dmaBufferFlush(u32);
JKRAramBlock* JKRDvdAramRipper::loadToAram(s32 entryNumber, u32 address,
JKRExpandSwitch expandSwitch, u32 param_3, u32 param_4,
u32* param_5) {
JKRDvdFile dvdFile;
if (!dvdFile.open(entryNumber)) {
return NULL;
} else {
return loadToAram(&dvdFile, address, expandSwitch, param_3, param_4, param_5);
}
}
JKRAramBlock* JKRDvdAramRipper::loadToAram(JKRDvdFile* dvdFile, u32 address,
JKRExpandSwitch expandSwitch, u32 param_3, u32 param_4,
u32* param_5) {
JKRADCommand* command =
loadToAram_Async(dvdFile, address, expandSwitch, NULL, param_3, param_4, param_5);
syncAram(command, 0);
if (command->field_0x48 < 0) {
delete command;
return NULL;
}
if (address) {
delete command;
return (JKRAramBlock*)-1;
}
JKRAramBlock* result = command->mBlock;
delete command;
return result;
}
JKRADCommand* JKRDvdAramRipper::loadToAram_Async(JKRDvdFile* dvdFile, u32 address,
JKRExpandSwitch expandSwitch,
void (*callback)(u32), u32 param_4, u32 param_5,
u32* param_6) {
JKRADCommand* command = new (JKRGetSystemHeap(), -4) JKRADCommand();
command->mDvdFile = dvdFile;
command->mAddress = address;
command->mBlock = NULL;
command->mExpandSwitch = expandSwitch;
command->mCallback = callback;
command->field_0x3c = param_4;
command->field_0x40 = param_5;
command->field_0x44 = param_6;
JKRADCommand* cmd2 = callCommand_Async(command);
if (!cmd2) {
delete command;
return NULL;
}
return command;
}
JSUList<JKRADCommand> JKRDvdAramRipper::sDvdAramAsyncList;
bool JKRDvdAramRipper::errorRetry = true;
JKRADCommand* JKRDvdAramRipper::callCommand_Async(JKRADCommand* command) {
s32 compression;
s32 uncompressedSize;
bool bVar1 = true;
JKRDvdFile* dvdFile = command->mDvdFile;
compression = 0;
OSLockMutex(&dvdFile->mMutex2);
if (command->field_0x44) {
*command->field_0x44 = 0;
}
if (dvdFile->field_0x50) {
bVar1 = false;
} else {
dvdFile->field_0x50 = OSGetCurrentThread();
JSUFileInputStream* stream = new (JKRGetSystemHeap(), -4) JSUFileInputStream(dvdFile);
dvdFile->mFileStream = stream;
u32 fileSize = dvdFile->getFileSize();
if (command->field_0x40 && fileSize > command->field_0x40) {
fileSize = command->field_0x40;
}
fileSize = ALIGN_NEXT(fileSize, 0x20);
if (command->mExpandSwitch == 1) {
u8 buffer[0x40];
u8* bufPtr = (u8*)ALIGN_NEXT((u32)&buffer, 0x20);
while (true) {
s32 result = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 0x20, 0, 2);
if (result >= 0) {
break;
}
if (JKRDvdAramRipper::errorRetry == 0) {
delete stream;
return NULL;
}
VIWaitForRetrace();
}
DCInvalidateRange(bufPtr, 0x20);
compression = JKRCheckCompressed_noASR(bufPtr);
u32 expandSize = JKRDecompExpandSize(bufPtr);
uncompressedSize = expandSize;
if (command->field_0x40 && uncompressedSize > command->field_0x40) {
uncompressedSize = command->field_0x40;
}
}
if (compression == 0) {
command->mExpandSwitch = EXPAND_SWITCH_UNKNOWN0;
}
if (command->mExpandSwitch == EXPAND_SWITCH_UNKNOWN1) {
if (command->mAddress == 0 && command->mBlock == NULL) {
command->mBlock = JKRAllocFromAram(uncompressedSize, JKRAramHeap::HEAD);
if (command->mBlock) {
command->mAddress = command->mBlock->getAddress();
}
dvdFile->mBlock = command->mBlock;
}
if (command->mBlock) {
command->mAddress = command->mBlock->getAddress();
}
if (command->mAddress == 0) {
dvdFile->field_0x50 = NULL;
return NULL;
}
} else {
if (command->mAddress == 0 && !command->mBlock) {
command->mBlock = JKRAllocFromAram(fileSize, JKRAramHeap::HEAD);
}
if (command->mBlock) {
command->mAddress = command->mBlock->getAddress();
}
if (command->mAddress == 0) {
dvdFile->field_0x50 = NULL;
return NULL;
}
}
if (compression == 0) {
command->mStreamCommand =
JKRStreamToAram_Async(stream, command->mAddress, fileSize - command->field_0x3c,
command->field_0x3c, NULL, command->field_0x44);
} else if (compression == 1) {
command->mStreamCommand =
JKRStreamToAram_Async(stream, command->mAddress, fileSize - command->field_0x3c,
command->field_0x3c, NULL, command->field_0x44);
} else if (compression == 2) {
command->mStreamCommand = NULL;
JKRDecompressFromDVDToAram(command->mDvdFile, command->mAddress, fileSize,
uncompressedSize, command->field_0x3c, 0,
command->field_0x44);
}
if (!command->mCallback) {
(*((JSUList<JKRADCommand>*)&sDvdAramAsyncList)).append(&command->mLink);
} else {
command->mCallback((u32)command);
}
}
OSUnlockMutex(&dvdFile->mMutex2);
return bVar1 == true ? command : NULL;
}
bool JKRDvdAramRipper::syncAram(JKRADCommand* command, int param_1) {
JKRDvdFile* dvdFile = command->mDvdFile;
OSLockMutex(&dvdFile->mMutex2);
if (command->mStreamCommand) {
JKRAramStreamCommand* var1 = JKRStreamToAram_Sync(command->mStreamCommand, param_1);
command->field_0x48 = (var1) ? 0 : -1;
if (param_1 != 0 && var1 == NULL) {
OSUnlockMutex(&dvdFile->mMutex2);
return false;
}
}
(*((JSUList<JKRADCommand>*)&sDvdAramAsyncList)).remove(&command->mLink);
if (command->mStreamCommand) {
delete command->mStreamCommand;
}
delete dvdFile->mFileStream;
dvdFile->field_0x50 = NULL;
OSUnlockMutex(&dvdFile->mMutex2);
return true;
}
JKRADCommand::JKRADCommand() : mLink(this) {
field_0x48 = 0;
field_0x4c = 0;
}
JKRADCommand::~JKRADCommand() {
if (field_0x4c == 1) {
delete mDvdFile;
}
}
static OSMutex decompMutex;
u32 JKRDvdAramRipper::sSZSBufferSize = 0x00000400;
static u8* szpBuf;
static u8* szpEnd;
static u8* refBuf;
static u8* refEnd;
static u8* refCurrent;
static u8* dmaBuf;
static u8* dmaEnd;
static u8* dmaCurrent;
static u32 srcOffset;
static u32 transLeft;
static u8* srcLimit;
static JKRDvdFile* srcFile;
static u32 fileOffset;
static int readCount;
static u32 maxDest;
static bool data_804514A4;
static u32* tsPtr;
static u32 tsArea;
int JKRDecompressFromDVDToAram(JKRDvdFile* dvdFile, u32 param_1, u32 fileSize, u32 uncompressedSize,
u32 param_4, u32 param_5, u32* param_6) {
BOOL level = OSDisableInterrupts();
if (!data_804514A4) {
OSInitMutex(&decompMutex);
data_804514A4 = true;
}
OSRestoreInterrupts(level);
OSLockMutex(&decompMutex);
int result = 0;
u32 bufferSize = JKRDvdAramRipper::getSZSBufferSize();
szpBuf = (u8*)JKRAllocFromSysHeap(bufferSize, 0x20);
JUT_ASSERT(755, szpBuf);
szpEnd = szpBuf + bufferSize;
refBuf = (u8*)JKRAllocFromSysHeap(0x1120, 0);
JUT_ASSERT(763, refBuf);
refEnd = refBuf + 0x1120;
refCurrent = refBuf;
dmaBuf = (u8*)JKRAllocFromSysHeap(0x100, 0x20);
JUT_ASSERT(772, dmaBuf);
dmaEnd = dmaBuf + 0x100;
dmaCurrent = dmaBuf;
srcFile = dvdFile;
srcOffset = param_5;
transLeft = fileSize - srcOffset;
fileOffset = param_4;
readCount = 0;
maxDest = uncompressedSize;
tsPtr = param_6 ? param_6 : &tsArea;
*tsPtr = 0;
u8* first = firstSrcData();
if (first) {
result = decompSZS_subroutine(first, param_1);
} else {
result = -1;
}
JKRFree(szpBuf);
JKRFree(refBuf);
JKRFree(dmaBuf);
OSUnlockMutex(&decompMutex);
return result;
}
static int decompSZS_subroutine(u8* src, u32 dest) {
u32 endAddr;
u8* copySource;
s32 validBitCount;
u32 currCodeByte;
s32 numBytes;
u32 var_r26;
u32 startDest;
validBitCount = 0;
currCodeByte = 0;
var_r26 = 0;
startDest = dest;
if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') {
return -1;
}
SYaz0Header* header = (SYaz0Header*)src;
endAddr = dest + (header->length - fileOffset);
if (endAddr > dest + maxDest) {
endAddr = dest + maxDest;
}
src += 0x10;
s32 b1;
u32 dist;
do {
if (validBitCount == 0) {
if ((src > srcLimit) && transLeft) {
src = nextSrcData(src);
}
currCodeByte = *src;
validBitCount = 8;
src++;
}
if (currCodeByte & 0x80) {
if (readCount >= fileOffset) {
*(dmaCurrent++) = *src;
dest++;
var_r26++;
if (dmaCurrent == dmaEnd) {
startDest += dmaBufferFlush(startDest);
}
if (dest == endAddr) {
break;
}
}
*(refCurrent++) = *src;
if (refCurrent == refEnd) {
refCurrent = refBuf;
}
src++;
readCount++;
} else {
b1 = src[0];
dist = src[1] | ((b1 & 0x0f) << 8);
numBytes = b1 >> 4;
src += 2;
copySource = refCurrent - dist - 1;
if (copySource < refBuf) {
copySource += refEnd - refBuf;
}
if (numBytes == 0) {
numBytes = *(src++);
numBytes += 0x12;
} else {
numBytes += 2;
}
do {
if (readCount >= fileOffset) {
*(dmaCurrent++) = *copySource;
dest++;
var_r26++;
if (dmaCurrent == dmaEnd) {
startDest += dmaBufferFlush(startDest);
}
if (dest == endAddr) {
break;
}
}
*(refCurrent++) = *copySource;
if (refCurrent == refEnd) {
refCurrent = refBuf;
}
copySource++;
if (copySource == refEnd) {
copySource = refBuf;
}
readCount++;
numBytes--;
} while (numBytes != 0);
}
currCodeByte <<= 1;
validBitCount--;
} while (dest < endAddr);
dmaBufferFlush(startDest);
*tsPtr = var_r26;
return 0;
}
static u8* firstSrcData() {
srcLimit = szpEnd - 0x19;
u8* buffer = szpBuf;
u32 bufSize = szpEnd - buffer;
u32 length = transLeft < bufSize ? transLeft : bufSize;
while (true) {
int result = DVDReadPrio(srcFile->getFileInfo(), buffer, length, 0, 2);
if (result >= 0) {
break;
}
if (!JKRDvdAramRipper::isErrorRetry()) {
return NULL;
}
VIWaitForRetrace();
}
srcOffset += length;
transLeft -= length;
return buffer;
}
static u8* nextSrcData(u8* src) {
u32 size = szpEnd - src;
u8* dest;
if (IS_NOT_ALIGNED(size, 0x20)) {
dest = szpBuf + 0x20 - (size & (0x20 - 1));
} else {
dest = szpBuf;
}
memcpy(dest, src, size);
u32 transSize = szpEnd - (dest + size);
if (transSize > transLeft) {
transSize = transLeft;
}
JUT_ASSERT(1036, transSize > 0);
while (true) {
s32 result = DVDReadPrio(srcFile->getFileInfo(), dest + size, transSize, srcOffset, 2);
if (result >= 0) {
break;
}
if (!JKRDvdAramRipper::isErrorRetry()) {
return NULL;
}
VIWaitForRetrace();
}
srcOffset += transSize;
transLeft -= transSize;
if (transLeft == 0) {
srcLimit = dest + size + transSize;
}
return dest;
}
static u32 dmaBufferFlush(u32 param_1) {
if (dmaCurrent == dmaBuf) {
return 0;
}
u32 size = ALIGN_NEXT(dmaCurrent - dmaBuf, 0x20);
JKRAramPcs(0, (u32)dmaBuf, param_1, size, NULL);
dmaCurrent = dmaBuf;
return size;
}
+371
View File
@@ -0,0 +1,371 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRDvdArchive.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JKernel/JKRDvdRipper.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTException.h"
#include <cmath>
#include <cstring>
#include "global.h"
#include <stdint.h>
JKRDvdArchive::JKRDvdArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
: JKRArchive(entryNum, MOUNT_DVD) {
mMountDirection = mountDirection;
if (!open(entryNum))
return;
mVolumeType = 'RARC';
mVolumeName = mStringTable + mNodes->name_offset;
sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
}
JKRDvdArchive::~JKRDvdArchive() {
if (mIsMounted == true) {
if (mArcInfoBlock) {
SDIFileEntry* fileEntry = mFiles;
int i = 0;
for (; i < mArcInfoBlock->num_file_entries; i++) {
if (fileEntry->data) {
JKRFreeToHeap(mHeap, fileEntry->data);
}
fileEntry++;
}
JKRFreeToHeap(mHeap, mArcInfoBlock);
mArcInfoBlock = NULL;
}
if (mExpandedSize) {
JKRFree(mExpandedSize);
mExpandedSize = NULL;
}
if (mDvdFile) {
delete mDvdFile;
}
sVolumeList.remove(&mFileLoaderLink);
mIsMounted = false;
}
}
bool JKRDvdArchive::open(s32 entryNum) {
mArcInfoBlock = NULL;
mDataOffset = 0;
mNodes = NULL;
mFiles = NULL;
mStringTable = NULL;
mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum);
if (!mDvdFile) {
mMountMode = UNKNOWN_MOUNT_MODE;
return false;
}
SArcHeader* arcHeader = NULL;
arcHeader = (SArcHeader*)JKRAllocFromSysHeap(sizeof(SArcHeader), 0x20);
if (!arcHeader) {
mMountMode = UNKNOWN_MOUNT_MODE;
goto cleanup;
}
JKRDvdToMainRam(entryNum, (u8*)arcHeader, EXPAND_SWITCH_UNKNOWN1, sizeof(SArcHeader), NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, 0, &mCompression, NULL);
DCInvalidateRange(arcHeader, sizeof(SArcHeader));
int alignment;
alignment = mMountDirection == MOUNT_DIRECTION_HEAD ? 0x20 : -0x20;
mArcInfoBlock = (SArcDataInfo*)JKRAllocFromHeap(mHeap, arcHeader->file_data_offset, alignment);
if (!mArcInfoBlock) {
mMountMode = UNKNOWN_MOUNT_MODE;
goto cleanup;
}
JKRDvdToMainRam(entryNum, (u8*)mArcInfoBlock, EXPAND_SWITCH_UNKNOWN1,
arcHeader->file_data_offset, NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
sizeof(SArcHeader), NULL, NULL);
DCInvalidateRange(mArcInfoBlock, arcHeader->file_data_offset);
mNodes = (SDIDirEntry*)((intptr_t)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
mFiles = (SDIFileEntry*)((intptr_t)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset);
mStringTable = (char*)((intptr_t)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset);
mExpandedSize = NULL;
u8 useCompression;
useCompression = 0;
SDIFileEntry* fileEntry;
fileEntry = mFiles;
for (u32 i = 0; i < mArcInfoBlock->num_file_entries; i++, fileEntry++) {
u8 flags = fileEntry->type_flags_and_name_offset >> 24;
if (flags & 1) {
useCompression |= u8(flags & 4);
}
}
if (useCompression) {
mExpandedSize = (s32*)JKRAllocFromHeap(mHeap, sizeof(s32) * mArcInfoBlock->num_file_entries,
abs(alignment));
if (!mExpandedSize) {
// !@bug: mArcInfoBlock is allocated from mHeap but free'd to sSystemHeap. I don't know
// what will happen if mHeap != sSystemHeap, but it's still a bug to free to the wrong
// allocator.
JKRFreeToSysHeap(mArcInfoBlock);
mMountMode = UNKNOWN_MOUNT_MODE;
goto cleanup;
}
memset(mExpandedSize, 0, sizeof(s32) * mArcInfoBlock->num_file_entries);
}
mDataOffset = arcHeader->header_length + arcHeader->file_data_offset;
cleanup:
if (arcHeader) {
JKRFreeToSysHeap(arcHeader);
}
if (mMountMode == UNKNOWN_MOUNT_MODE) {
OS_REPORT(":::Cannot alloc memory [%s][%d]\n", __FILE__, 397);
if (mDvdFile) {
delete mDvdFile;
}
return false;
}
return true;
}
void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) {
JUT_ASSERT(428, isMounted());
u32 tempReturnSize;
if (returnSize == NULL) {
returnSize = &tempReturnSize;
}
JKRCompression fileCompression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 24));
if (!fileEntry->data) {
u8* resourcePtr;
u32 resourceSize = fetchResource_subroutine(
mEntryNum, mDataOffset + fileEntry->data_offset, fileEntry->data_size, mHeap,
fileCompression, mCompression, &resourcePtr);
*returnSize = resourceSize;
if (resourceSize == 0) {
return NULL;
}
fileEntry->data = resourcePtr;
if (fileCompression == COMPRESSION_YAZ0) {
setExpandSize(fileEntry, *returnSize);
}
} else {
if (fileCompression == COMPRESSION_YAZ0) {
*returnSize = getExpandSize(fileEntry);
} else {
*returnSize = fileEntry->data_size;
}
}
return fileEntry->data;
}
void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
u32* returnSize) {
JUT_ASSERT(504, isMounted());
u32 size = fileEntry->data_size;
JKRCompression fileCompression = JKRConvertAttrToCompressionType(u8(fileEntry->type_flags_and_name_offset >> 24));
if (!fileEntry->data) {
bufferSize = (s32)ALIGN_PREV(bufferSize, 0x20);
size = fetchResource_subroutine(mEntryNum, mDataOffset + fileEntry->data_offset,
fileEntry->data_size, (u8*)buffer, bufferSize, fileCompression,
mCompression);
} else {
if (fileCompression == COMPRESSION_YAZ0) {
u32 expandSize = getExpandSize(fileEntry);
if (expandSize) {
size = expandSize;
}
}
if (size > bufferSize) {
size = bufferSize;
}
JKRHeap::copyMemory(buffer, fileEntry->data, size);
}
if (returnSize) {
*returnSize = size;
}
return buffer;
}
u32 JKRDvdArchive::fetchResource_subroutine(s32 entryNum, u32 offset, u32 size, u8* dst,
u32 dstLength, JKRCompression fileCompression,
JKRCompression archiveCompression) {
u32 alignedSize = ALIGN_NEXT(size, 0x20);
u32 alignedDstLength = ALIGN_PREV(dstLength, 0x20);
switch (archiveCompression) {
case COMPRESSION_NONE: {
switch (fileCompression) {
case COMPRESSION_NONE:
if (alignedSize > alignedDstLength) {
alignedSize = alignedDstLength;
}
JKRDvdToMainRam(entryNum, dst, EXPAND_SWITCH_UNKNOWN0, alignedSize, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(dst, alignedSize);
return alignedSize;
case COMPRESSION_YAY0:
case COMPRESSION_YAZ0:
// The dst pointer to JKRDvdToMainRam should be aligned to 32 bytes. This will align
// arcHeader to 32 bytes on the stack.
char arcHeaderBuffer[64];
u8* arcHeader = (u8*)ALIGN_NEXT((uintptr_t)arcHeaderBuffer, 0x20);
JKRDvdToMainRam(entryNum, arcHeader, EXPAND_SWITCH_UNKNOWN2, sizeof(SArcHeader),
NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(arcHeader, sizeof(SArcHeader));
u32 decompressedSize = JKRDecompExpandSize(arcHeader);
u32 alignedDecompressedSize = ALIGN_NEXT(decompressedSize, 0x20);
if (alignedDecompressedSize > alignedDstLength) {
alignedDecompressedSize = alignedDstLength;
}
JKRDvdToMainRam(entryNum, dst, EXPAND_SWITCH_UNKNOWN1, alignedDecompressedSize, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(dst, alignedDecompressedSize);
return decompressedSize;
}
}
case COMPRESSION_YAZ0: {
if (size > alignedDstLength) {
size = alignedDstLength;
}
JKRDvdToMainRam(entryNum, dst, EXPAND_SWITCH_UNKNOWN1, size, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(dst, size);
return size;
}
case COMPRESSION_YAY0: {
JUTException::panic(__FILE__, 649, "Sorry, not applied for SZP archive.\n");
}
default: {
JUTException::panic(__FILE__, 653, "??? bad sequence\n");
return 0;
}
}
}
u32 JKRDvdArchive::fetchResource_subroutine(s32 entryNum, u32 offset, u32 size, JKRHeap* heap,
JKRCompression fileCompression,
JKRCompression archiveCompression,
u8** returnResource) {
u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* buffer;
switch (archiveCompression) {
case COMPRESSION_NONE: {
switch (fileCompression) {
case COMPRESSION_NONE:
buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, sizeof(SArcHeader));
JUT_ASSERT(675, buffer != NULL);
JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_UNKNOWN0, alignedSize, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(buffer, alignedSize);
*returnResource = buffer;
return alignedSize;
case COMPRESSION_YAY0:
case COMPRESSION_YAZ0:
// The dst pointer to JKRDvdToMainRam should be aligned to 32 bytes. This will align
// arcHeader to 32 bytes on the stack.
char arcHeaderBuffer[64];
u8* arcHeader = (u8*)ALIGN_NEXT((uintptr_t)arcHeaderBuffer, 0x20);
JKRDvdToMainRam(entryNum, arcHeader, EXPAND_SWITCH_UNKNOWN2, sizeof(SArcHeader),
NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(arcHeader, sizeof(SArcHeader));
alignedSize = JKRDecompExpandSize(arcHeader);
buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, sizeof(SArcHeader));
JUT_ASSERT(715, buffer);
JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_UNKNOWN1, alignedSize, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(buffer, alignedSize);
*returnResource = buffer;
return alignedSize;
}
}
case COMPRESSION_YAZ0: {
buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, sizeof(SArcHeader));
JUT_ASSERT(735, buffer);
JKRDvdToMainRam(entryNum, buffer, EXPAND_SWITCH_UNKNOWN1, size, NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(buffer, size);
*returnResource = buffer;
return alignedSize;
}
case COMPRESSION_YAY0: {
JUTException::panic(__FILE__, 754, "Sorry, not applied SZP archive.\n");
}
default: {
JUTException::panic(__FILE__, 758, "??? bad sequence\n");
return 0;
}
}
}
u32 JKRDvdArchive::getExpandedResSize(const void* resource) const {
u32 resourceSize;
if (!mExpandedSize) {
return getResSize(resource);
}
SDIFileEntry* fileEntry = findPtrResource(resource);
if (!fileEntry) {
return -1;
}
u8 flags = fileEntry->type_flags_and_name_offset >> 24;
if ((flags & 4) == 0) {
return getResSize(resource);
}
resourceSize = getExpandSize(fileEntry);
if (resourceSize) {
return resourceSize;
}
// The dst pointer to JKRDvdToMainRam should be aligned to 32 bytes. This will align arcHeader
// to 32 bytes on the stack.
char buffer[64];
u8* arcHeader = (u8*)ALIGN_NEXT((uintptr_t)buffer, 0x20);
JKRDvdToMainRam(mEntryNum, arcHeader, EXPAND_SWITCH_UNKNOWN2, sizeof(SArcHeader), NULL,
JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
mDataOffset + fileEntry->data_offset, NULL, NULL);
DCInvalidateRange(arcHeader, sizeof(SArcHeader));
u32 expandSize = JKRDecompExpandSize(arcHeader);
// ???
((JKRDvdArchive*)this)->setExpandSize(fileEntry, expandSize);
return expandSize;
}
+133
View File
@@ -0,0 +1,133 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTException.h"
#include <stdint.h>
JSUList<JKRDvdFile> JKRDvdFile::sDvdList;
JKRDvdFile::JKRDvdFile() : mDvdLink(this) {
initiate();
}
JKRDvdFile::JKRDvdFile(const char* name) : mDvdLink(this) {
initiate();
mIsAvailable = open(name);
// weird code. doesn't match without this, maybe remains from assert or something?
if (!mIsAvailable)
return;
else
return;
}
JKRDvdFile::JKRDvdFile(s32 entryNum) : mDvdLink(this) {
initiate();
mIsAvailable = open(entryNum);
// weird code. doesn't match without this, maybe remains from assert or something?
if (!mIsAvailable)
return;
else
return;
}
JKRDvdFile::~JKRDvdFile() {
close();
}
void JKRDvdFile::initiate(void) {
mDvdFile = this;
OSInitMutex(&mMutex1);
OSInitMutex(&mMutex2);
OSInitMessageQueue(&mMessageQueue2, &mMessage2, 1);
OSInitMessageQueue(&mMessageQueue1, &mMessage1, 1);
mOSThread = NULL;
field_0x50 = 0;
field_0x58 = 0;
}
bool JKRDvdFile::open(const char* name) {
if (!mIsAvailable) {
mIsAvailable = DVDOpen(name, &mFileInfo);
if (mIsAvailable) {
sDvdList.append(&mDvdLink);
getStatus();
}
}
return mIsAvailable;
}
bool JKRDvdFile::open(s32 entryNum) {
if (!mIsAvailable) {
mIsAvailable = DVDFastOpen(entryNum, &mFileInfo);
if (mIsAvailable) {
sDvdList.append(&mDvdLink);
getStatus();
}
}
return mIsAvailable;
}
void JKRDvdFile::close() {
if (mIsAvailable) {
if (DVDClose(&mFileInfo) != 0) {
mIsAvailable = false;
sDvdList.remove(&mDvdLink);
} else {
JUTException::panic(__FILE__, 213, "cannot close DVD file\n");
}
}
}
s32 JKRDvdFile::readData(void* param_1, s32 length, s32 param_3) {
/* clang-format off */
// The assert condition gets stringified as "( length & 0x1f ) == 0",
// with out disabling clang-format the spaces in the condition will
// get removed and the string will be incorrect.
JUT_ASSERT(238, ( length & 0x1f ) == 0);
/* clang-format on */
OSLockMutex(&mMutex1);
if (mOSThread) {
OSUnlockMutex(&mMutex1);
return -1;
}
mOSThread = OSGetCurrentThread();
s32 result = -1;
if (DVDReadAsyncPrio(&mFileInfo, param_1, length, param_3, JKRDvdFile::doneProcess, 2)) {
result = sync();
}
mOSThread = NULL;
OSUnlockMutex(&mMutex1);
return result;
}
s32 JKRDvdFile::writeData(void const* param_0, s32 length, s32 param_2) {
/* clang-format off */
JUT_ASSERT(344, ( length & 0x1f ) == 0);
/* clang-format on */
return -1;
}
s32 JKRDvdFile::sync(void) {
OSMessage message;
OSLockMutex(&mMutex1);
OSReceiveMessage(&mMessageQueue2, &message, 1);
mOSThread = NULL;
OSUnlockMutex(&mMutex1);
return (intptr_t)message;
}
void JKRDvdFile::doneProcess(s32 id, DVDFileInfo* fileInfo) {
// fileInfo->field_0x3c looks like some kind of user pointer?
JKRDvdFile* dvdFile = *(JKRDvdFile**)((u8*)fileInfo + 0x3c);
OSSendMessage(&dvdFile->mMessageQueue2, (OSMessage)(intptr_t)id, OS_MESSAGE_NOBLOCK);
}
s32 JKRDvdFile::getFileSize(void) const {
return mFileInfo.length;
}
+494
View File
@@ -0,0 +1,494 @@
//
// JKRDvdRipper
//
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRDvdRipper.h"
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JUtility/JUTException.h"
#include <cstring>
#include <os.h>
#include <vi.h>
#include <stdint.h>
static int JKRDecompressFromDVD(JKRDvdFile*, void*, u32, u32, u32, u32, u32*);
static int decompSZS_subroutine(u8*, u8*);
static u8* firstSrcData();
static u8* nextSrcData(u8*);
void* JKRDvdRipper::loadToMainRAM(char const* name, u8* dst, JKRExpandSwitch expandSwitch,
u32 dstLength, JKRHeap* heap,
JKRDvdRipper::EAllocDirection allocDirection, u32 offset,
int* pCompression, u32* param_8) {
JKRDvdFile file;
if (!file.open(name)) {
return NULL;
}
return JKRDvdToMainRam(&file, dst, expandSwitch, dstLength, heap, allocDirection, offset,
pCompression, param_8);
}
void* JKRDvdRipper::loadToMainRAM(s32 entryNumber, u8* dst, JKRExpandSwitch expandSwitch,
u32 dstLength, JKRHeap* heap,
JKRDvdRipper::EAllocDirection allocDirection, u32 offset,
int* pCompression, u32* param_8) {
JKRDvdFile file;
if (!file.open(entryNumber)) {
return NULL;
}
return JKRDvdToMainRam(&file, dst, expandSwitch, dstLength, heap, allocDirection, offset,
pCompression, param_8);
}
bool JKRDvdRipper::errorRetry = true;
void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* dvdFile, u8* dst, JKRExpandSwitch expandSwitch,
u32 dstLength, JKRHeap* heap,
JKRDvdRipper::EAllocDirection allocDirection, u32 offset,
int* pCompression, u32* param_8) {
s32 fileSizeAligned;
bool hasAllocated = false;
JKRCompression compression = COMPRESSION_NONE;
u32 expandSize;
u8 *mem = NULL;
fileSizeAligned = ALIGN_NEXT(dvdFile->getFileSize(), 32);
if (expandSwitch == EXPAND_SWITCH_UNKNOWN1)
{
u8 buffer[0x40];
u8 *bufPtr = (u8 *)ALIGN_NEXT((uintptr_t)buffer, 32);
while (true)
{
int readBytes = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 0x20, 0, 2);
if (readBytes >= 0)
break;
if (readBytes == -3 || errorRetry == false)
return NULL;
VIWaitForRetrace();
}
DCInvalidateRange(bufPtr, 0x20);
compression = JKRCheckCompressed_noASR(bufPtr);
expandSize = JKRDecompExpandSize(bufPtr);
}
if (pCompression)
*pCompression = (int)compression;
if (expandSwitch == EXPAND_SWITCH_UNKNOWN1 && compression != COMPRESSION_NONE)
{
if (dstLength != 0 && expandSize > dstLength)
{
expandSize = dstLength;
}
if (dst == NULL)
{
dst = (u8 *)JKRAllocFromHeap(heap, expandSize, allocDirection == ALLOC_DIRECTION_FORWARD ? 32 : -32);
hasAllocated = true;
}
if (dst == NULL)
return NULL;
if (compression == COMPRESSION_YAY0)
{
mem = (u8 *)JKRAllocFromHeap((heap), fileSizeAligned, 32);
if (mem == NULL)
{
if (hasAllocated == true)
{
JKRFree(dst);
return NULL;
}
}
}
}
else
{
if (dst == NULL)
{
u32 size = fileSizeAligned - offset;
if ((dstLength != 0) && (size > dstLength))
size = dstLength;
dst = (u8 *)JKRAllocFromHeap(heap, size, allocDirection == ALLOC_DIRECTION_FORWARD ? 32 : -32);
hasAllocated = true;
}
if (dst == NULL)
return NULL;
}
if (compression == COMPRESSION_NONE)
{
JKRCompression compression2 = COMPRESSION_NONE; // maybe for a sub archive?
if (offset != 0)
{
u8 buffer[0x40];
u8 *bufPtr = (u8 *)ALIGN_NEXT((uintptr_t)buffer, 32);
while (true)
{
int readBytes = DVDReadPrio(dvdFile->getFileInfo(), bufPtr, 32, (s32)offset, 2);
if (readBytes >= 0)
break;
if (readBytes == -3 || !errorRetry)
{
if (hasAllocated == true)
{
JKRFree(dst);
}
return NULL;
}
VIWaitForRetrace();
}
DCInvalidateRange(bufPtr, 32);
compression2 = JKRCheckCompressed_noASR(bufPtr);
}
if ((compression2 == COMPRESSION_NONE || expandSwitch == EXPAND_SWITCH_UNKNOWN2) || expandSwitch == EXPAND_SWITCH_UNKNOWN0)
{
s32 size = fileSizeAligned - offset;
if (dstLength != 0 && dstLength < size)
size = dstLength; // probably a ternary
while (true)
{
int readBytes = DVDReadPrio(dvdFile->getFileInfo(), dst, size, (s32)offset, 2);
if (readBytes >= 0)
break;
if (readBytes == -3 || !errorRetry)
{
if (hasAllocated == true)
JKRFree(dst);
return NULL;
}
VIWaitForRetrace();
}
if (param_8)
{
*param_8 = size;
}
return dst;
}
else if (compression2 == COMPRESSION_YAZ0)
{
JKRDecompressFromDVD(dvdFile, dst, fileSizeAligned, dstLength, 0, offset, param_8);
} else {
JUTException::panic(__FILE__, 0x143, "Sorry, not applied for SZP archive.");
}
return dst;
}
else if (compression == COMPRESSION_YAY0)
{
// SZP decompression
// s32 readoffset = startOffset;
if (offset != 0)
{
JUTException::panic(__FILE__, 0x14d, "Not support SZP with offset read");
}
while (true)
{
int readBytes = DVDReadPrio(dvdFile->getFileInfo(), mem, fileSizeAligned, 0, 2);
if (readBytes >= 0)
break;
if (readBytes == -3 || !errorRetry)
{
if (hasAllocated == true)
JKRFree(dst);
JKRFree(mem);
return NULL;
}
VIWaitForRetrace();
}
DCInvalidateRange(mem, fileSizeAligned);
JKRDecompress(mem, dst, expandSize, offset);
JKRFree(mem);
if (param_8)
{
*param_8 = expandSize;
}
return dst;
}
else if (compression == COMPRESSION_YAZ0)
{
u32 result = JKRDecompressFromDVD(dvdFile, dst, fileSizeAligned, expandSize, offset, 0, param_8);
if (result != 0u)
{
if (hasAllocated)
JKRFree(dst);
dst = NULL;
}
return dst;
}
else if (hasAllocated)
{
JKRFree(dst);
dst = NULL;
}
return NULL;
}
static u8 lit_491[12];
JSUList<JKRDMCommand> JKRDvdRipper::sDvdAsyncList;
static OSMutex decompMutex;
u32 JKRDvdRipper::sSZSBufferSize = 0x00000400;
static u8* szpBuf;
static u8* szpEnd;
static u8* refBuf;
static u8* refEnd;
static u8* refCurrent;
static u32 srcOffset;
static u32 transLeft;
static u8* srcLimit;
static JKRDvdFile* srcFile;
static u32 fileOffset;
static u32 readCount;
static u32 maxDest;
static bool data_80451458;
static u32* tsPtr;
static u32 tsArea;
static int JKRDecompressFromDVD(JKRDvdFile* dvdFile, void* dst, u32 fileSize, u32 inMaxDest,
u32 inFileOffset, u32 inSrcOffset, u32* inTsPtr) {
BOOL interrupts = OSDisableInterrupts();
if (data_80451458 == false)
{
OSInitMutex(&decompMutex);
data_80451458 = true;
}
OSRestoreInterrupts(interrupts);
OSLockMutex(&decompMutex);
u32 result = 0;
u32 szsBufferSize = JKRDvdRipper::getSZSBufferSize();
szpBuf = (u8 *)JKRAllocFromSysHeap(szsBufferSize, -0x20);
JUT_ASSERT(909, szpBuf != NULL);
szpEnd = szpBuf + szsBufferSize;
if (inFileOffset != 0) {
refBuf = (u8 *)JKRAllocFromSysHeap(0x1120, -4);
JUT_ASSERT(918, refBuf != NULL);
refEnd = refBuf + 0x1120;
refCurrent = refBuf;
} else {
refBuf = NULL;
}
srcFile = dvdFile;
srcOffset = inSrcOffset;
transLeft = fileSize - srcOffset;
fileOffset = inFileOffset;
readCount = 0;
maxDest = inMaxDest;
tsPtr = inTsPtr ? inTsPtr : &tsArea;
*tsPtr = 0;
u8 *data = firstSrcData();
if (data != NULL) {
result = decompSZS_subroutine(data, (u8 *)dst);
} else {
result = -1;
}
JKRFree(szpBuf);
if (refBuf)
{
JKRFree(refBuf);
}
DCStoreRangeNoSync(dst, *tsPtr);
OSUnlockMutex(&decompMutex);
return result;
}
int decompSZS_subroutine(u8* src, u8* dest) {
u8* endPtr;
s32 validBitCount = 0;
s32 currCodeByte = 0;
u32 ts = 0;
if (src[0] != 'Y' || src[1] != 'a' || src[2] != 'z' || src[3] != '0') {
return -1;
}
SYaz0Header* header = (SYaz0Header*)src;
endPtr = dest + (header->length - fileOffset);
if (endPtr > dest + maxDest) {
endPtr = dest + maxDest;
}
src += 0x10;
s32 b1;
u32 dist;
s32 numBytes;
u8* copySource;
do {
if (validBitCount == 0) {
if ((src > srcLimit) && transLeft) {
src = nextSrcData(src);
if (!src) {
return -1;
}
}
currCodeByte = *src++;
validBitCount = 8;
}
if (currCodeByte & 0x80) {
if (fileOffset != 0) {
if (readCount >= fileOffset) {
*dest = *src;
dest++;
ts++;
if (dest == endPtr) {
break;
}
}
*(refCurrent++) = *src;
if (refCurrent == refEnd) {
refCurrent = refBuf;
}
src++;
} else {
*dest++ = *src++;
ts++;
if (dest == endPtr) {
break;
}
}
readCount++;
} else {
b1 = src[0];
dist = src[1] | ((b1 & 0x0f) << 8);
numBytes = b1 >> 4;
src += 2;
if (fileOffset != 0) {
copySource = refCurrent - dist - 1;
if (copySource < refBuf) {
copySource += refEnd - refBuf;
}
} else {
copySource = dest - dist - 1;
}
if (numBytes == 0) {
numBytes = (*src++) + 0x12;
} else {
numBytes += 2;
}
if (fileOffset != 0) {
do {
if (readCount >= fileOffset) {
*dest = *copySource;
dest++;
ts++;
if (dest == endPtr) {
break;
}
}
*(refCurrent++) = *copySource;
if (refCurrent == refEnd) {
refCurrent = refBuf;
}
copySource++;
if (copySource == refEnd) {
copySource = refBuf;
}
readCount++;
numBytes--;
} while (numBytes != 0);
} else {
do {
*dest = *copySource;
dest++;
ts++;
if (dest == endPtr) {
break;
}
copySource++;
readCount++;
numBytes--;
} while (numBytes != 0);
}
}
currCodeByte <<= 1;
validBitCount--;
} while (dest < endPtr);
*tsPtr = ts;
return 0;
}
static u8* firstSrcData() {
srcLimit = szpEnd - 0x19;
u8* buffer = szpBuf;
u32 bufSize = szpEnd - buffer;
u32 length = transLeft < bufSize ? transLeft : bufSize;
while (true) {
int result = DVDReadPrio(srcFile->getFileInfo(), buffer, length, srcOffset, 2);
if (result >= 0) {
break;
}
if (result == -3 || !JKRDvdRipper::isErrorRetry()) {
return NULL;
}
VIWaitForRetrace();
}
DCInvalidateRange(buffer, length);
srcOffset += length;
transLeft -= length;
return buffer;
}
static u8* nextSrcData(u8* src) {
u32 limit = szpEnd - src;
u8 *dest;
if (IS_NOT_ALIGNED(limit, 0x20)) {
dest = szpBuf + 0x20 - (limit & (0x20 - 1));
} else {
dest = szpBuf;
}
memcpy(dest, src, limit);
u32 transSize = (uintptr_t)(szpEnd - (dest + limit));
if (transSize > transLeft) {
transSize = transLeft;
}
JUT_ASSERT(1208, transSize > 0);
while (true)
{
s32 result = DVDReadPrio(srcFile->getFileInfo(), (dest + limit), transSize, srcOffset, 2);
if (result >= 0)
break;
// bug: supposed to call isErrorRetry, but didn't
if (result == -3 || !JKRDvdRipper::isErrorRetry)
return NULL;
VIWaitForRetrace();
}
DCInvalidateRange((dest + limit), transSize);
srcOffset += transSize;
transLeft -= transSize;
if (transLeft == 0)
srcLimit = transSize + (dest + limit);
return dest;
}
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRFile.h"
#include <vi.h>
void JKRFile::read(void* data, s32 length, s32 offset) {
JUT_ASSERT(32, ( length & 0x1f ) == 0);
while (true) {
if (length != readData(data, length, offset)) {
VIWaitForRetrace();
} else {
return;
}
}
}
+376
View File
@@ -0,0 +1,376 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRFileCache.h"
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JKernel/JKRFileFinder.h"
#include "JSystem/JKernel/JKRHeap.h"
#include "JSystem/JUtility/JUTAssert.h"
#include <cctype>
#include <cstring>
#include "global.h"
JKRFileCache* JKRFileCache::mount(const char* path, JKRHeap* heap, const char* param_3) {
if (!path || *path != '/') {
return NULL;
}
u32 pathLength = strlen(path);
if (pathLength != 1 && path[pathLength - 1] == '/') {
return NULL;
}
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
if (iterator->getVolumeType() == 'CASH') {
JKRFileCache* fileCache = (JKRFileCache*)iterator.operator->();
if (fileCache->mRootPath) {
if (strcmp(fileCache->mRootPath, path) == 0) {
fileCache->mMountCount++;
return fileCache;
}
}
}
}
JKRFileCache* fileCache = new (heap, 0) JKRFileCache(path, param_3);
return fileCache;
}
JKRFileCache::JKRFileCache(const char* path, const char* volume) {
mParentHeap = JKRHeap::findFromRoot(this);
mMountCount = 1;
mVolumeType = 'CASH';
u32 pathLength = strlen(path);
mRootPath = (char*)JKRAllocFromHeap(mParentHeap, pathLength + 1, 1);
mCurrentPath = (char*)JKRAllocFromSysHeap(pathLength + 2, 1);
strcpy(mRootPath, path);
strcpy(mCurrentPath, path);
if (path[1] != '\0') {
convStrLower(mRootPath);
convStrLower(mCurrentPath);
strcat(mCurrentPath, "/");
const char* volumePath = volume;
if (!volumePath) {
volumePath = strrchr(mRootPath, '/') + 1;
}
mVolumePath = (char*)JKRAllocFromSysHeap(strlen(volumePath) + 1, 0);
strcpy(mVolumePath, volumePath);
convStrLower(mVolumePath);
mVolumeName = mVolumePath;
} else {
const char* volumePath = volume;
if (!volumePath) {
volumePath = "dvd";
}
mVolumePath = (char*)JKRAllocFromSysHeap(strlen(volumePath) + 1, 0);
strcpy(mVolumePath, volumePath);
convStrLower(mVolumePath);
mVolumeName = mVolumePath;
}
sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
}
JKRFileCache::~JKRFileCache() {
removeResourceAll();
if (mRootPath)
JKRFreeToHeap(mParentHeap, mRootPath);
if (mCurrentPath)
JKRFreeToSysHeap(mCurrentPath);
if (mVolumePath)
JKRFreeToSysHeap(mVolumePath);
sVolumeList.remove(&mFileLoaderLink);
}
bool JKRFileCache::becomeCurrent(const char* path) {
char* dvdPathName = getDvdPathName(path);
bool result = DVDChangeDir(dvdPathName);
if (result) {
sCurrentVolume = this;
JKRFreeToSysHeap(mCurrentPath);
mCurrentPath = dvdPathName;
if (mCurrentPath[1] != '\0') {
strcat(mCurrentPath, "/");
}
} else {
JKRFreeToSysHeap(dvdPathName);
}
return result;
}
void* JKRFileCache::getResource(const char* path) {
JUT_ASSERT(237, isMounted());
void* buffer = NULL;
char* name = getDvdPathName(path);
JKRDvdFile dvdFile(name);
if (dvdFile.isAvailable()) {
CCacheBlock* cacheBlock = findCacheBlock(dvdFile.getFileID());
if (!cacheBlock) {
u32 alignedSize = ALIGN_NEXT(dvdFile.getFileInfo()->length, 0x20);
buffer = JKRAllocFromHeap(mParentHeap, alignedSize, 0x20);
if (buffer) {
dvdFile.read(buffer, alignedSize, 0);
cacheBlock = new (JKRGetSystemHeap(), 0)
CCacheBlock(dvdFile.getFileID(), dvdFile.getFileInfo()->length, buffer);
mCacheBlockList.append(&cacheBlock->mCacheBlockLink);
}
} else {
cacheBlock->mReferenceCount++;
buffer = cacheBlock->mMemoryPtr;
}
}
JKRFreeToSysHeap(name);
return buffer;
}
void* JKRFileCache::getResource(u32, const char* path) {
JUT_ASSERT(303, isMounted());
char finalPath[256];
char* filePath = finalPath + strlen(mRootPath);
strcpy(finalPath, mRootPath);
if (findFile(finalPath, path)) {
return getResource(filePath);
}
return NULL;
}
u32 JKRFileCache::readResource(void* dst, u32 dstLength, const char* path) {
JUT_ASSERT(344, isMounted());
char* name = getDvdPathName(path);
JKRDvdFile dvdFile(name);
u32 resourceSize = 0;
// !@bug: (maybe?) Infinite Loop: Because dvdFile.isAvailable() is never updated in the loop-body
// will would never exit the loop.
while (true) {
if (!dvdFile.isAvailable()) {
break;
}
resourceSize = ALIGN_NEXT(dvdFile.getFileInfo()->length, 0x20);
dstLength = ALIGN_PREV(dstLength, 0x20);
if (resourceSize > dstLength) {
resourceSize = dstLength;
}
CCacheBlock* cacheBlock = findCacheBlock(dvdFile.getFileID());
if (!cacheBlock) {
dvdFile.read(dst, resourceSize, 0);
} else {
memcpy(dst, cacheBlock->mMemoryPtr, resourceSize);
}
}
JKRFreeToSysHeap(name);
return resourceSize;
}
u32 JKRFileCache::readResource(void* dst, u32 dstLength, u32, const char* path) {
JUT_ASSERT(412, isMounted());
char finalPath[256];
char* filePath = finalPath + strlen(mRootPath);
strcpy(finalPath, mRootPath);
if (findFile(finalPath, path)) {
return readResource(dst, dstLength, filePath);
}
return 0;
}
void JKRFileCache::removeResourceAll(void) {
JUT_ASSERT(441, isMounted());
JSUListIterator<CCacheBlock> iterator = mCacheBlockList.getFirst();
while (iterator != mCacheBlockList.getEnd()) {
JKRFreeToHeap(mParentHeap, iterator->mMemoryPtr);
mCacheBlockList.remove(&iterator.getObject()->mCacheBlockLink);
delete (iterator++).getObject();
}
}
bool JKRFileCache::removeResource(void* resource) {
JUT_ASSERT(463, isMounted());
CCacheBlock* cacheBlock = findCacheBlock(resource);
if (!cacheBlock)
return false;
if (--cacheBlock->mReferenceCount == 0) {
JKRFreeToHeap(mParentHeap, resource);
mCacheBlockList.remove(&cacheBlock->mCacheBlockLink);
delete cacheBlock;
}
return true;
}
bool JKRFileCache::detachResource(void* resource) {
JUT_ASSERT(490, isMounted());
CCacheBlock* cacheBlock = findCacheBlock(resource);
if (!cacheBlock)
return false;
mCacheBlockList.remove(&cacheBlock->mCacheBlockLink);
delete cacheBlock;
return true;
}
u32 JKRFileCache::getResSize(const void* resource) const {
CCacheBlock* cacheBlock = findCacheBlock(resource);
if (cacheBlock == NULL) {
return -1;
} else {
return cacheBlock->mFileSize;
}
}
u32 JKRFileCache::countFile(const char* path) const {
u32 count = 0;
char* name = getDvdPathName(path);
DVDDir dir;
if (DVDOpenDir(name, &dir) != 0) {
DVDDirEntry dirEntry;
while (DVDReadDir(&dir, &dirEntry)) {
count = count + 1;
}
DVDCloseDir(&dir);
}
JKRFreeToSysHeap(name);
return count;
}
JKRFileFinder* JKRFileCache::getFirstFile(const char* path) const {
char* name = getDvdPathName(path);
JKRDvdFinder* finder = new (JKRGetSystemHeap(), 0) JKRDvdFinder(name);
JKRFreeToSysHeap(name);
if (finder->isAvailable() != true) {
delete finder;
return NULL;
}
return finder;
}
JKRFileCache::CCacheBlock* JKRFileCache::findCacheBlock(const void* resource) const {
for (JSUListIterator<CCacheBlock> iterator = mCacheBlockList.getFirst(); iterator != mCacheBlockList.getEnd(); ++iterator) {
if (iterator->mMemoryPtr == resource) {
return iterator.getObject();
}
}
return NULL;
}
JKRFileCache::CCacheBlock* JKRFileCache::findCacheBlock(u32 fileID) const {
for (JSUListIterator<CCacheBlock> iterator = mCacheBlockList.getFirst(); iterator != mCacheBlockList.getEnd(); ++iterator) {
if (iterator->mFileId == fileID) {
return iterator.getObject();
}
}
return NULL;
}
bool JKRFileCache::findFile(char* path, const char* fileName) const {
bool result = false;
u32 pathLength = strlen(path);
DVDDir dir;
if (DVDOpenDir(path, &dir)) {
DVDDirEntry dirEntry;
while (DVDReadDir(&dir, &dirEntry)) {
if (dirEntry.isDir) {
path[pathLength] = '/';
strcpy(path + pathLength + 1, dirEntry.name);
result = findFile(path, fileName);
if (result)
break;
path[pathLength] = '\0';
} else {
result = (strcmp(fileName, dirEntry.name) == 0);
if (result) {
strcat(path, "/");
strcat(path, fileName);
break;
}
}
}
DVDCloseDir(&dir);
}
return result;
}
char* JKRFileCache::getDvdPathName(const char* path) const {
char* newPath;
if (path[0] == '/') {
newPath = (char*)JKRAllocFromSysHeap(strlen(mRootPath) + strlen(path) + 2, 1);
strcpy(newPath, mRootPath);
if (path[1]) {
if (mRootPath[1] == 0) {
strcat(newPath, path + 1);
} else {
strcat(newPath, path);
}
}
} else {
newPath = (char*)JKRAllocFromSysHeap(strlen(mCurrentPath) + strlen(path) + 2, 1);
strcpy(newPath, mCurrentPath);
strcat(newPath, path);
}
convStrLower(newPath);
return newPath;
}
void JKRFileCache::convStrLower(char* buffer) const {
while (*buffer) {
*buffer++ = tolower(*buffer);
}
}
JKRFileCache::CCacheBlock::CCacheBlock(u32 fileId, u32 fileSize, const void* resource)
: mCacheBlockLink(this) {
mReferenceCount = 1;
mFileId = fileId;
mFileSize = fileSize;
mMemoryPtr = (void*)resource; // todo: don't cast away const
}
void* JKRFileCache::getFsResource(const char* path) {
return getResource(path);
}
void* JKRFileCache::getNameResource(u32 type, const char* path) {
return getResource(type, path);
}
u32 JKRFileCache::readFsResource(void* dst, u32 dstLength, const char* path) {
return readResource(dst, dstLength, path);
}
u32 JKRFileCache::readNameResource(void* dst, u32 dstLength, u32 type, const char* path) {
return readResource(dst, dstLength, type, path);
}
@@ -0,0 +1,66 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRFileFinder.h"
#include "JSystem/JKernel/JKRArchive.h"
JKRArcFinder::JKRArcFinder(JKRArchive* archive, s32 startIndex, s32 numEntries) : JKRFileFinder() {
mArchive = archive;
mIsAvailable = numEntries > 0;
mStartIndex = startIndex;
mEndIndex = startIndex + numEntries - 1;
mNextIndex = mStartIndex;
findNextFile();
}
bool JKRArcFinder::findNextFile(void) {
if (mIsAvailable) {
mIsAvailable = !(mNextIndex > mEndIndex);
if (mIsAvailable) {
JKRArchive::SDirEntry entry;
mIsAvailable = mArchive->getDirEntry(&entry, mNextIndex);
mEntryName = entry.name;
mEntryFileIndex = mNextIndex;
mEntryId = entry.id;
mEntryTypeFlags = entry.flags;
mIsFileOrDirectory = mEntryTypeFlags & 2;
mNextIndex++;
}
}
return mIsAvailable;
}
JKRDvdFinder::JKRDvdFinder(const char* directory) : JKRFileFinder() {
mDvdIsOpen = DVDOpenDir(directory, &mDvdDirectory);
mIsAvailable = mDvdIsOpen;
findNextFile();
}
JKRDvdFinder::~JKRDvdFinder() {
if (mDvdIsOpen) {
DVDCloseDir(&mDvdDirectory);
}
}
bool JKRDvdFinder::findNextFile(void) {
if (mIsAvailable) {
DVDDirEntry directoryEntry;
mIsAvailable = DVDReadDir(&mDvdDirectory, &directoryEntry);
if (mIsAvailable) {
mIsFileOrDirectory = directoryEntry.isDir != 0;
mEntryName = directoryEntry.name;
mEntryFileIndex = directoryEntry.entryNum;
mEntryId = 0;
// only matches with enum
// TODO: placeholder
enum EntryTypeFlags {
EntryTypeFlags1 = 1,
EntryTypeFlags2 = 2,
};
mEntryTypeFlags = mIsFileOrDirectory ? EntryTypeFlags2 : EntryTypeFlags1;
}
}
return mIsAvailable;
}
+125
View File
@@ -0,0 +1,125 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRFileLoader.h"
#define MSL_USE_INLINES 1 // needed to inline tolower call. not inlined elsewhere in the repo
#include <cstring>
#include <cctype>
#include "global.h"
JKRFileLoader* JKRFileLoader::sCurrentVolume;
JSUList<JKRFileLoader> JKRFileLoader::sVolumeList;
JKRFileLoader::JKRFileLoader(void)
: mFileLoaderLink(this), mVolumeName(NULL), mVolumeType(0), mMountCount(0) {}
JKRFileLoader::~JKRFileLoader() {
if (sCurrentVolume == this) {
sCurrentVolume = NULL;
}
}
void JKRFileLoader::unmount(void) {
if (mMountCount != 0) {
if (--mMountCount == 0) {
delete this;
}
}
}
void* JKRFileLoader::getGlbResource(const char* name) {
JKRFileLoader* fileLoader = findVolume(&name);
void* resource;
if (fileLoader == NULL) {
return NULL;
} else {
resource = fileLoader->getResource(name);
return resource;
}
}
void* JKRFileLoader::getGlbResource(const char* name, JKRFileLoader* fileLoader) {
void* resource = NULL;
if (fileLoader) {
resource = fileLoader->getResource(0, name);
} else {
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
resource = iterator->getResource(0, name);
if (resource)
break;
}
}
return resource;
}
bool JKRFileLoader::removeResource(void* resource, JKRFileLoader* fileLoader) {
if (fileLoader) {
return fileLoader->removeResource(resource);
}
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
if (iterator->removeResource(resource)) {
return true;
}
}
return false;
}
bool JKRFileLoader::detachResource(void* resource, JKRFileLoader* fileLoader) {
if (fileLoader) {
return fileLoader->detachResource(resource);
}
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
if (iterator->detachResource(resource)) {
return true;
}
}
return false;
}
JKRFileLoader* JKRFileLoader::findVolume(const char** volumeName) {
if (*volumeName[0] != '/') {
return sCurrentVolume;
}
char volumeNameBuffer[0x101];
*volumeName = fetchVolumeName(volumeNameBuffer, ARRAY_SIZEU(volumeNameBuffer), *volumeName);
for (JSUListIterator<JKRFileLoader> iterator = sVolumeList.getFirst(); iterator != sVolumeList.getEnd(); ++iterator) {
if (strcmp(volumeNameBuffer, iterator->mVolumeName) == 0) {
return iterator.getObject();
}
}
return NULL;
}
const char* JKRFileLoader::fetchVolumeName(char* buffer, s32 bufferSize, const char* path) {
static char rootPath[2] = "/";
if (strcmp(path, "/") == 0) {
strcpy(buffer, rootPath);
return rootPath;
}
path++;
while (*path != 0 && *path != '/') {
if (1 < bufferSize) {
*buffer = tolower(*path);
buffer++;
bufferSize--;
}
path++;
}
*buffer = '\0';
if (*path == '\0') {
path = rootPath;
}
return path;
}
+532
View File
@@ -0,0 +1,532 @@
/**
* JKRHeap.cpp
* JSystem Heap Framework
*/
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRHeap.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTException.h"
#include <stdint.h>
#include <cstring>
#if DEBUG
u8 JKRValue_DEBUGFILL_NOTUSE = 0xFD;
u8 JKRValue_DEBUGFILL_NEW = 0xCD;
u8 JKRValue_DEBUGFILL_DELETE = 0xDD;
#endif
bool JKRHeap::sDefaultFillFlag = true;
JKRHeap* JKRHeap::sSystemHeap;
JKRHeap* JKRHeap::sCurrentHeap;
JKRHeap* JKRHeap::sRootHeap;
#if PLATFORM_WII || PLATFORM_SHIELD
JKRHeap* JKRHeap::sRootHeap2;
#endif
JKRErrorHandler JKRHeap::mErrorHandler;
static bool data_80451380;
JKRHeap::JKRHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag)
: JKRDisposer(), mChildTree(this), mDisposerList() {
OSInitMutex(&mMutex);
mSize = size;
mStart = (u8*)data;
mEnd = (u8*)data + size;
if (parent == NULL) {
becomeSystemHeap();
becomeCurrentHeap();
} else {
parent->mChildTree.appendChild(&mChildTree);
if (sSystemHeap == sRootHeap) {
becomeSystemHeap();
}
if (sCurrentHeap == sRootHeap) {
becomeCurrentHeap();
}
}
mErrorFlag = errorFlag;
if (mErrorFlag == true && mErrorHandler == NULL) {
mErrorHandler = JKRDefaultMemoryErrorRoutine;
}
mDebugFill = sDefaultFillFlag;
mCheckMemoryFilled = data_80451380;
mInitFlag = false;
}
JKRHeap::~JKRHeap() {
mChildTree.getParent()->removeChild(&mChildTree);
JSUTree<JKRHeap>* nextRootHeap = sRootHeap->mChildTree.getFirstChild();
if (sCurrentHeap == this) {
sCurrentHeap = !nextRootHeap ? sRootHeap : nextRootHeap->getObject();
}
if (sSystemHeap == this) {
sSystemHeap = !nextRootHeap ? sRootHeap : nextRootHeap->getObject();
}
}
void* JKRHeap::mCodeStart;
void* JKRHeap::mCodeEnd;
void* JKRHeap::mUserRamStart;
void* JKRHeap::mUserRamEnd;
u32 JKRHeap::mMemorySize;
JKRHeap::JKRAllocCallback JKRHeap::sAllocCallback;
JKRHeap::JKRFreeCallback JKRHeap::sFreeCallback;
bool JKRHeap::initArena(char** memory, u32* size, int maxHeaps) {
void* arenaLo = OSGetArenaLo();
void* arenaHi = OSGetArenaHi();
#if !PLATFORM_GCN
OSReport("original arenaLo = %p arenaHi = %p\n", arenaLo, arenaHi);
#endif
if (arenaLo == arenaHi)
return false;
arenaLo = OSInitAlloc(arenaLo, arenaHi, maxHeaps);
arenaLo = (void*)ALIGN_NEXT((uintptr_t)arenaLo, 0x20);
arenaHi = (void*)ALIGN_PREV((uintptr_t)arenaHi, 0x20);
OSBootInfo* codeStart = (OSBootInfo*)OSPhysicalToCached(0);
mCodeStart = codeStart;
mCodeEnd = arenaLo;
mUserRamStart = arenaLo;
mUserRamEnd = arenaHi;
mMemorySize = codeStart->memorySize;
OSSetArenaLo(arenaHi);
OSSetArenaHi(arenaHi);
*memory = (char*)arenaLo;
*size = (uintptr_t)arenaHi - (uintptr_t)arenaLo;
return true;
}
#if PLATFORM_WII || PLATFORM_SHIELD
bool JKRHeap::initArena2(char** memory, u32* size, int maxHeaps) {
void* arenaLo = OSGetMEM2ArenaLo();
void* arenaHi = OSGetMEM2ArenaHi();
#if !PLATFORM_GCN
OSReport("original arenaLo = %p arenaHi = %p\n", arenaLo, arenaHi);
#endif
if (arenaLo == arenaHi) {
return false;
}
arenaLo = (void*)0x91100000;
arenaHi = (void*)ALIGN_PREV(uintptr_t(arenaHi), 32);
OSSetMEM2ArenaLo(arenaHi);
OSSetMEM2ArenaHi(arenaHi);
*memory = (char*)arenaLo;
*size = uintptr_t(arenaHi) - uintptr_t(arenaLo);
return true;
}
#endif
JKRHeap* JKRHeap::becomeSystemHeap() {
JKRHeap* prev = sSystemHeap;
sSystemHeap = this;
return prev;
}
JKRHeap* JKRHeap::becomeCurrentHeap() {
JKRHeap* prev = sCurrentHeap;
sCurrentHeap = this;
return prev;
}
void JKRHeap::destroy() {
do_destroy();
}
static void dummy1(JKRHeap* heap) {
JUT_ASSERT(0, heap != 0);
}
void* JKRHeap::alloc(u32 size, int alignment, JKRHeap* heap) {
if (heap != NULL) {
return heap->alloc(size, alignment);
}
if (sCurrentHeap != NULL) {
return sCurrentHeap->alloc(size, alignment);
}
return NULL;
}
void* JKRHeap::alloc(u32 size, int alignment) {
if (mInitFlag) {
JUT_WARN(393, "alloc %x byte in heap %x", size, this);
}
void* mem = do_alloc(size, alignment);
#if DEBUG
if (sAllocCallback) {
sAllocCallback(size, alignment, this, mem);
}
#endif
return mem;
}
void JKRHeap::free(void* ptr, JKRHeap* heap) {
if (!heap) {
heap = findFromRoot(ptr);
if (!heap)
return;
}
heap->free(ptr);
}
void JKRHeap::free(void* ptr) {
if (mInitFlag) {
JUT_WARN(441, "free %x in heap %x", ptr, this);
}
#if DEBUG
if (sFreeCallback) {
sFreeCallback(ptr, this);
}
#endif
do_free(ptr);
}
void JKRHeap::callAllDisposer() {
JSUListIterator<JKRDisposer> iterator;
while ((iterator = mDisposerList.getFirst()) != mDisposerList.getEnd()) {
iterator->~JKRDisposer();
}
}
void JKRHeap::freeAll() {
if (mInitFlag) {
JUT_WARN(493, "freeAll in heap %x", this);
}
do_freeAll();
}
void JKRHeap::freeTail() {
if (mInitFlag) {
JUT_WARN(507, "freeTail in heap %x", this);
}
do_freeTail();
}
static void dummy2() {
OS_REPORT("fillFreeArea in heap %x");
}
s32 JKRHeap::resize(void* ptr, u32 size, JKRHeap* heap) {
if (!heap) {
heap = findFromRoot(ptr);
if (!heap)
return -1;
}
return heap->resize(ptr, size);
}
s32 JKRHeap::resize(void* ptr, u32 size) {
if (mInitFlag) {
JUT_WARN(567, "resize block %x into %x in heap %x", ptr, size, this);
}
return do_resize(ptr, size);
}
s32 JKRHeap::getSize(void* ptr, JKRHeap* heap) {
if (!heap) {
heap = findFromRoot(ptr);
if (!heap)
return -1;
}
return heap->getSize(ptr);
}
s32 JKRHeap::getSize(void* ptr) {
return do_getSize(ptr);
}
s32 JKRHeap::getFreeSize() {
return do_getFreeSize();
}
void* JKRHeap::getMaxFreeBlock() {
return do_getMaxFreeBlock();
}
s32 JKRHeap::getTotalFreeSize() {
return do_getTotalFreeSize();
}
s32 JKRHeap::changeGroupID(u8 groupID) {
if (mInitFlag) {
JUT_WARN(646, "change heap ID into %x in heap %x", groupID, this);
}
return do_changeGroupID(groupID);
}
u8 JKRHeap::getCurrentGroupId() {
return do_getCurrentGroupId();
}
u32 JKRHeap::getMaxAllocatableSize(int alignment) {
u32 maxFreeBlock = (uintptr_t)getMaxFreeBlock();
u32 ptrOffset = (alignment - 1) & alignment - (maxFreeBlock & 0xf);
return ~(alignment - 1) & (getFreeSize() - ptrOffset);
}
JKRHeap* JKRHeap::findFromRoot(void* ptr) {
if (sRootHeap == NULL) {
return NULL;
}
if (sRootHeap->mStart <= ptr && ptr < sRootHeap->mEnd) {
return sRootHeap->find(ptr);
}
#if PLATFORM_WII || PLATFORM_SHIELD
if (sRootHeap2->mStart <= ptr && ptr < sRootHeap2->mEnd) {
return sRootHeap2->find(ptr);
}
#endif
return sRootHeap->findAllHeap(ptr);
}
JKRHeap* JKRHeap::find(void* memory) const {
if (mStart <= memory && memory < mEnd) {
if (mChildTree.getNumChildren() != 0) {
for (JSUTreeIterator<JKRHeap> iterator(mChildTree.getFirstChild());
iterator != mChildTree.getEndChild(); ++iterator)
{
JKRHeap* result = iterator->find(memory);
if (result) {
return result;
}
}
}
return const_cast<JKRHeap*>(this);
}
return NULL;
}
JKRHeap* JKRHeap::findAllHeap(void* ptr) const {
if (mChildTree.getNumChildren() != 0) {
for (JSUTreeIterator<JKRHeap> iterator(mChildTree.getFirstChild());
iterator != mChildTree.getEndChild(); ++iterator)
{
JKRHeap* result = iterator->findAllHeap(ptr);
if (result) {
return result;
}
}
}
if (mStart <= ptr && ptr < mEnd) {
return const_cast<JKRHeap*>(this);
}
return NULL;
}
void JKRHeap::dispose_subroutine(uintptr_t begin, uintptr_t end) {
JSUListIterator<JKRDisposer> next_iterator((JSULink<JKRDisposer>*)NULL);
JSUListIterator<JKRDisposer> it = mDisposerList.getFirst();
while (it != mDisposerList.getEnd()) {
JKRDisposer* disposer = it.getObject();
if ((void*)begin <= disposer && disposer < (void*)end) {
it->~JKRDisposer();
if (next_iterator == JSUListIterator<JKRDisposer>((JSULink<JKRDisposer>*)NULL)) {
it = mDisposerList.getFirst();
continue;
}
it = next_iterator;
it++;
continue;
}
next_iterator = it;
it++;
}
}
bool JKRHeap::dispose(void* ptr, u32 size) {
dispose_subroutine((uintptr_t)ptr, (uintptr_t)ptr + size);
return false;
}
void JKRHeap::dispose(void* begin, void* end) {
dispose_subroutine((uintptr_t)begin, (uintptr_t)end);
}
void JKRHeap::dispose() {
JSUListIterator<JKRDisposer> iterator;
while ((iterator = mDisposerList.getFirst()) != mDisposerList.getEnd()) {
iterator->~JKRDisposer();
}
}
void JKRHeap::copyMemory(void* dst, void* src, u32 size) {
u32 count = (size + 3) / 4;
u32* dst_32 = (u32*)dst;
u32* src_32 = (u32*)src;
while (count-- > 0) {
*dst_32++ = *src_32++;
}
}
void JKRDefaultMemoryErrorRoutine(void* heap, u32 size, int alignment) {
OS_REPORT("Error: Cannot allocate memory %d(0x%x)byte in %d byte alignment from %08x\n", size,
size, alignment, heap);
#if PLATFORM_GCN
JUTException::panic(__FILE__, 831, "abort\n");
#else
JUTException::panic(__FILE__, 912, "abort\n");
#endif
}
bool JKRHeap::setErrorFlag(bool errorFlag) {
bool prev = mErrorFlag;
mErrorFlag = errorFlag;
return prev;
}
JKRErrorHandler JKRHeap::setErrorHandler(JKRErrorHandler errorHandler) {
JKRErrorHandler prev = mErrorHandler;
mErrorHandler = !errorHandler ? JKRDefaultMemoryErrorRoutine : errorHandler;
return prev;
}
void JKRHeap::fillMemory(u8* dst, u32 size, u8 val) {
uintptr_t ptr = uintptr_t(dst);
memset(dst, val, size);
DCFlushRange((void*)ALIGN_PREV(ptr, 32), ALIGN_NEXT(size, 32));
}
bool JKRHeap::checkMemoryFilled(u8* mem, u32 size, u8 val) {
void* ptr = mem;
bool result = true;
for (int i = 0; i < size; i++) {
if (val == mem[i]) {
continue;
}
result = false;
if (fillcheck_dispcount <= 0) {
continue;
}
fillcheck_dispcount--;
JUT_WARN(999, "**** checkMemoryFilled:\n address %08x size %x:\n (%08x = %02x)\n", mem, size, mem + i, mem[i]);
if (data_8074A8D0_debug) {
break;
}
}
return result;
}
bool JKRHeap::isSubHeap(JKRHeap* heap) const {
if (!heap)
return false;
if (mChildTree.getNumChildren() != 0) {
for (JSUTreeIterator<JKRHeap> iterator = mChildTree.getFirstChild(); iterator != mChildTree.getEndChild();
++iterator)
{
if (iterator.getObject() == heap) {
return true;
}
if (iterator.getObject()->isSubHeap(heap)) {
return true;
}
}
}
return false;
}
void* operator new(size_t size) {
return JKRHeap::alloc(size, 4, NULL);
}
void* operator new(size_t size, int alignment) {
return JKRHeap::alloc(size, alignment, NULL);
}
void* operator new(size_t size, JKRHeap* heap, int alignment) {
return JKRHeap::alloc(size, alignment, heap);
}
void* operator new[](size_t size) {
return JKRHeap::alloc(size, 4, NULL);
}
void* operator new[](size_t size, int alignment) {
return JKRHeap::alloc(size, alignment, NULL);
}
void* operator new[](size_t size, JKRHeap* heap, int alignment) {
return JKRHeap::alloc(size, alignment, heap);
}
void operator delete(void* ptr) {
JKRHeap::free(ptr, NULL);
}
void operator delete[](void* ptr) {
JKRHeap::free(ptr, NULL);
}
s32 fillcheck_dispcount = 100;
bool data_8074A8D0_debug = true;
void JKRHeap::state_register(JKRHeap::TState* p, u32 id) const {
JUT_ASSERT(1213, p != NULL);
JUT_ASSERT(1214, p->getHeap() == this);
}
bool JKRHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const {
JUT_ASSERT(1222, r1.getHeap() == r2.getHeap());
return r1.getCheckCode() == r2.getCheckCode();
}
void JKRHeap::state_dump(const JKRHeap::TState& p) const {
JUT_LOG(1246, "check-code : 0x%08x", p.getCheckCode());
JUT_LOG(1247, "id : 0x%08x", p.getId());
JUT_LOG(1248, "used size : %u", p.getUsedSize());
}
void* ARALT_AramStartAdr = (void*)0x90000000;
void* JKRHeap::getAltAramStartAdr() { return ARALT_AramStartAdr; }
s32 JKRHeap::do_changeGroupID(u8 param_0) {
return 0;
}
u8 JKRHeap::do_getCurrentGroupId() {
return 0;
}
+234
View File
@@ -0,0 +1,234 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRMemArchive.h"
#include "JSystem/JKernel/JKRDecomp.h"
#include "JSystem/JKernel/JKRDvdRipper.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTException.h"
#include <cstring>
#include "global.h"
#include <stdint.h>
JKRMemArchive::JKRMemArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
: JKRArchive(entryNum, MOUNT_MEM) {
mIsMounted = false;
mMountDirection = mountDirection;
if (!open(entryNum, mMountDirection)) {
return;
}
mVolumeType = 'RARC';
mVolumeName = mStringTable + mNodes->name_offset;
sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
}
JKRMemArchive::JKRMemArchive(void* buffer, u32 bufferSize, JKRMemBreakFlag param_3)
: JKRArchive((s32)buffer, MOUNT_MEM) {
mIsMounted = false;
if (!open(buffer, bufferSize, param_3)) {
return;
}
mVolumeType = 'RARC';
mVolumeName = mStringTable + mNodes->name_offset;
sVolumeList.prepend(&mFileLoaderLink);
mIsMounted = true;
}
JKRMemArchive::~JKRMemArchive() {
if (mIsMounted == true) {
if (mIsOpen) {
if (mArcHeader)
JKRFreeToHeap(mHeap, mArcHeader);
}
sVolumeList.remove(&mFileLoaderLink);
mIsMounted = false;
}
}
static void dummy() {
OS_REPORT(__FILE__);
OS_REPORT("isMounted()");
OS_REPORT("mMountCount == 1");
}
bool JKRMemArchive::open(s32 entryNum, JKRArchive::EMountDirection mountDirection) {
mArcHeader = NULL;
mArcInfoBlock = NULL;
mArchiveData = NULL;
mNodes = NULL;
mFiles = NULL;
mStringTable = NULL;
mIsOpen = false;
mMountDirection = mountDirection;
if (mMountDirection == JKRArchive::MOUNT_DIRECTION_HEAD) {
u32 loadedSize;
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap, JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
0, (int *)&mCompression, &loadedSize);
if (mArcHeader) {
DCInvalidateRange(mArcHeader, loadedSize);
}
}
else {
u32 loadedSize;
mArcHeader = (SArcHeader *)JKRDvdToMainRam(
entryNum, NULL, EXPAND_SWITCH_UNKNOWN1, 0, mHeap,
JKRDvdRipper::ALLOC_DIRECTION_BACKWARD, 0, (int *)&mCompression, &loadedSize);
if (mArcHeader) {
DCInvalidateRange(mArcHeader, loadedSize);
}
}
if (!mArcHeader) {
mMountMode = UNKNOWN_MOUNT_MODE;
}
else {
JUT_ASSERT(438, mArcHeader->signature == 'RARC');
mArcInfoBlock = (SArcDataInfo *)((u8 *)mArcHeader + mArcHeader->header_length);
mNodes = (SDIDirEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
mFiles = (SDIFileEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset);
mStringTable = (char *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset);
mArchiveData =
(u8 *)((uintptr_t)mArcHeader + mArcHeader->header_length + mArcHeader->file_data_offset);
mIsOpen = true;
}
#if DEBUG
if (mMountMode == 0) {
OSReport(":::Cannot alloc memory [%s][%d]\n", __FILE__, 460);
}
#endif
return (mMountMode == UNKNOWN_MOUNT_MODE) ? false : true;
}
bool JKRMemArchive::open(void* buffer, u32 bufferSize, JKRMemBreakFlag flag) {
mArcHeader = (SArcHeader *)buffer;
JUT_ASSERT(491, mArcHeader->signature == 'RARC');
mArcInfoBlock = (SArcDataInfo *)((u8 *)mArcHeader + mArcHeader->header_length);
mNodes = (SDIDirEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
mFiles = (SDIFileEntry *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset);
mStringTable = (char *)((u8 *)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset);
mArchiveData = (u8 *)(((uintptr_t)mArcHeader + mArcHeader->header_length) + mArcHeader->file_data_offset);
mIsOpen = (flag == JKRMEMBREAK_FLAG_UNKNOWN1) ? true : false; // mIsOpen might be u8
mHeap = JKRHeap::findFromRoot(buffer);
mCompression = COMPRESSION_NONE;
return true;
}
void* JKRMemArchive::fetchResource(SDIFileEntry* fileEntry, u32* resourceSize) {
JUT_ASSERT(555, isMounted());
if (!fileEntry->data) {
fileEntry->data = mArchiveData + fileEntry->data_offset;
}
if (resourceSize) {
*resourceSize = fileEntry->data_size;
}
return fileEntry->data;
}
void* JKRMemArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
u32* resourceSize) {
JUT_ASSERT(595, isMounted());
u32 srcLength = fileEntry->data_size;
if (srcLength > bufferSize) {
srcLength = bufferSize;
}
if (fileEntry->data != NULL) {
memcpy(buffer, fileEntry->data, srcLength);
} else {
u8 flags = fileEntry->type_flags_and_name_offset >> 24;
JKRCompression compression = JKRConvertAttrToCompressionType(flags);
srcLength =
fetchResource_subroutine(mArchiveData + fileEntry->data_offset, srcLength, (u8*)buffer, bufferSize, compression);
}
if (resourceSize) {
*resourceSize = srcLength;
}
return buffer;
}
void JKRMemArchive::removeResourceAll(void) {
JUT_ASSERT(642, isMounted());
if (mArcInfoBlock == NULL)
return;
if (mMountMode == MOUNT_MEM)
return;
// !@bug: looping over file entries without incrementing the fileEntry pointer. Thus, only the
// 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;
}
}
fileEntry++;
}
bool JKRMemArchive::removeResource(void* resource) {
JUT_ASSERT(673, isMounted());
SDIFileEntry* fileEntry = findPtrResource(resource);
if (!fileEntry)
return false;
fileEntry->data = NULL;
return true;
}
u32 JKRMemArchive::fetchResource_subroutine(u8* src, u32 srcLength, u8* dst, u32 dstLength,
JKRCompression compression) {
switch (compression) {
case COMPRESSION_NONE:
if (srcLength > dstLength) {
srcLength = dstLength;
}
memcpy(dst, src, srcLength);
return srcLength;
case COMPRESSION_YAY0:
case COMPRESSION_YAZ0: {
u32 expendedSize = JKRDecompExpandSize(src);
if (expendedSize > dstLength) {
expendedSize = dstLength;
}
JKRDecompress(src, dst, expendedSize, 0);
return expendedSize;
}
default: {
JUTException::panic(__FILE__, 723, "??? bad sequence\n");
} break;
}
return 0;
}
u32 JKRMemArchive::getExpandedResSize(const void* resource) const {
SDIFileEntry* fileEntry = findPtrResource(resource);
if (fileEntry == NULL)
return -1;
u8 flags = fileEntry->type_flags_and_name_offset >> 24;
if ((flags & 4) == false) {
return getResSize(resource);
}
u32 expandSize = JKRDecompExpandSize((u8*)resource);
return expandSize;
}
+287
View File
@@ -0,0 +1,287 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRSolidHeap.h"
#include "JSystem/JGadget/binary.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTConsole.h"
#include "global.h"
#include <stdint.h>
#include <cstdlib>
JKRSolidHeap* JKRSolidHeap::create(u32 size, JKRHeap* heap, bool useErrorHandler) {
if (!heap) {
heap = sRootHeap;
}
u32 solidHeapSize = ALIGN_NEXT(sizeof(JKRSolidHeap), 0x10);
if (size == -1) {
size = heap->getMaxAllocatableSize(0x10);
}
u32 alignedSize = ALIGN_PREV(size, 0x10);
if (alignedSize < solidHeapSize)
return NULL;
u8* mem = (u8*)JKRAllocFromHeap(heap, alignedSize, 0x10);
void* dataPtr = mem + solidHeapSize;
if (!mem)
return NULL;
return new (mem) JKRSolidHeap(dataPtr, alignedSize - solidHeapSize, heap, useErrorHandler);
}
void JKRSolidHeap::do_destroy(void) {
JKRHeap* parent = getParent();
if (parent) {
this->~JKRSolidHeap();
JKRFreeToHeap(parent, this);
}
}
JKRSolidHeap::JKRSolidHeap(void* start, u32 size, JKRHeap* parent, bool useErrorHandler)
: JKRHeap(start, size, parent, useErrorHandler) {
mFreeSize = mSize;
mSolidHead = (u8*)mStart;
mSolidTail = (u8*)mEnd;
field_0x78 = NULL;
#if DEBUG
if (mDebugFill) {
JKRFillMemory(mStart, mSize, JKRValue_DEBUGFILL_NOTUSE);
}
#endif
}
JKRSolidHeap::~JKRSolidHeap(void) {
dispose();
}
s32 JKRSolidHeap::adjustSize(void) {
int r25 = 0;
JKRHeap* parent = getParent();
if (parent) {
lock();
u32 thisSize = (uintptr_t)mStart - (uintptr_t)this;
u32 newSize = ALIGN_NEXT(mSolidHead - mStart, 0x20);
s32 r26 = parent->resize(this, thisSize + newSize);
if (r26 != -1) {
mFreeSize = 0;
mSize = newSize;
mEnd = mStart + mSize;
mSolidHead = mEnd;
mSolidTail = mEnd;
}
unlock();
return thisSize + newSize;
}
return -1;
}
void* JKRSolidHeap::do_alloc(u32 size, int alignment) {
#if DEBUG
if (alignment) {
u32 u = abs(alignment);
JUT_CONFIRM(219, u < 0x80);
JUT_CONFIRM(220, JGadget::binary::isPower2( u ));
}
#endif
lock();
if (size < 4) {
size = 4;
}
void* ptr;
if (alignment >= 0) {
ptr = allocFromHead(size, alignment < 4 ? 4 : alignment);
} else {
ptr = allocFromTail(size, -alignment < 4 ? 4 : -alignment);
}
unlock();
return ptr;
}
void* JKRSolidHeap::allocFromHead(u32 size, int alignment) {
size = ALIGN_NEXT(size, sizeof(void*));
void* ptr = NULL;
uintptr_t alignedStart = (alignment - 1 + (uintptr_t)mSolidHead) & ~(alignment - 1);
u32 totalSize = size + (alignedStart - (uintptr_t)mSolidHead);
if (totalSize <= mFreeSize) {
#if DEBUG
if (mCheckMemoryFilled) {
checkMemoryFilled(mSolidHead, totalSize, JKRValue_DEBUGFILL_DELETE);
}
if (mDebugFill) {
JKRFillMemory(mSolidHead, totalSize, JKRValue_DEBUGFILL_NEW);
}
#endif
ptr = (void*)alignedStart;
mSolidHead += totalSize;
mFreeSize -= totalSize;
} else {
JUTWarningConsole_f("allocFromHead: cannot alloc memory (0x%x byte).\n", totalSize);
if (getErrorFlag() == true) {
callErrorHandler(this, size, alignment);
}
}
return ptr;
}
void* JKRSolidHeap::allocFromTail(u32 size, int alignment) {
size = ALIGN_NEXT(size, sizeof(void*));
void* ptr = NULL;
uintptr_t alignedStart = ALIGN_PREV((uintptr_t)mSolidTail - size, alignment);
u32 totalSize = (uintptr_t)mSolidTail - (uintptr_t)alignedStart;
if (totalSize <= mFreeSize) {
ptr = (void*)alignedStart;
mSolidTail -= totalSize;
mFreeSize -= totalSize;
#if DEBUG
if (mCheckMemoryFilled) {
checkMemoryFilled((u8*)alignedStart, totalSize, JKRValue_DEBUGFILL_DELETE);
}
if (mDebugFill) {
JKRFillMemory((u8*)alignedStart, totalSize, JKRValue_DEBUGFILL_NEW);
}
#endif
} else {
JUTWarningConsole_f("allocFromTail: cannot alloc memory (0x%x byte).\n", totalSize);
if (getErrorFlag() == true) {
callErrorHandler(this, size, alignment);
}
}
return ptr;
}
void JKRSolidHeap::do_free(void* ptr) {
JUTWarningConsole_f("free: cannot free memory block (%08x)\n", ptr);
}
void JKRSolidHeap::do_freeAll(void) {
lock();
this->JKRHeap::callAllDisposer();
mFreeSize = mSize;
mSolidHead = (u8*)mStart;
mSolidTail = (u8*)mEnd;
field_0x78 = NULL;
#if DEBUG
if (mDebugFill) {
JKRFillMemory(mStart, mSize, JKRValue_DEBUGFILL_DELETE);
}
#endif
unlock();
}
void JKRSolidHeap::do_freeTail(void) {
lock();
if (mSolidTail != mEnd) {
dispose(mSolidTail, mEnd);
}
#if DEBUG
if (mDebugFill) {
JKRFillMemory(mSolidTail, mEnd - mSolidTail, JKRValue_DEBUGFILL_DELETE);
}
#endif
this->mFreeSize = ((uintptr_t)mEnd - (uintptr_t)mSolidTail + mFreeSize);
this->mSolidTail = mEnd;
for (JKRSolidHeap::Unknown* unknown = field_0x78; unknown; unknown = unknown->mNext) {
unknown->field_0xc = mEnd;
}
unlock();
}
void JKRSolidHeap::do_fillFreeArea() {
#if DEBUG
JKRFillMemory(mSolidHead, mEnd - mSolidHead, JKRValue_DEBUGFILL_DELETE);
#endif
}
s32 JKRSolidHeap::do_resize(void* ptr, u32 newSize) {
JUTWarningConsole_f("resize: cannot resize memory block (%08x: %d)\n", ptr, newSize);
return -1;
}
s32 JKRSolidHeap::do_getSize(void* ptr) {
JUTWarningConsole_f("getSize: cannot get memory block size (%08x)\n", ptr);
return -1;
}
bool JKRSolidHeap::check(void) {
lock();
bool result = true;
u32 calculatedSize = (mSolidHead - mStart) + mFreeSize + (mEnd - mSolidTail);
if (calculatedSize != mSize) {
result = false;
JUTWarningConsole_f("check: bad total memory block size (%08X, %08X)\n", mSize,
calculatedSize);
}
unlock();
return result;
}
bool JKRSolidHeap::dump(void) {
bool result = check();
lock();
s32 htSize = (mSolidHead - mStart) + (mEnd - mSolidTail);
JUTReportConsole_f("head %08x: %08x\n", mStart, (mSolidHead - mStart));
JUTReportConsole_f("tail %08x: %08x\n", mSolidTail, (mEnd - mSolidTail));
JUTReportConsole_f("%d / %d bytes (%6.2f%%) used\n", htSize, mSize, f32(htSize) / f32(mSize) * 100.0f);
unlock();
return result;
}
void JKRSolidHeap::state_register(JKRHeap::TState* p, u32 id) const {
JUT_ASSERT(604, p != NULL);
JUT_ASSERT(605, p->getHeap() == this);
void* r28 = getState_(p);
setState_u32ID_(p, id);
setState_uUsedSize_(p, getUsedSize((JKRSolidHeap*)this));
u32 r29 = (uintptr_t)mSolidHead;
r29 += (uintptr_t)mSolidTail * 3;
setState_u32CheckCode_(p, r29);
}
bool JKRSolidHeap::state_compare(JKRHeap::TState const& r1, JKRHeap::TState const& r2) const {
JUT_ASSERT(632, r1.getHeap() == r2.getHeap());
bool result = true;
if (r1.getCheckCode() != r2.getCheckCode()) {
result = false;
}
if (r1.getUsedSize() != r2.getUsedSize()) {
result = false;
}
return result;
}
u32 JKRSolidHeap::getHeapType(void) {
return 'SLID';
}
s32 JKRSolidHeap::do_getFreeSize(void) {
return mFreeSize;
}
void* JKRSolidHeap::do_getMaxFreeBlock(void) {
return mSolidHead;
}
s32 JKRSolidHeap::do_getTotalFreeSize(void) {
return getFreeSize();
}
+338
View File
@@ -0,0 +1,338 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JKernel/JKRThread.h"
#include "JSystem/JUtility/JUTAssert.h"
#include "JSystem/JUtility/JUTConsole.h"
#include <cstdio>
#include "global.h"
#include <stdint.h>
JSUList<JKRThread> JKRThread::sThreadList(0);
void* JKRIdleThread::sThread;
JKRThreadSwitch* JKRThreadSwitch::sManager;
u32 JKRThreadSwitch::sTotalCount;
u64 JKRThreadSwitch::sTotalStart;
JKRThreadSwitch_PreCallback JKRThreadSwitch::mUserPreCallback;
JKRThreadSwitch_PostCallback JKRThreadSwitch::mUserPostCallback;
JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this) {
JKRHeap* heap = JKRHeap::findFromRoot(this);
if (heap == NULL) {
heap = JKRGetSystemHeap();
}
setCommon_heapSpecified(heap, stack_size, param_3);
setCommon_mesgQueue(mHeap, message_count);
}
JKRThread::JKRThread(JKRHeap* heap, u32 stack_size, int message_count, int param_4)
: mThreadListLink(this) {
if (heap == NULL) {
heap = JKRGetCurrentHeap();
}
setCommon_heapSpecified(heap, stack_size, param_4);
setCommon_mesgQueue(mHeap, message_count);
}
JKRThread::JKRThread(OSThread* thread, int message_count) : mThreadListLink(this) {
mHeap = NULL;
mThreadRecord = thread;
mStackSize = (uintptr_t)thread->stackEnd - (uintptr_t)thread->stackBase;
mStackMemory = thread->stackBase;
setCommon_mesgQueue(JKRGetSystemHeap(), message_count);
}
JKRThread::~JKRThread() {
sThreadList.remove(&mThreadListLink);
if (mHeap) {
if (OSIsThreadTerminated(mThreadRecord) == FALSE) {
OSDetachThread(mThreadRecord);
OSCancelThread(mThreadRecord);
}
JKRFreeToHeap(mHeap, mStackMemory);
JKRFreeToHeap(mHeap, mThreadRecord);
}
JKRFree(mMesgBuffer);
}
void JKRThread::setCommon_mesgQueue(JKRHeap* heap, int message_count) {
mMessageCount = message_count;
mMesgBuffer = (OSMessage*)JKRAllocFromHeap(heap, mMessageCount * sizeof(OSMessage), 0);
JUT_ASSERT(130, mMesgBuffer);
OSInitMessageQueue(&mMessageQueue, mMesgBuffer, mMessageCount);
sThreadList.append(&mThreadListLink);
mCurrentHeap = NULL;
mCurrentHeapError = 0;
}
void JKRThread::setCommon_heapSpecified(JKRHeap* heap, u32 stack_size, int param_3) {
mHeap = heap;
mStackSize = stack_size & 0xffffffe0;
mStackMemory = JKRAllocFromHeap(mHeap, mStackSize, 0x20);
JUT_ASSERT(164, mStackMemory);
mThreadRecord = (OSThread*)JKRAllocFromHeap(mHeap, sizeof(OSThread), 0x20);
JUT_ASSERT(168, mThreadRecord);
OSCreateThread(mThreadRecord, start, this, (u8*)mStackMemory + mStackSize, mStackSize, param_3, 1);
}
void* JKRThread::start(void* thread) {
return ((JKRThread*)thread)->run();
}
JKRThread* JKRThread::searchThread(OSThread* thread) {
for (JSUListIterator<JKRThread> iterator = getList().getFirst(); iterator != getList().getEnd(); ++iterator) {
if (iterator->getThreadRecord() == thread) {
return iterator.getObject();
}
}
return NULL;
}
static void dummy1(JKRThread* thread, JKRThread::TLoad* load) {
load->getId();
load->isValid();
thread->getLoadInfo();
}
JKRThreadSwitch::JKRThreadSwitch(JKRHeap* param_0) {
mHeap = param_0;
OSSetSwitchThreadCallback(JKRThreadSwitch::callback);
this->field_0xC = 0;
this->field_0x10 = 1;
this->field_0x18 = 0;
sTotalCount = 0;
sTotalStart = 0;
this->field_0x20 = 0;
this->field_0x24 = 0;
mSetNextHeap = true;
}
JKRThreadSwitch* JKRThreadSwitch::createManager(JKRHeap* heap) {
JUT_ASSERT(343, sManager == NULL);
if (!heap) {
heap = JKRGetCurrentHeap();
}
sManager = new (heap, 0) JKRThreadSwitch(heap);
return sManager;
}
static void dummy2(JKRThread::TLoad* load) {
load->setValid(false);
load->setId(0);
}
JKRThread* JKRThreadSwitch::enter(JKRThread* thread, int thread_id) {
if (!thread) {
return NULL;
}
JKRThread* found_thread = JKRThread::searchThread(thread->getThreadRecord());
if (found_thread) {
thread = found_thread;
}
JKRThread::TLoad* loadInfo = thread->getLoadInfo();
loadInfo->clear();
loadInfo->setValid(true);
loadInfo->setId(thread_id);
return thread;
}
static void dummyStrings() {
DEAD_STRING("on");
DEAD_STRING("off");
DEAD_STRING("JKRThread:%x OSThread:%x Load:ID:%d (%s)\n");
}
void JKRThreadSwitch::callback(OSThread* current, OSThread* next) {
if (mUserPreCallback) {
(*mUserPreCallback)(current, next);
}
sTotalCount = sTotalCount + 1;
JKRHeap* next_heap = NULL;
for (JSUListIterator<JKRThread> iterator = JKRThread::getList().getFirst(); iterator != JKRThread::getList().getEnd(); ++iterator) {
JKRThread* thread = iterator.getObject();
if (thread->getThreadRecord() == current) {
thread->setCurrentHeap(JKRHeap::getCurrentHeap());
if (thread->getLoadInfo()->isValid()) {
thread->getLoadInfo()->addCurrentCost();
}
}
if (thread->getThreadRecord() == next) {
if (thread->getLoadInfo()->isValid()) {
thread->getLoadInfo()->setCurrentTime();
thread->getLoadInfo()->incCount();
}
if (sManager->mSetNextHeap) {
next_heap = thread->getCurrentHeap();
if (!next_heap) {
next_heap = JKRHeap::getCurrentHeap();
} else if (JKRHeap::getRootHeap()->isSubHeap(next_heap)) {
continue;
#if PLATFORM_WII || PLATFORM_SHIELD
} else if (JKRHeap::getRootHeap2()->isSubHeap(next_heap)) {
continue;
#endif
} else {
switch (thread->getCurrentHeapError()) {
case 0:
JUT_PANIC(508, "JKRThreadSwitch: currentHeap destroyed.");
break;
case 1:
JUTWarningConsole("JKRThreadSwitch: currentHeap destroyed.\n");
next_heap = JKRHeap::getCurrentHeap();
break;
case 2:
next_heap = JKRHeap::getCurrentHeap();
break;
case 3:
next_heap = JKRHeap::getSystemHeap();
break;
}
}
}
}
}
if (next_heap) {
next_heap->becomeCurrentHeap();
}
if (mUserPostCallback) {
(*mUserPostCallback)(current, next);
}
}
void dummy3(JKRThreadSwitch* threadSw, JKRThreadName_* name) {
threadSw->draw(name);
}
void JKRThreadSwitch::draw(JKRThreadName_* thread_name_list, JUTConsole* console) {
const char* print_0 = " total: switch:%3d time:%d(%df)\n";
const char* print_1 = " -------------------------------------\n";
if (console) {
console->clear();
console->print_f(print_0, getTotalCount(), (int)this->field_0x18, this->field_0x10);
console->print(print_1);
} else {
OS_REPORT(print_0, getTotalCount(), (int)this->field_0x18, this->field_0x10);
OS_REPORT(print_1);
}
for (JSUListIterator<JKRThread> iterator = JKRThread::getList().getFirst(); iterator != JKRThread::getList().getEnd(); ++iterator) {
JKRThread* thread = iterator.getObject();
JKRThread::TLoad* loadInfo = thread->getLoadInfo();
if (loadInfo->isValid()) {
char* thread_print_name = NULL;
if (thread_name_list) {
JKRThreadName_* thread_name = thread_name_list;
for (; thread_name->name; thread_name++) {
if (thread_name->id == loadInfo->getId()) {
thread_print_name = thread_name->name;
break;
}
}
}
if (!thread_print_name) {
char buffer[16];
sprintf(buffer, "%d", loadInfo->getId());
thread_print_name = buffer;
}
u32 switch_count = loadInfo->getCount();
u32 cost = loadInfo->getCost();
f32 cost_per_0x18 = loadInfo->getCost() / f32(this->field_0x18);
u32 cost_int = (u32)(cost_per_0x18 * 100.0f);
u32 cost_float = (u32)(cost_per_0x18 * 1000.0f) % 10;
if (console) {
console->print_f(" [%10s] switch:%5d cost:%2d.%d%%\n", thread_print_name,
switch_count, cost_int, cost_float);
} else {
OS_REPORT(" [%10s] switch:%5d cost:%2d.%d%%\n", thread_print_name, switch_count,
cost_int, cost_float);
}
}
}
}
static void dummy4(JKRTask* thread, JSULink<JKRTask>* link) {
thread->getStack();
delete link;
}
JKRTask::~JKRTask() {
sTaskList.remove(&mTaskLink);
}
void* JKRTask::run() {
struct TaskMessage {
void (*field_0x0)(int);
int field_0x4;
void* field_0x8;
};
OSInitFastCast();
while (true) {
TaskMessage* msg = (TaskMessage*)waitMessageBlock();
if (msg->field_0x0) {
msg->field_0x0(msg->field_0x4);
check();
if (field_0x94) {
OSSendMessage(field_0x94, msg->field_0x8, OS_MESSAGE_NOBLOCK);
}
}
msg->field_0x0 = NULL;
}
}
int JKRTask::check() {
int result = 0;
u8* ptr = (u8*)JKRThread::getStack();
JUT_ASSERT(1033, *((u32*)ptr) == 0xDEADBABE);
ptr += 4;
result += 4;
while (*ptr++ == 0xDE) { result++; }
return result;
}
#if !PLATFORM_GCN
static void dummy(JKRIdleThread* thread) {
thread->run();
delete thread;
thread->destroy();
}
#endif
#pragma push
#pragma force_active on
JSUList<JKRTask> JKRTask::sTaskList;
#pragma pop
#pragma push
#pragma force_active on
u8 JKRTask::sEndMesgQueue[32];
#pragma pop