Files
tp/libs/JSystem/JKernel/JKRDvdArchive.cpp
T

380 lines
13 KiB
C++
Raw Normal View History

2021-04-01 02:07:58 +02:00
#include "JSystem/JKernel/JKRDvdArchive.h"
2023-09-24 02:05:03 -07:00
#include "JSystem/JKernel/JKRDecomp.h"
2021-05-03 02:03:24 +02:00
#include "JSystem/JKernel/JKRDvdFile.h"
#include "JSystem/JKernel/JKRDvdRipper.h"
2023-09-19 03:46:45 -07:00
#include "JSystem/JUtility/JUTAssert.h"
2021-05-03 02:03:24 +02:00
#include "JSystem/JUtility/JUTException.h"
#include "math.h"
#include "string.h"
2024-01-19 16:22:19 -08:00
#include "dolphin/os.h"
2021-05-03 02:03:24 +02:00
#include "global.h"
2021-03-28 22:49:05 +02:00
2021-04-06 18:00:35 +02:00
/* 802D7BF0-802D7C98 2D2530 00A8+00 0/0 1/1 0/0 .text
2021-04-01 02:07:58 +02:00
* __ct__13JKRDvdArchiveFlQ210JKRArchive15EMountDirection */
2021-05-03 02:03:24 +02:00
JKRDvdArchive::JKRDvdArchive(s32 entryNum, JKRArchive::EMountDirection mountDirection)
2023-09-16 10:18:45 -07:00
: JKRArchive(entryNum, MOUNT_DVD) {
mMountDirection = mountDirection;
2021-05-03 02:03:24 +02:00
if (!open(entryNum))
return;
mVolumeType = 'RARC';
2022-05-21 01:26:15 -07:00
mVolumeName = mStringTable + mNodes->name_offset;
2021-05-03 02:03:24 +02:00
getVolumeList().prepend(&mFileLoaderLink);
mIsMounted = true;
2021-01-31 15:33:34 -05:00
}
2021-04-06 18:00:35 +02:00
/* 802D7C98-802D7DB4 2D25D8 011C+00 1/0 0/0 0/0 .text __dt__13JKRDvdArchiveFv */
2021-05-03 02:03:24 +02:00
JKRDvdArchive::~JKRDvdArchive() {
if (mIsMounted == true) {
if (mArcInfoBlock) {
SDIFileEntry* fileEntry = mFiles;
int i = 0;
for (; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) {
if (fileEntry->data) {
JKRFreeToHeap(mHeap, fileEntry->data);
}
}
JKRFreeToHeap(mHeap, mArcInfoBlock);
mArcInfoBlock = NULL;
}
if (mExpandedSize) {
i_JKRFree(mExpandedSize);
2021-05-03 02:03:24 +02:00
mExpandedSize = NULL;
}
if (mDvdFile) {
delete mDvdFile;
}
getVolumeList().remove(&mFileLoaderLink);
mIsMounted = false;
}
2020-12-06 21:02:25 +01:00
}
2021-04-06 18:00:35 +02:00
/* 802D7DB4-802D8050 2D26F4 029C+00 1/1 0/0 0/0 .text open__13JKRDvdArchiveFl */
2021-05-03 02:03:24 +02:00
bool JKRDvdArchive::open(s32 entryNum) {
mArcInfoBlock = NULL;
2024-01-24 04:00:46 -08:00
mDataOffset = 0;
2021-05-03 02:03:24 +02:00
mNodes = NULL;
mFiles = NULL;
mStringTable = NULL;
2023-09-19 03:46:45 -07:00
mDvdFile = new (JKRGetSystemHeap(), 0) JKRDvdFile(entryNum);
2021-05-03 02:03:24 +02:00
if (!mDvdFile) {
mMountMode = UNKNOWN_MOUNT_MODE;
return false;
}
SArcHeader* 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 = mMountDirection == MOUNT_DIRECTION_HEAD ? 0x20 : -0x20;
2021-05-03 02:03:24 +02:00
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);
2022-05-21 01:26:15 -07:00
mNodes = (SDIDirEntry*)((int)&mArcInfoBlock->num_nodes + mArcInfoBlock->node_offset);
2021-05-03 02:03:24 +02:00
mFiles = (SDIFileEntry*)((int)&mArcInfoBlock->num_nodes + mArcInfoBlock->file_entry_offset);
mStringTable = (char*)((int)&mArcInfoBlock->num_nodes + mArcInfoBlock->string_table_offset);
mExpandedSize = NULL;
u8 useCompression = 0;
2021-05-03 02:03:24 +02:00
SDIFileEntry* fileEntry = mFiles;
for (u32 i = 0; i < mArcInfoBlock->num_file_entries; fileEntry++, i++) {
if (fileEntry->isUnknownFlag1()) {
useCompression |= fileEntry->getCompressFlag();
2021-05-03 02:03:24 +02:00
}
}
if (useCompression) {
mExpandedSize = (s32*)JKRAllocFromHeap(mHeap, sizeof(s32) * mArcInfoBlock->num_file_entries,
abs(alignment));
if (!mExpandedSize) {
2021-05-03 02:03:24 +02:00
// !@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);
}
2024-01-24 04:00:46 -08:00
mDataOffset = arcHeader->header_length + arcHeader->file_data_offset;
2021-05-03 02:03:24 +02:00
cleanup:
if (arcHeader) {
JKRFreeToSysHeap(arcHeader);
}
if (mMountMode == UNKNOWN_MOUNT_MODE) {
#ifdef DEBUG
2023-09-19 03:46:45 -07:00
OSReport(":::Cannot alloc memory [%s][%d]\n", __FILE__, 397);
#endif
2021-05-03 02:03:24 +02:00
if (mDvdFile) {
delete mDvdFile;
}
return false;
}
return true;
}
2020-12-06 21:02:25 +01:00
2021-04-06 18:00:35 +02:00
/* 802D8050-802D8168 2D2990 0118+00 1/0 0/0 0/0 .text
2021-04-01 02:07:58 +02:00
* fetchResource__13JKRDvdArchiveFPQ210JKRArchive12SDIFileEntryPUl */
2021-05-03 02:03:24 +02:00
void* JKRDvdArchive::fetchResource(SDIFileEntry* fileEntry, u32* returnSize) {
2023-09-19 03:46:45 -07:00
JUT_ASSERT(428, isMounted());
2021-05-03 02:03:24 +02:00
u32 tempReturnSize;
if (returnSize == NULL) {
returnSize = &tempReturnSize;
}
JKRCompression fileCompression = JKRConvertAttrToCompressionType(fileEntry->getAttr());
if (!fileEntry->data) {
u8* resourcePtr;
u32 resourceSize = fetchResource_subroutine(
2024-01-24 04:00:46 -08:00
mEntryNum, mDataOffset + fileEntry->data_offset, fileEntry->data_size, mHeap,
2021-05-03 02:03:24 +02:00
fileCompression, mCompression, &resourcePtr);
*returnSize = resourceSize;
if (resourceSize == 0) {
return NULL;
}
2023-02-26 17:50:56 -08:00
2021-05-03 02:03:24 +02:00
fileEntry->data = resourcePtr;
if (fileCompression == COMPRESSION_YAZ0) {
setExpandSize(fileEntry, *returnSize);
}
} else {
if (fileCompression == COMPRESSION_YAZ0) {
u32 resourceSize = getExpandSize(fileEntry);
*returnSize = resourceSize;
} else {
*returnSize = fileEntry->data_size;
}
}
return fileEntry->data;
2021-01-10 02:15:52 +01:00
}
2021-03-28 22:49:05 +02:00
2021-04-06 18:00:35 +02:00
/* 802D8168-802D826C 2D2AA8 0104+00 1/0 0/0 0/0 .text
2021-04-01 02:07:58 +02:00
* fetchResource__13JKRDvdArchiveFPvUlPQ210JKRArchive12SDIFileEntryPUl */
2021-05-03 02:03:24 +02:00
void* JKRDvdArchive::fetchResource(void* buffer, u32 bufferSize, SDIFileEntry* fileEntry,
u32* returnSize) {
2023-09-19 03:46:45 -07:00
JUT_ASSERT(504, isMounted());
2024-01-24 04:00:46 -08:00
u32 expandSize;
2021-05-03 02:03:24 +02:00
u32 size = fileEntry->data_size;
JKRCompression fileCompression = JKRConvertAttrToCompressionType(fileEntry->getAttr());
if (!fileEntry->data) {
2024-01-24 04:00:46 -08:00
bufferSize = (s32)ALIGN_PREV(bufferSize, 0x20);
size = fetchResource_subroutine(mEntryNum, mDataOffset + fileEntry->data_offset,
fileEntry->data_size, (u8*)buffer, bufferSize, fileCompression,
2021-05-03 02:03:24 +02:00
mCompression);
} else {
if (fileCompression == COMPRESSION_YAZ0) {
2024-01-24 04:00:46 -08:00
expandSize = getExpandSize(fileEntry);
if (expandSize) {
size = expandSize;
2021-05-03 02:03:24 +02:00
}
}
if (size > bufferSize) {
size = bufferSize;
}
JKRHeap::copyMemory(buffer, fileEntry->data, size);
}
if (returnSize) {
*returnSize = size;
}
return buffer;
}
2021-04-06 18:00:35 +02:00
/* 802D826C-802D8474 2D2BAC 0208+00 1/1 1/1 0/0 .text
2021-04-01 02:07:58 +02:00
* fetchResource_subroutine__13JKRDvdArchiveFlUlUlPUcUlii */
2021-05-03 02:03:24 +02:00
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);
2020-12-06 21:02:25 +01:00
2021-05-03 02:03:24 +02:00
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];
2023-07-21 19:30:25 +03:00
u8* arcHeader = (u8*)ALIGN_NEXT((u32)arcHeaderBuffer, 0x20);
JKRDvdToMainRam(entryNum, arcHeader, EXPAND_SWITCH_UNKNOWN2, sizeof(SArcHeader),
2021-05-03 02:03:24 +02:00
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: {
2023-09-19 03:46:45 -07:00
JUTException::panic(__FILE__, 649, "Sorry, not applied for SZP archive.\n");
2021-05-03 02:03:24 +02:00
}
default: {
2023-09-19 03:46:45 -07:00
JUTException::panic(__FILE__, 653, "??? bad sequence\n");
2021-05-03 02:03:24 +02:00
return 0;
}
}
}
2021-04-06 18:00:35 +02:00
/* 802D8474-802D8698 2D2DB4 0224+00 1/1 1/1 0/0 .text
2021-04-01 02:07:58 +02:00
* fetchResource_subroutine__13JKRDvdArchiveFlUlUlP7JKRHeapiiPPUc */
2021-05-03 02:03:24 +02:00
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));
2023-09-19 03:46:45 -07:00
JUT_ASSERT(675, buffer != 0);
2021-05-03 02:03:24 +02:00
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];
2023-07-21 19:30:25 +03:00
u8* arcHeader = (u8*)ALIGN_NEXT((u32)arcHeaderBuffer, 0x20);
JKRDvdToMainRam(entryNum, arcHeader, EXPAND_SWITCH_UNKNOWN2, sizeof(SArcHeader),
2021-05-03 02:03:24 +02:00
NULL, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, offset, NULL, NULL);
DCInvalidateRange(arcHeader, sizeof(SArcHeader));
alignedSize = JKRDecompExpandSize(arcHeader);
buffer = (u8*)JKRAllocFromHeap(heap, alignedSize, sizeof(SArcHeader));
2023-09-19 03:46:45 -07:00
JUT_ASSERT(715, buffer);
2021-05-03 02:03:24 +02:00
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));
2023-09-19 03:46:45 -07:00
JUT_ASSERT(735, buffer);
2021-05-03 02:03:24 +02:00
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: {
2023-09-19 03:46:45 -07:00
JUTException::panic(__FILE__, 754, "Sorry, not applied SZP archive.\n");
2021-05-03 02:03:24 +02:00
}
default: {
2023-09-19 03:46:45 -07:00
JUTException::panic(__FILE__, 758, "??? bad sequence\n");
2021-05-03 02:03:24 +02:00
return 0;
}
}
2021-01-10 02:15:52 +01:00
}
2021-03-28 22:49:05 +02:00
2021-04-06 18:00:35 +02:00
/* 802D8698-802D87D4 2D2FD8 013C+00 1/0 0/0 0/0 .text getExpandedResSize__13JKRDvdArchiveCFPCv */
2021-05-03 02:03:24 +02:00
u32 JKRDvdArchive::getExpandedResSize(const void* resource) const {
u32 resourceSize;
if (!mExpandedSize) {
return getResSize(resource);
}
SDIFileEntry* fileEntry = findPtrResource(resource);
if (!fileEntry) {
return -1;
}
if (!fileEntry->isCompressed()) {
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];
2023-07-21 19:30:25 +03:00
u8* arcHeader = (u8*)ALIGN_NEXT((u32)buffer, 0x20);
JKRDvdToMainRam(mEntryNum, arcHeader, EXPAND_SWITCH_UNKNOWN2, sizeof(SArcHeader), NULL,
2021-05-03 02:03:24 +02:00
JKRDvdRipper::ALLOC_DIRECTION_FORWARD,
2024-01-24 04:00:46 -08:00
mDataOffset + fileEntry->data_offset, NULL, NULL);
2023-07-21 19:30:25 +03:00
DCInvalidateRange(arcHeader, sizeof(SArcHeader));
2021-05-03 02:03:24 +02:00
resourceSize = JKRDecompExpandSize(arcHeader);
// ???
((JKRDvdArchive*)this)->setExpandSize(fileEntry, resourceSize);
return resourceSize;
2020-12-06 21:02:25 +01:00
}