mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-08-22 05:49:04 -04:00
merge cuyler's PR
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#include "JSystem/JKernel/JKRAram.h"
|
||||
|
||||
JKRAramBlock::JKRAramBlock(u32 address, u32 size, u32 freeSize, u8 groupID, bool tempMemory)
|
||||
: mLink(this)
|
||||
, mAddress(address)
|
||||
, mSize(size)
|
||||
, mFreeSize(freeSize)
|
||||
, mGroupID(groupID)
|
||||
, mIsTempMemory(tempMemory)
|
||||
{
|
||||
}
|
||||
|
||||
JKRAramBlock::~JKRAramBlock() {
|
||||
JSULink<JKRAramBlock>* prev = this->mLink.getPrev();
|
||||
JSUList<JKRAramBlock>* list = this->mLink.getList();
|
||||
|
||||
if (prev) {
|
||||
prev->getObject()->mFreeSize += this->mSize + this->mFreeSize;
|
||||
list->remove(&this->mLink);
|
||||
}
|
||||
else {
|
||||
this->mFreeSize += this->mSize;
|
||||
this->mSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
JKRAramBlock* JKRAramBlock::allocHead(u32 size, u8 groupID, JKRAramHeap* heap) {
|
||||
u32 address = this->mAddress + this->mSize;
|
||||
u32 freeSize = this->mFreeSize - size;
|
||||
|
||||
JKRAramBlock* block = new(heap->mHeap, nullptr) JKRAramBlock(address, size, freeSize, groupID, false);
|
||||
this->mFreeSize = 0;
|
||||
this->mLink.mPtrList->insert(this->mLink.mNext, &block->mLink);
|
||||
return block;
|
||||
}
|
||||
|
||||
JKRAramBlock* JKRAramBlock::allocTail(u32 size, u8 groupID, JKRAramHeap* heap) {
|
||||
u32 address = this->mAddress + this->mSize + this->mFreeSize - size;
|
||||
|
||||
JKRAramBlock* block = new(heap->mHeap, nullptr) JKRAramBlock(address, size, 0, groupID, true);
|
||||
this->mFreeSize -= size;
|
||||
this->mLink.mPtrList->insert(this->mLink.mNext, &block->mLink);
|
||||
return block;
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
#include "JSystem/JKernel/JKRAram.h"
|
||||
#include "JSystem/JSystem.h"
|
||||
#include "dolphin/os.h" /* TODO: OSReport is actually in libforest */
|
||||
|
||||
JSUList<JKRAramBlock> JKRAramHeap::sAramList;
|
||||
|
||||
JKRAramHeap::JKRAramHeap(u32 baseAddress, u32 size) : JKRDisposer() {
|
||||
OSInitMutex(&this->mMutex);
|
||||
this->mHeap = JKRHeap::findFromRoot(this);
|
||||
this->mSize = ALIGN_PREV(size, 0x20);
|
||||
this->mHeadAddress = ALIGN_NEXT(baseAddress, 0x20);
|
||||
this->mTailAddress = this->mHeadAddress + this->mSize;
|
||||
this->mGroupID = 0xFF;
|
||||
JKRAramBlock* block = new (this->mHeap, nullptr)
|
||||
JKRAramBlock(this->mHeadAddress, 0, this->mSize, 0xFF, false);
|
||||
sAramList.append(&block->mLink);
|
||||
}
|
||||
|
||||
JKRAramHeap::~JKRAramHeap() {
|
||||
for (JSUListIterator<JKRAramBlock> it = sAramList.getFirst();
|
||||
it != sAramList.getEnd();) {
|
||||
delete (it++).getObject();
|
||||
}
|
||||
}
|
||||
|
||||
JKRAramBlock* JKRAramHeap::alloc(u32 size, JKRAramHeap::EAllocMode mode) {
|
||||
JKRAramBlock* block;
|
||||
this->lock();
|
||||
|
||||
if (mode == Head) {
|
||||
block = this->allocFromHead(size);
|
||||
} else {
|
||||
block = this->allocFromTail(size);
|
||||
}
|
||||
|
||||
this->unlock();
|
||||
return block;
|
||||
}
|
||||
|
||||
/* Code retrieved from Twilight Princess Debug version & matched. Unused in AC. */
|
||||
void JKRAramHeap::free(JKRAramBlock* block) {
|
||||
delete block;
|
||||
}
|
||||
|
||||
JKRAramBlock* JKRAramHeap::allocFromHead(u32 size) {
|
||||
size = ALIGN_NEXT(size, 32);
|
||||
u32 min_size = 0xFFFFFFFFUL;
|
||||
JKRAramBlock* block = nullptr;
|
||||
|
||||
for (JSUListIterator<JKRAramBlock> it = sAramList.getFirst();
|
||||
it != sAramList.getEnd(); it++) {
|
||||
JKRAramBlock* n_block = it.getObject();
|
||||
if (n_block->mFreeSize >= size && min_size > n_block->mFreeSize) {
|
||||
min_size = n_block->mFreeSize;
|
||||
block = n_block;
|
||||
if (block->mFreeSize == size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block != nullptr) {
|
||||
return block->allocHead(size, this->mGroupID, this);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JKRAramBlock* JKRAramHeap::allocFromTail(u32 size) {
|
||||
JKRAramBlock* block = nullptr;
|
||||
size = ALIGN_NEXT(size, 32);
|
||||
|
||||
for (JSUListIterator<JKRAramBlock> it = sAramList.getLast();
|
||||
it != sAramList.getEnd(); it--) {
|
||||
JKRAramBlock* n_block = it.getObject();
|
||||
|
||||
if (n_block->mFreeSize >= size) {
|
||||
block = n_block;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (block != nullptr) {
|
||||
return block->allocTail(size, this->mGroupID, this);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Debug code retrieved from Twilight Princess Debug version */
|
||||
void JKRAramHeap::dump() {
|
||||
this->lock();
|
||||
|
||||
int total_used = 0;
|
||||
JREPORT("\nJKRAramHeap dump\n");
|
||||
JREPORT(" attr address: size gid\n");
|
||||
|
||||
for (JSUListIterator<JKRAramBlock> listItr = sAramList.getFirst();
|
||||
listItr != sAramList.getEnd(); listItr++) {
|
||||
if (listItr->mSize != 0) {
|
||||
JREPORTF("%s %08x: %08x %3d\n",
|
||||
listItr->isTempMemory() ? " temp" : "alloc", listItr->mAddress,
|
||||
listItr->mSize, listItr->mGroupID);
|
||||
}
|
||||
|
||||
if (listItr->mFreeSize != 0) {
|
||||
JREPORTF(" free %08x: %08x 0\n", listItr->mAddress + listItr->mSize,
|
||||
listItr->mFreeSize);
|
||||
}
|
||||
|
||||
total_used += listItr->mSize;
|
||||
}
|
||||
|
||||
JREPORTF("%d / %d bytes (%6.2f%%) used\n", total_used, this->mSize,
|
||||
(f32)total_used / (f32)this->mSize);
|
||||
|
||||
this->unlock();
|
||||
}
|
||||
|
||||
/* Not present in AC, recreated from TP debug. TODO: Check for matching. */
|
||||
u32 JKRAramHeap::getFreeSize() {
|
||||
u32 max_free = 0;
|
||||
this->lock();
|
||||
|
||||
for (JSUListIterator<JKRAramBlock> it = sAramList.getFirst(); it != sAramList.getEnd(); it++) {
|
||||
if (it->mFreeSize > max_free) {
|
||||
max_free = it->mFreeSize;
|
||||
}
|
||||
}
|
||||
|
||||
this->unlock();
|
||||
return max_free;
|
||||
}
|
||||
|
||||
/* Not present in AC, recreated from TP debug. TODO: Check for matching. */
|
||||
u32 JKRAramHeap::getTotalFreeSize() {
|
||||
u32 total_free = 0;
|
||||
this->lock();
|
||||
|
||||
for (JSUListIterator<JKRAramBlock> it = sAramList.getFirst(); it != sAramList.getEnd(); it++) {
|
||||
total_free += it->mFreeSize;
|
||||
}
|
||||
|
||||
this->unlock();
|
||||
return total_free;
|
||||
}
|
||||
|
||||
/* Not present in AC, recreated from TP debug. TODO: Check for matching. */
|
||||
u32 JKRAramHeap::getUsedSize(u8 groupID) {
|
||||
u32 total_used = 0;
|
||||
this->lock();
|
||||
|
||||
if (groupID == ARAM_GROUP_ID_ALL) {
|
||||
total_used = this->mSize - this->getTotalFreeSize();
|
||||
}
|
||||
else {
|
||||
for (JSUListIterator<JKRAramBlock> it = sAramList.getFirst(); it != sAramList.getEnd(); it++) {
|
||||
if (groupID == it->mGroupID) {
|
||||
total_used += it->mSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->unlock();
|
||||
return total_used;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "types.h"
|
||||
#include "dolphin/ar.h"
|
||||
#include "dolphin/os/OSCache.h"
|
||||
#include "dolphin/os/OSMessage.h"
|
||||
#include "dolphin/os.h" /* TODO: OSReport lives in libforest in AC */
|
||||
#include "JSystem/JKernel/JKRMacro.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "JSystem/JKernel/JKRDecomp.h"
|
||||
#include "JSystem/JSystem.h"
|
||||
|
||||
#include "JSystem/JKernel/JKRAram.h"
|
||||
|
||||
JSUList<JKRAMCommand> JKRAramPiece::sAramPieceCommandList;
|
||||
OSMutex JKRAramPiece::mMutex;
|
||||
|
||||
JKRAMCommand* JKRAramPiece::prepareCommand(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) {
|
||||
JKRAMCommand* cmd = new (JKRGetSystemHeap(), -4) JKRAMCommand();
|
||||
cmd->mDirection = direction;
|
||||
cmd->mSource = source;
|
||||
cmd->mDestination = destination;
|
||||
cmd->mAramBlock = aramBlock;
|
||||
cmd->mLength = length;
|
||||
cmd->mCallback = callback;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void JKRAramPiece::sendCommand(JKRAMCommand* cmd) {
|
||||
JKRAramPiece::startDMA(cmd);
|
||||
}
|
||||
|
||||
JKRAMCommand* JKRAramPiece::orderAsync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock, JKRAMCommand::AMCommandCallback callback) {
|
||||
JKRAramPiece::lock();
|
||||
|
||||
if (!JKR_ISALIGNED32(source) || !JKR_ISALIGNED32(destination)) {
|
||||
JLOGF("direction = %x\n", direction);
|
||||
JLOGF("source = %x\n", source);
|
||||
JLOGF("destination = %x\n", destination);
|
||||
JLOGF("length = %x\n", length);
|
||||
JPANICLINE(102);
|
||||
}
|
||||
|
||||
JKRAramCommand* aramCmd = new (JKRGetSystemHeap(), -4) JKRAramCommand();
|
||||
JKRAMCommand* cmd = JKRAramPiece::prepareCommand(direction, source, destination, length, aramBlock, callback);
|
||||
aramCmd->setting(TRUE, cmd);
|
||||
OSSendMessage((OSMessageQueue*)&JKRAram::sMessageQueue, (OSMessage)aramCmd, OS_MESSAGE_BLOCK);
|
||||
if (cmd->mCallback != nullptr) {
|
||||
JKRAramPiece::sAramPieceCommandList.append(&cmd->mAramPieceCommandLink);
|
||||
}
|
||||
|
||||
JKRAramPiece::unlock();
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool JKRAramPiece::sync(JKRAMCommand* cmd, BOOL noBlock) {
|
||||
OSMessage msg[1];
|
||||
|
||||
JKRAramPiece::lock();
|
||||
|
||||
if (!noBlock) {
|
||||
OSReceiveMessage(&cmd->mMesgQueue, msg, OS_MESSAGE_BLOCK);
|
||||
JKRAramPiece::sAramPieceCommandList.remove(&cmd->mAramPieceCommandLink);
|
||||
JKRAramPiece::unlock();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (!OSReceiveMessage(&cmd->mMesgQueue, msg, OS_MESSAGE_NOBLOCK)) {
|
||||
JKRAramPiece::unlock();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
JKRAramPiece::sAramPieceCommandList.remove(&cmd->mAramPieceCommandLink);
|
||||
JKRAramPiece::unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool JKRAramPiece::orderSync(int direction, u32 source, u32 destination, u32 length, JKRAramBlock* aramBlock) {
|
||||
JKRAramPiece::lock();
|
||||
|
||||
JKRAMCommand* cmd = JKRAramPiece::orderAsync(direction, source, destination, length, aramBlock, nullptr);
|
||||
bool res = JKRAramPiece::sync(cmd, FALSE);
|
||||
delete cmd;
|
||||
|
||||
JKRAramPiece::unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
void JKRAramPiece::startDMA(JKRAMCommand* cmd) {
|
||||
if (cmd->mDirection == ARAM_DIR_ARAM_TO_MRAM) {
|
||||
DCInvalidateRange((u8*)cmd->mDestination, cmd->mLength);
|
||||
}
|
||||
else { /* cmd->mDirection == ARAM_DIR_MRAM_TO_ARAM */
|
||||
DCStoreRange((u8*)cmd->mSource, cmd->mLength);
|
||||
}
|
||||
|
||||
ARQPostRequest(cmd, 0, cmd->mDirection, 0, cmd->mSource, cmd->mDestination, cmd->mLength, JKRAramPiece::doneDMA);
|
||||
}
|
||||
|
||||
void JKRAramPiece::doneDMA(u32 param) {
|
||||
JKRAMCommand* cmd = (JKRAMCommand*)param;
|
||||
if (cmd->mDirection == ARAM_DIR_ARAM_TO_MRAM) {
|
||||
DCInvalidateRange((u8*)cmd->mDestination, cmd->mLength);
|
||||
}
|
||||
if (cmd->mCallbackType != ARAMPIECE_DONE_CALLBACK) {
|
||||
if (cmd->mCallbackType == ARAMPIECE_DONE_DECOMPRESS) {
|
||||
JKRDecomp::sendCommand(cmd->mDecompCommand);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (cmd->mCallback != nullptr) {
|
||||
(*cmd->mCallback)(param);
|
||||
}
|
||||
else {
|
||||
if (cmd->mCompletedMesgQueue != nullptr) {
|
||||
OSSendMessage(cmd->mCompletedMesgQueue, (OSMessage)cmd, OS_MESSAGE_NOBLOCK);
|
||||
}
|
||||
else {
|
||||
OSSendMessage(&cmd->mMesgQueue, (OSMessage)cmd, OS_MESSAGE_NOBLOCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JKRAMCommand::JKRAMCommand() : mAramPieceCommandLink(this), mLink30(this) {
|
||||
OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, 1);
|
||||
this->mCallback = nullptr;
|
||||
this->mCompletedMesgQueue = nullptr;
|
||||
this->mCallbackType = ARAMPIECE_DONE_CALLBACK;
|
||||
this->_8C = nullptr;
|
||||
this->_90 = nullptr;
|
||||
this->_94 = nullptr;
|
||||
}
|
||||
|
||||
JKRAMCommand::~JKRAMCommand() {
|
||||
if (this->_8C != nullptr) {
|
||||
delete this->_8C;
|
||||
}
|
||||
|
||||
if (this->_90 != nullptr) {
|
||||
delete this->_90;
|
||||
}
|
||||
|
||||
if (this->_94 != nullptr) {
|
||||
JKRFree(this->_94);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "JKRAram.h"
|
||||
#include "JSUStream.h"
|
||||
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
#include "types.h"
|
||||
#include "dolphin/os/OSMessage.h"
|
||||
#include "JSystem/JSystem.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "JSystem/JKernel/JKRAram.h"
|
||||
|
||||
#include "JSystem/JKernel/JKRDecomp.h"
|
||||
|
||||
OSMessage JKRDecomp::sMessageBuffer[JKRDECOMP_MSG_BUF_COUNT] = { 0 };
|
||||
OSMessageQueue JKRDecomp::sMessageQueue = { 0 };
|
||||
JKRDecomp* JKRDecomp::sDecompObject;
|
||||
|
||||
JKRDecomp* JKRDecomp::create(s32 decompPriority) {
|
||||
if (JKRDecomp::sDecompObject == nullptr) {
|
||||
JKRDecomp::sDecompObject = new(JKRGetSystemHeap(), 0) JKRDecomp(decompPriority);
|
||||
}
|
||||
|
||||
return JKRDecomp::sDecompObject;
|
||||
}
|
||||
|
||||
JKRDecomp::JKRDecomp(s32 priority) : JKRThread(JKRDECOMP_STACK_SIZE, JKRDECOMP_THREAD_MSG_BUF_COUNT, priority) {
|
||||
OSResumeThread(this->mThreadRecord);
|
||||
}
|
||||
|
||||
JKRDecomp::~JKRDecomp() { }
|
||||
|
||||
void* JKRDecomp::run() {
|
||||
OSMessage recMesg;
|
||||
JKRDecompCommand* cmd;
|
||||
OSInitMessageQueue(&JKRDecomp::sMessageQueue, JKRDecomp::sMessageBuffer, JKRDECOMP_MSG_BUF_COUNT);
|
||||
|
||||
while (true) {
|
||||
while (true) {
|
||||
while (true) {
|
||||
OSReceiveMessage(&JKRDecomp::sMessageQueue, &recMesg, OS_MESSAGE_BLOCK);
|
||||
cmd = static_cast<JKRDecompCommand*>(recMesg);
|
||||
JKRDecomp::decode(cmd->mSrcBuffer, cmd->mDstBuffer, cmd->mSrcLength, cmd->mSkipCount);
|
||||
|
||||
if (cmd->transferType == JKRDecompCommand::MRAM) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd->transferType == JKRDecompCommand::ARAM) {
|
||||
JKRAramPcs_SendCommand(cmd->mAMCommand);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->mCallback == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
cmd->mCallback((u32)cmd);
|
||||
}
|
||||
|
||||
if (cmd->pMesgQueue1C != nullptr) {
|
||||
OSSendMessage(cmd->pMesgQueue1C, (OSMessage)1, OS_MESSAGE_NOBLOCK);
|
||||
}
|
||||
else {
|
||||
OSSendMessage(&cmd->mMesgQueue, (OSMessage)1, OS_MESSAGE_NOBLOCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount, DecompCallback* callback) {
|
||||
JKRDecompCommand* cmd = new(JKRGetSystemHeap(), -4) JKRDecompCommand();
|
||||
|
||||
cmd->mSrcBuffer = srcBuffer;
|
||||
cmd->mDstBuffer = dstBuffer;
|
||||
cmd->mSrcLength = srcLength;
|
||||
cmd->mSkipCount = skipCount;
|
||||
cmd->mCallback = callback;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
BOOL JKRDecomp::sendCommand(JKRDecompCommand* cmd) {
|
||||
BOOL res = OSSendMessage(&JKRDecomp::sMessageQueue, (OSMessage)cmd, OS_MESSAGE_BLOCK);
|
||||
|
||||
#ifdef JSYSTEM_DEBUG
|
||||
if (res == FALSE) {
|
||||
JPANIC(142, "Decomp MesgBuf FULL!");
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
JKRDecompCommand* JKRDecomp::orderAsync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount, DecompCallback* callback) {
|
||||
JKRDecompCommand* cmd = JKRDecomp::prepareCommand(srcBuffer, dstBuffer, srcLength, skipCount, callback);
|
||||
JKRDecomp::sendCommand(cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool JKRDecomp::sync(JKRDecompCommand* cmd, BOOL noBlock) {
|
||||
OSMessage msg;
|
||||
|
||||
if (!noBlock) {
|
||||
OSReceiveMessage(&cmd->mMesgQueue, &msg, OS_MESSAGE_BLOCK);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return OSReceiveMessage(&cmd->mMesgQueue, &msg, OS_MESSAGE_NOBLOCK) != FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool JKRDecomp::orderSync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount) {
|
||||
JKRDecompCommand* cmd = JKRDecomp::orderAsync(srcBuffer, dstBuffer, srcLength, skipCount, nullptr);
|
||||
bool res = JKRDecomp::sync(cmd, FALSE);
|
||||
delete cmd;
|
||||
return res;
|
||||
}
|
||||
|
||||
void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 skipCount) {
|
||||
CompressionMode mode = JKRDecomp::checkCompressed(srcBuffer);
|
||||
if (mode == SZP) {
|
||||
JKRDecomp::decodeSZP(srcBuffer, dstBuffer, srcLength, skipCount);
|
||||
}
|
||||
else if (mode == SZS) {
|
||||
JKRDecomp::decodeSZS(srcBuffer, dstBuffer, srcLength, skipCount);
|
||||
}
|
||||
}
|
||||
|
||||
void JKRDecomp::decodeSZP(u8 *src, u8 *dst, u32 srcLength, u32 skipCount)
|
||||
{
|
||||
int srcChunkOffset;
|
||||
int count;
|
||||
int dstOffset;
|
||||
u32 length;
|
||||
int linkInfo;
|
||||
int offset;
|
||||
int i;
|
||||
|
||||
int decodedSize = JKRDECOMP_READU32BE(src, 4);
|
||||
int linkTableOffset = JKRDECOMP_READU32BE(src, 8);
|
||||
int srcDataOffset = JKRDECOMP_READU32BE(src, 12);
|
||||
|
||||
dstOffset = 0;
|
||||
u32 counter = 0; // curently counter gets assembled before the READ_U32 operations
|
||||
srcChunkOffset = 16;
|
||||
|
||||
u32 chunkBits;
|
||||
if (srcLength == 0)
|
||||
return;
|
||||
if (skipCount > decodedSize)
|
||||
return;
|
||||
|
||||
length = srcLength;
|
||||
do
|
||||
{
|
||||
if (counter == 0)
|
||||
{
|
||||
chunkBits = JKRDECOMP_READU32BE(src, srcChunkOffset);
|
||||
srcChunkOffset += sizeof(u32);
|
||||
counter = sizeof(u32) * 8;
|
||||
}
|
||||
|
||||
if (chunkBits & 0x80000000)
|
||||
{
|
||||
if (skipCount == 0)
|
||||
{
|
||||
dst[dstOffset] = src[srcDataOffset];
|
||||
length--;
|
||||
if (length == 0)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
skipCount--;
|
||||
}
|
||||
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 ((int)count > decodedSize - dstOffset)
|
||||
count = decodedSize - dstOffset;
|
||||
|
||||
for (i = 0; i < (int)count; i++, dstOffset++, offset++)
|
||||
{
|
||||
if (skipCount == 0)
|
||||
{
|
||||
dst[dstOffset] = dst[offset - 1];
|
||||
length--;
|
||||
if (length == 0)
|
||||
return;
|
||||
}
|
||||
else
|
||||
skipCount--;
|
||||
}
|
||||
}
|
||||
|
||||
chunkBits <<= 1;
|
||||
counter--;
|
||||
} while (dstOffset < decodedSize);
|
||||
}
|
||||
|
||||
void JKRDecomp::decodeSZS(u8 *src_buffer, u8 *dst_buffer, u32 srcSize, u32 skipCount) {
|
||||
|
||||
u8 *decompEnd = dst_buffer + *(u32 *)(src_buffer + 4) - skipCount;
|
||||
u8 *copyStart;
|
||||
s32 copyByteCount;
|
||||
s32 chunkBitsLeft = 0;
|
||||
s32 chunkBits;
|
||||
|
||||
if (srcSize == 0)
|
||||
return;
|
||||
if (skipCount > *(u32 *)src_buffer)
|
||||
return;
|
||||
|
||||
u8 *curSrcPos = src_buffer + 0x10;
|
||||
do {
|
||||
if (chunkBitsLeft == 0) {
|
||||
chunkBits = *curSrcPos++;
|
||||
chunkBitsLeft = 8;
|
||||
}
|
||||
if ((chunkBits & 0x80) != 0) {
|
||||
if (skipCount == 0)
|
||||
{
|
||||
*dst_buffer = *curSrcPos;
|
||||
srcSize--;
|
||||
dst_buffer++;
|
||||
if (srcSize == 0)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
skipCount--;
|
||||
}
|
||||
curSrcPos++;
|
||||
}
|
||||
else {
|
||||
u8 curVal = *curSrcPos;
|
||||
copyStart = dst_buffer - (curSrcPos[1] | (curVal & 0xF) << 8);
|
||||
curSrcPos += 2;
|
||||
if (curVal >> 4 == 0) {
|
||||
copyByteCount = *curSrcPos + 0x12;
|
||||
curSrcPos++;
|
||||
}
|
||||
else {
|
||||
copyByteCount = (curVal >> 4) + 2;
|
||||
}
|
||||
do {
|
||||
if (skipCount == 0) {
|
||||
*dst_buffer = *(copyStart - 1);
|
||||
srcSize--;
|
||||
dst_buffer++;
|
||||
if (srcSize == 0)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
skipCount--;
|
||||
}
|
||||
copyByteCount--;
|
||||
copyStart++;
|
||||
} while (copyByteCount != 0);
|
||||
}
|
||||
chunkBits <<= 1;
|
||||
chunkBitsLeft--;
|
||||
} while (dst_buffer != decompEnd);
|
||||
}
|
||||
|
||||
JKRDecomp::CompressionMode JKRDecomp::checkCompressed(u8* buf) {
|
||||
if (buf[0] == 'Y' && buf[1] == 'a' && buf[3] == '0') {
|
||||
if (buf[2] == 'y') {
|
||||
return SZP;
|
||||
}
|
||||
|
||||
if (buf[2] == 'z') {
|
||||
return SZS;
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
JKRDecompCommand::JKRDecompCommand() {
|
||||
OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, 1);
|
||||
this->mCallback = nullptr;
|
||||
this->pMesgQueue1C = nullptr;
|
||||
this->mCmd = this;
|
||||
this->transferType = MRAM;
|
||||
}
|
||||
|
||||
JKRDecompCommand::~JKRDecompCommand() { }
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "JSystem/JKernel/JKRDvdFile.h"
|
||||
|
||||
JSUList<JKRDvdFile> JKRDvdFile::sDvdList;
|
||||
|
||||
JKRDvdFile::JKRDvdFile() : JKRFile(), mLink(this) { this->initiate(); }
|
||||
|
||||
/* This method is confirmed to exist, but goes unused in AC. Retrieved from TP debug. */
|
||||
JKRDvdFile::JKRDvdFile(const char* filename) : JKRFile(), mLink(this) {
|
||||
this->initiate();
|
||||
this->mFileOpen = this->open(filename);
|
||||
|
||||
if (this->isAvailable()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JKRDvdFile::JKRDvdFile(s32 entrynum) : JKRFile(), mLink(this) {
|
||||
this->initiate();
|
||||
this->mFileOpen = this->open(entrynum);
|
||||
|
||||
if (this->isAvailable()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JKRDvdFile::~JKRDvdFile() { this->close(); }
|
||||
|
||||
void JKRDvdFile::initiate() {
|
||||
/* Reference to self. Used to retrieve reference in the DVDReadAsync
|
||||
* DVDCallback func. */
|
||||
this->mDvdFileInfo.mFile = this;
|
||||
OSInitMutex(&this->mMutex1);
|
||||
OSInitMutex(&this->mMutex2);
|
||||
OSInitMessageQueue(&this->mMessageQueue2, &this->mMsg2, 1);
|
||||
OSInitMessageQueue(&this->mMessageQueue1, &this->mMsg1, 1);
|
||||
this->mThread2 = nullptr;
|
||||
this->mThread1 = nullptr;
|
||||
this->_58 = 0;
|
||||
}
|
||||
|
||||
/* This method is confirmed to exist, but goes unused in AC. Retrieved from TP debug. */
|
||||
bool JKRDvdFile::open(const char* filename) {
|
||||
if (this->mFileOpen == false) {
|
||||
this->mFileOpen = DVDOpen((char*)filename, &this->mDvdFileInfo);
|
||||
if (this->mFileOpen) {
|
||||
sDvdList.append(&this->mLink);
|
||||
DVDGetFileInfoStatus(&this->mDvdFileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return this->mFileOpen;
|
||||
}
|
||||
|
||||
bool JKRDvdFile::open(s32 entrynum) {
|
||||
if (this->mFileOpen == false) {
|
||||
this->mFileOpen = DVDFastOpen(entrynum, &this->mDvdFileInfo);
|
||||
if (this->mFileOpen) {
|
||||
sDvdList.append(&this->mLink);
|
||||
DVDGetFileInfoStatus(&this->mDvdFileInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return this->mFileOpen;
|
||||
}
|
||||
|
||||
bool JKRDvdFile::close() {
|
||||
if (this->mFileOpen) {
|
||||
if (DVDClose(&this->mDvdFileInfo)) {
|
||||
this->mFileOpen = false;
|
||||
return sDvdList.remove(&this->mLink);
|
||||
} else {
|
||||
OSErrorLine(212, "cannot close DVD file\n"); /* JKRDvdFile.cpp line 212 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int JKRDvdFile::readData(void* data, s32 length, s32 ofs) {
|
||||
OSLockMutex(&this->mMutex1);
|
||||
s32 retAddr;
|
||||
|
||||
if (this->mThread2 != nullptr) {
|
||||
OSUnlockMutex(&this->mMutex1);
|
||||
return -1;
|
||||
} else {
|
||||
this->mThread2 = OSGetCurrentThread();
|
||||
retAddr = -1;
|
||||
if (DVDReadAsync(&this->mDvdFileInfo, data, length, ofs,
|
||||
JKRDvdFile::doneProcess)) {
|
||||
retAddr = this->sync();
|
||||
}
|
||||
|
||||
this->mThread2 = nullptr;
|
||||
OSUnlockMutex(&this->mMutex1);
|
||||
}
|
||||
|
||||
return retAddr;
|
||||
}
|
||||
|
||||
int JKRDvdFile::writeData(const void* data, s32 length, s32 ofs) { return -1; }
|
||||
|
||||
s32 JKRDvdFile::sync() {
|
||||
OSMessage m;
|
||||
|
||||
OSLockMutex(&this->mMutex1);
|
||||
OSReceiveMessage(&this->mMessageQueue2, &m, OS_MESSAGE_BLOCK);
|
||||
this->mThread2 = nullptr;
|
||||
OSUnlockMutex(&this->mMutex1);
|
||||
return (s32)m;
|
||||
}
|
||||
|
||||
void JKRDvdFile::doneProcess(s32 result, DVDFileInfo* info) {
|
||||
OSSendMessage(&static_cast<JKRDvdFileInfo*>(info)->mFile->mMessageQueue2,
|
||||
(OSMessage)result, OS_MESSAGE_NOBLOCK);
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "dolphin/vi.h"
|
||||
#include "JSystem/JSystem.h"
|
||||
#include "JSystem/JKernel/JKRMacro.h"
|
||||
#include "JSystem/JKernel/JKRDvdFile.h"
|
||||
#include "JSystem/JKernel/JKRDecomp.h"
|
||||
|
||||
#include "JSystem/JKernel/JKRDvdRipper.h"
|
||||
|
||||
JSUList<JKRDMCommand> JKRDvdRipper::sDvdAsyncList;
|
||||
bool JKRDvdRipper::errorRetry = true;
|
||||
|
||||
static int decompSZS_subroutine(u8* src, u8* dest);
|
||||
static u8* firstSrcData();
|
||||
static u8* nextSrcData(u8* nowData);
|
||||
|
||||
void* JKRDvdRipper::loadToMainRAM(const char* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* compressMode) {
|
||||
JKRDvdFile dvdFile;
|
||||
|
||||
if (!dvdFile.open(file)) {
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
return JKRDvdRipper::loadToMainRAM(&dvdFile, buf, expandSwitch, maxDest, heap, allocDir, offset, compressMode);
|
||||
}
|
||||
}
|
||||
|
||||
void* JKRDvdRipper::loadToMainRAM(s32 entrynum, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* compressMode) {
|
||||
JKRDvdFile dvdFile;
|
||||
|
||||
if (!dvdFile.open(entrynum)) {
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
return JKRDvdRipper::loadToMainRAM(&dvdFile, buf, expandSwitch, maxDest, heap, allocDir, offset, compressMode);
|
||||
}
|
||||
}
|
||||
|
||||
void* JKRDvdRipper::loadToMainRAM(JKRDvdFile* file, u8* buf, JKRExpandSwitch expandSwitch, u32 maxDest, JKRHeap* heap, EAllocDirection allocDir, u32 offset, int* compressMode) {
|
||||
u32 finalSize;
|
||||
|
||||
bool allocated = false;
|
||||
JKRDecomp::CompressionMode fileCompressMode = JKRDecomp::NONE;
|
||||
u8* mem = nullptr;
|
||||
u32 fileSize = ALIGN_NEXT(file->getFileSize(), 32);
|
||||
|
||||
if (expandSwitch == EXPAND_SWITCH_DECOMPRESS) {
|
||||
u8 buffer[64];
|
||||
u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32);
|
||||
while (true) {
|
||||
if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, 0, 2) >= 0) {
|
||||
break;
|
||||
}
|
||||
if (JKRDvdRipper::errorRetry == false) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
|
||||
fileCompressMode = JKRCheckCompressed(aligned_buf);
|
||||
finalSize = JKRDecompExpandSize(aligned_buf);
|
||||
}
|
||||
|
||||
if (compressMode != nullptr) {
|
||||
*compressMode = fileCompressMode;
|
||||
}
|
||||
|
||||
if (expandSwitch == EXPAND_SWITCH_DECOMPRESS && fileCompressMode != JKRDecomp::NONE) {
|
||||
if (maxDest != 0 && finalSize > maxDest) {
|
||||
finalSize = maxDest;
|
||||
}
|
||||
|
||||
if (buf == nullptr) {
|
||||
buf = (u8*)JKRAllocFromHeap(heap, finalSize, allocDir == ALLOC_DIR_TOP ? 32 : -32);
|
||||
allocated = true;
|
||||
}
|
||||
|
||||
if (buf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (fileCompressMode == JKRDecomp::SZP) {
|
||||
mem = (u8*)JKRAllocFromHeap(heap, fileSize, 32);
|
||||
if (mem == nullptr && allocated == true) {
|
||||
JKRFree(buf);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (buf == nullptr) {
|
||||
buf = (u8*)JKRAllocFromHeap(heap, fileSize - offset, allocDir == ALLOC_DIR_TOP ? 32 : -32);
|
||||
allocated = true;
|
||||
}
|
||||
|
||||
if (buf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileCompressMode == JKRDecomp::NONE) {
|
||||
JKRDecomp::CompressionMode subCompressMode = JKRDecomp::NONE;
|
||||
|
||||
if (offset != 0) {
|
||||
u8 buffer[64];
|
||||
u8* aligned_buf = (u8*)ALIGN_NEXT((u32)buffer, 32);
|
||||
while (true) {
|
||||
if (DVDReadPrio(file->getFileInfo(), aligned_buf, 32, offset, 2) >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (JKRDvdRipper::errorRetry == false) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
|
||||
subCompressMode = JKRCheckCompressed(aligned_buf);
|
||||
}
|
||||
|
||||
if (subCompressMode == JKRDecomp::NONE || expandSwitch == EXPAND_SWITCH_NONE || expandSwitch == EXPAND_SWITCH_DEFAULT) {
|
||||
s32 readSize = fileSize - offset;
|
||||
if (maxDest != 0 && maxDest < readSize) {
|
||||
readSize = maxDest;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (DVDReadPrio(file->getFileInfo(), buf, readSize, offset, 2) >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (JKRDvdRipper::errorRetry == false) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (subCompressMode == JKRDecomp::SZS) {
|
||||
JKRDecompressFromDVD(file, buf, fileSize, maxDest, 0, offset);
|
||||
}
|
||||
else {
|
||||
JPANIC(297, "Sorry, not prepared for SZP resource\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (fileCompressMode == JKRDecomp::SZP) {
|
||||
if (offset != 0) {
|
||||
JPANIC(306, ":::Not support SZP with offset read");
|
||||
}
|
||||
|
||||
/* Looks like a bug here */
|
||||
#ifndef FIXES
|
||||
if (DVDReadPrio(file->getFileInfo(), mem, fileSize, 0, 2) < 0) {
|
||||
if (JKRDvdRipper::errorRetry == false) {
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
|
||||
JKRFree(mem);
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
JKRDecompress(mem, buf, finalSize, offset);
|
||||
JKRFree(mem);
|
||||
return buf;
|
||||
}
|
||||
#else
|
||||
while (DVDReadPrio(file->getFileInfo(), mem, fileSize, 0, 2) < 0) {
|
||||
if (JKRDvdRipper::errorRetry == false) {
|
||||
if (allocated) {
|
||||
JKRFree(buf);
|
||||
}
|
||||
|
||||
JKRFree(mem);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
|
||||
JKRDecompress(mem, buf, finalSize, 0);
|
||||
JKRFree(mem);
|
||||
#endif
|
||||
}
|
||||
else if (fileCompressMode == JKRDecomp::SZS) {
|
||||
JKRDecompressFromDVD(file, buf, fileSize, finalSize, offset, 0);
|
||||
return buf;
|
||||
}
|
||||
else {
|
||||
if (allocated) {
|
||||
JKRFree(buf);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
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 int JKRDecompressFromDVD(JKRDvdFile* _srcFile, void* buf, u32 size, u32 _maxDest, u32 _fileOffset, u32 _srcOffset) {
|
||||
int res = 0;
|
||||
|
||||
szpBuf = (u8*)JKRAllocFromSysHeap(SZP_BUFFERSIZE, -32);
|
||||
szpEnd = szpBuf + SZP_BUFFERSIZE;
|
||||
|
||||
if (_fileOffset != 0) {
|
||||
refBuf = (u8*)JKRAllocFromSysHeap(REF_BUFFERSIZE, -4);
|
||||
refEnd = refBuf + REF_BUFFERSIZE;
|
||||
refCurrent = refBuf;
|
||||
}
|
||||
else {
|
||||
refBuf = nullptr;
|
||||
}
|
||||
|
||||
srcFile = _srcFile;
|
||||
srcOffset = _srcOffset;
|
||||
transLeft = size - _srcOffset;
|
||||
fileOffset = _fileOffset;
|
||||
readCount = 0;
|
||||
maxDest = _maxDest;
|
||||
|
||||
u8* src = firstSrcData();
|
||||
if (src != nullptr) {
|
||||
res = decompSZS_subroutine(src, (u8*)buf);
|
||||
}
|
||||
|
||||
JKRFree(szpBuf);
|
||||
|
||||
if (refBuf != nullptr) {
|
||||
JKRFree(refBuf);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int decompSZS_subroutine(u8* src, u8* dest) {
|
||||
u8 *endPtr;
|
||||
s32 validBitCount = 0;
|
||||
s32 currCodeByte = 0;
|
||||
u32 ts = 0;
|
||||
|
||||
if ((s32)src[0] != 'Y' || (s32)src[1] != 'a' || (s32)src[2] != 'z' || (s32)src[3] != '0')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
SZPHeader *header = (SZPHeader *)src;
|
||||
endPtr = dest + (header->decompSize - fileOffset);
|
||||
if (endPtr > dest + maxDest)
|
||||
{
|
||||
endPtr = dest + maxDest;
|
||||
}
|
||||
|
||||
src += 0x10;
|
||||
do
|
||||
{
|
||||
if (validBitCount == 0)
|
||||
{
|
||||
if ((src > srcLimit) && transLeft)
|
||||
{
|
||||
src = nextSrcData(src);
|
||||
if (!src)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
currCodeByte = *src;
|
||||
validBitCount = 8;
|
||||
src++;
|
||||
}
|
||||
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;
|
||||
dest++;
|
||||
src++;
|
||||
ts++;
|
||||
if (dest == endPtr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
readCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 dist = src[1] | (src[0] & 0x0f) << 8;
|
||||
s32 numBytes = src[0] >> 4;
|
||||
src += 2;
|
||||
u8 *copySource;
|
||||
if (fileOffset != 0)
|
||||
{
|
||||
copySource = refCurrent - dist - 1;
|
||||
if (copySource < refBuf)
|
||||
{
|
||||
copySource += refEnd - refBuf;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
copySource = dest - dist - 1;
|
||||
}
|
||||
if (numBytes == 0)
|
||||
{
|
||||
numBytes = *src + 0x12;
|
||||
src += 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
readCount++;
|
||||
numBytes--;
|
||||
copySource++;
|
||||
} while (numBytes != 0);
|
||||
}
|
||||
}
|
||||
currCodeByte <<= 1;
|
||||
validBitCount--;
|
||||
} while (dest < endPtr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8* firstSrcData() {
|
||||
srcLimit = szpEnd - 0x19;
|
||||
u8* buf = szpBuf;
|
||||
u32 size = (szpEnd - szpBuf);
|
||||
u32 transSize = MIN(transLeft, size);
|
||||
|
||||
while (true) {
|
||||
if (DVDReadPrio(srcFile->getFileInfo(), buf, transSize, srcOffset, 2) < 0) {
|
||||
if (JKRDvdRipper::errorRetry == false) {
|
||||
return nullptr;
|
||||
}
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
else {
|
||||
srcOffset += transSize;
|
||||
transLeft -= transSize;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u8* nextSrcData(u8* nowData) {
|
||||
u32 size = (szpEnd - nowData);
|
||||
u8* dst;
|
||||
if (JKR_ISNOTALIGNED32(size)) {
|
||||
dst = szpBuf + 32 - (size & 31);
|
||||
}
|
||||
else {
|
||||
dst = szpBuf;
|
||||
}
|
||||
|
||||
memcpy(dst, nowData, size);
|
||||
|
||||
u32 n_size = (szpEnd - (dst + size));
|
||||
if (n_size > transLeft) {
|
||||
n_size = transLeft;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (DVDReadPrio(srcFile->getFileInfo(), (dst + size), n_size, srcOffset, 2) >= 0) {
|
||||
break;
|
||||
}
|
||||
// Oopsies, forgot to call the function
|
||||
#ifndef FIXES
|
||||
if (JKRDvdRipper::isErrorRetry == false) {
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
if (JKRDvdRipper::isErrorRetry() == false) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
|
||||
srcOffset += n_size;
|
||||
transLeft -= n_size;
|
||||
|
||||
if (transLeft == 0) {
|
||||
srcLimit = (dst + size) + n_size;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "JSystem/JKernel/JKRFile.h"
|
||||
#include "dolphin/vi.h"
|
||||
|
||||
#ifdef JSYSTEM_DEBUG
|
||||
#include "JSystem/JUtility/JUTAssertion.h"
|
||||
#endif
|
||||
|
||||
/* Empty space for aligning line numbers */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Nonmatched function. Unused in Animal Crossing.
|
||||
*/
|
||||
void JKRFile::read(void* data, s32 length, s32 ofs) {
|
||||
#ifdef JSYSTEM_DEBUG
|
||||
if (!JKR_ISALIGNED(length, 32)) {
|
||||
JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, __LINE__, "( length & 0x1f ) == 0");
|
||||
}
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
if (this->readData(data, length, ofs) == length) {
|
||||
return;
|
||||
}
|
||||
|
||||
VIWaitForRetrace();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "JSystem/JUT/JUTAssertion.h"
|
||||
#include "JSystem/JUtility/JUTAssertion.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "dolphin/os.h"
|
||||
#include "dolphin/os/OSArena.h"
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "JSystem/JKernel/JKRThread.h"
|
||||
|
||||
#include "JSystem/JSupport/JSUList.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "JSystem/JKernel/JKRMacro.h"
|
||||
|
||||
JSUList<JKRThread> JKRThread::sThreadList;
|
||||
|
||||
JKRThread::JKRThread(u32 stackSize, int msgCount, int threadPrio)
|
||||
: JKRDisposer(), mLink(this) {
|
||||
this->mHeap = JKRHeap::findFromRoot(this);
|
||||
if (this->mHeap == nullptr) {
|
||||
this->mHeap = JKRHeap::sSystemHeap;
|
||||
}
|
||||
|
||||
this->mStackSize = JKR_ALIGN32(stackSize);
|
||||
this->mStackMemory = JKRHeap::alloc(this->mStackSize, 32, this->mHeap);
|
||||
this->mThreadRecord =
|
||||
(OSThread *)JKRHeap::alloc(sizeof(OSThread), 32, this->mHeap);
|
||||
OSCreateThread(this->mThreadRecord, &JKRThread::start, this,
|
||||
(void *)((u32)this->mStackMemory + this->mStackSize),
|
||||
this->mStackSize, threadPrio, OS_THREAD_ATTR_DETACH);
|
||||
this->mMesgCount = msgCount;
|
||||
this->mMesgBuffer = (OSMessage *)JKRHeap::alloc(
|
||||
mMesgCount * sizeof(OSMessage), 0, this->mHeap);
|
||||
OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount);
|
||||
JKRThread::sThreadList.append(&this->mLink);
|
||||
}
|
||||
|
||||
JKRThread::JKRThread(OSThread *threadRecord, int msgCount)
|
||||
: JKRDisposer(), mLink(this) {
|
||||
this->mHeap = nullptr;
|
||||
this->mThreadRecord = threadRecord;
|
||||
this->mStackSize = (u32)threadRecord->stackEnd - (u32)threadRecord->stackBase;
|
||||
this->mStackMemory = threadRecord->stackBase;
|
||||
this->mMesgCount = msgCount;
|
||||
this->mMesgBuffer = (OSMessage *)JKRHeap::sSystemHeap->alloc(
|
||||
mMesgCount * sizeof(OSMessage), 4);
|
||||
OSInitMessageQueue(&this->mMesgQueue, this->mMesgBuffer, this->mMesgCount);
|
||||
JKRThread::sThreadList.append(&this->mLink);
|
||||
}
|
||||
|
||||
JKRThread::~JKRThread() {
|
||||
JKRThread::sThreadList.remove(&this->mLink);
|
||||
|
||||
if (this->mHeap != nullptr) {
|
||||
if (!OSIsThreadTerminated(this->mThreadRecord)) {
|
||||
OSDetachThread(this->mThreadRecord);
|
||||
OSCancelThread(this->mThreadRecord);
|
||||
}
|
||||
|
||||
JKRHeap::free(this->mStackMemory, this->mHeap);
|
||||
JKRHeap::free(this->mThreadRecord, this->mHeap);
|
||||
}
|
||||
|
||||
JKRHeap::free(this->mMesgBuffer, nullptr);
|
||||
}
|
||||
|
||||
void *JKRThread::start(void *thread) {
|
||||
return static_cast<JKRThread*>(thread)->run();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "JSystem/JKernel/JKRThread.h"
|
||||
|
||||
__declspec(weak) void* JKRThread::run() { return nullptr; }
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "JSystem/JSupport/JSUStream.h"
|
||||
|
||||
JSUFileInputStream::JSUFileInputStream(JKRFile* file)
|
||||
: mObject(file), mPosition(0) {}
|
||||
|
||||
int JSUFileInputStream::readData(void* buf, s32 len) {
|
||||
int read = 0;
|
||||
|
||||
if (((JKRFile*)this->mObject)->isAvailable()) {
|
||||
/* Check if need to clamp length to EOF */
|
||||
if ((u32)(this->mPosition + len) >
|
||||
((JKRFile*)this->mObject)->getFileSize()) {
|
||||
len = ((JKRFile*)this->mObject)->getFileSize() - this->mPosition;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
read = ((JKRFile*)this->mObject)->readData(buf, len, this->mPosition);
|
||||
this->mPosition += read;
|
||||
}
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
int JSUFileInputStream::seekPos(s32 offset, JSUStreamSeekFrom from) {
|
||||
int pos = this->mPosition;
|
||||
|
||||
switch (from) {
|
||||
case SEEK_SET:
|
||||
this->mPosition = offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
this->mPosition = ((JKRFile*)this->mObject)->getFileSize() - offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
this->mPosition = pos + offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->mPosition < 0) {
|
||||
this->mPosition = 0;
|
||||
}
|
||||
|
||||
if (this->mPosition > (s32)((JKRFile*)this->mObject)->getFileSize()) {
|
||||
this->mPosition = ((JKRFile*)this->mObject)->getFileSize();
|
||||
}
|
||||
|
||||
return this->mPosition - pos;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "JSystem/JSupport/JSUStream.h"
|
||||
|
||||
JSUInputStream::~JSUInputStream() { }
|
||||
|
||||
int JSUInputStream::read(void* buf, s32 size) {
|
||||
int len = this->readData(buf, size);
|
||||
if (len != size) {
|
||||
this->setState(EOF);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
char* JSUInputStream::read(char* str) {
|
||||
u16 size;
|
||||
int len = this->readData(&size, sizeof(size));
|
||||
if (len != sizeof(size)) {
|
||||
str[0] = '\0';
|
||||
this->setState(EOF);
|
||||
str = nullptr;
|
||||
}
|
||||
else {
|
||||
int strRead = this->readData(str, size);
|
||||
str[strRead] = '\0';
|
||||
if (strRead != size) {
|
||||
this->setState(EOF);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/* @fabricated -- this method is confirmed to exist, but goes unused in AC */
|
||||
char* JSUInputStream::readString() {
|
||||
u16 len;
|
||||
int r = this->readData(&len, sizeof(len));
|
||||
if (r != sizeof(len)) {
|
||||
this->setState(EOF);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char* buf = new char[len+1];
|
||||
r = this->readData(buf, len);
|
||||
if (r != len) {
|
||||
delete[] buf;
|
||||
this->setState(EOF);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* @fabricated -- this method is confirmed to exist, but goes unused in AC */
|
||||
char* JSUInputStream::readString(char* buf, u16 len) {
|
||||
int r = this->readData(buf, len);
|
||||
if (r != len) {
|
||||
this->setState(EOF);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buf[len] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int JSUInputStream::skip(s32 amount) {
|
||||
u8 _p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < amount; i++) {
|
||||
if (this->readData(&_p, sizeof(_p)) != sizeof(_p)) {
|
||||
this->setState(EOF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* JSURandomInputStream */
|
||||
|
||||
int JSURandomInputStream::skip(s32 amount) {
|
||||
int s = this->seekPos(amount, SEEK_CUR);
|
||||
if (s != amount) {
|
||||
this->setState(EOF);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* This method is confirmed to exist, but goes unused in AC. Retrieved from TP debug. */
|
||||
int JSURandomInputStream::align(s32 alignment) {
|
||||
int pos = this->getPosition();
|
||||
int aligned = ((alignment-1) + pos) & ~(alignment-1);
|
||||
int change = aligned - pos;
|
||||
|
||||
if (change != 0) {
|
||||
int s = this->seekPos(aligned, SEEK_SET);
|
||||
if (s != change) {
|
||||
this->setState(EOF);
|
||||
}
|
||||
}
|
||||
|
||||
return change;
|
||||
}
|
||||
|
||||
/* This method is confirmed to exist, but goes unused in AC. Retrieved from TP debug. */
|
||||
int JSURandomInputStream::peek(void* buf, s32 len) {
|
||||
int pos = this->getPosition();
|
||||
int r = this->read(buf, len);
|
||||
if (r != 0) {
|
||||
this->seekPos(pos, SEEK_SET);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int JSURandomInputStream::seek(s32 offset, JSUStreamSeekFrom from) {
|
||||
int s = this->seekPos(offset, from);
|
||||
this->clrState(EOF);
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#include "types.h"
|
||||
#include "dolphin/os.h"
|
||||
#include "dolphin/PPCArch.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef void (*voidfunctionptr)(void); // pointer to function returning void
|
||||
__declspec(section ".ctors") extern voidfunctionptr _ctors[];
|
||||
__declspec(section ".dtors") extern voidfunctionptr _dtors[];
|
||||
|
||||
static void __init_cpp(void);
|
||||
|
||||
// clang-format off
|
||||
__declspec(section ".init") asm void __init_hardware(void) {
|
||||
nofralloc
|
||||
mfmsr r0
|
||||
ori r0,r0,0x2000
|
||||
mtmsr r0
|
||||
mflr r31
|
||||
bl __OSPSInit
|
||||
bl __OSCacheInit
|
||||
mtlr r31
|
||||
blr
|
||||
}
|
||||
|
||||
__declspec(section ".init") asm void __flush_cache(void) {
|
||||
nofralloc
|
||||
lis r5, 0xFFFFFFF1@h
|
||||
ori r5, r5, 0xFFFFFFF1@l
|
||||
and r5, r5, r3
|
||||
subf r3, r5, r3
|
||||
add r4, r4, r3
|
||||
loop:
|
||||
dcbst 0, r5
|
||||
sync
|
||||
icbi 0, r5
|
||||
addic r5, r5, 8
|
||||
addic. r4, r4, -8
|
||||
bge loop
|
||||
isync
|
||||
blr
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
|
||||
void __init_user(void) { __init_cpp(); }
|
||||
|
||||
static void __init_cpp(void)
|
||||
{
|
||||
voidfunctionptr* constructor;
|
||||
/*
|
||||
* call static initializers
|
||||
*/
|
||||
for (constructor = _ctors; *constructor; constructor++) {
|
||||
(*constructor)();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void __fini_cpp(void)
|
||||
{
|
||||
// UNUSED FUNCTION
|
||||
}
|
||||
|
||||
void _ExitProcess(void) { PPCHalt(); }
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user