merge cuyler's PR

This commit is contained in:
Prakxo
2023-03-13 07:15:03 +00:00
parent cf13cc2139
commit 3dd5dbcf59
48 changed files with 3102 additions and 215 deletions
+44
View File
@@ -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;
}
+166
View File
@@ -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;
}
+149
View File
@@ -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);
}
}
+4
View File
@@ -0,0 +1,4 @@
#include "JKRAram.h"
#include "JSUStream.h"
+295
View File
@@ -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() { }
+114
View File
@@ -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);
}
+466
View File
@@ -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;
}
+43
View File
@@ -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 -1
View File
@@ -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"
+61
View File
@@ -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();
}
+3
View File
@@ -0,0 +1,3 @@
#include "JSystem/JKernel/JKRThread.h"
__declspec(weak) void* JKRThread::run() { return nullptr; }
+51
View File
@@ -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;
}
+120
View File
@@ -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;
}
+69
View File
@@ -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