diff --git a/include/JSystem/JKernel/JKRDecomp/JKRDecomp.h b/include/JSystem/JKernel/JKRDecomp/JKRDecomp.h index 96e9996d155..5baf3800d29 100644 --- a/include/JSystem/JKernel/JKRDecomp/JKRDecomp.h +++ b/include/JSystem/JKernel/JKRDecomp/JKRDecomp.h @@ -4,30 +4,60 @@ #include "JSystem/JKernel/JKRThread/JKRThread.h" #include "dolphin/types.h" +class JKRAMCommand; class JKRDecompCommand { public: + typedef void (*AsyncCallback)(u32); + JKRDecompCommand(); ~JKRDecompCommand(); + +public: + /* 0x00 */ u32 field_0x0; + /* 0x04 */ u8* mSrcBuffer; + /* 0x08 */ u8* mDstBuffer; + /* 0x0C */ u32 mSrcLength; + /* 0x10 */ u32 mDstLength; + /* 0x14 */ AsyncCallback mCallback; + /* 0x18 */ JKRDecompCommand* mThis; + /* 0x1C */ OSMessageQueue* field_0x1c; + /* 0x20 */ s32 field_0x20; + /* 0x24 */ JKRAMCommand* mAMCommand; + /* 0x28 */ OSMessageQueue mMessageQueue; + /* 0x48 */ OSMessage mMessage; }; +#define JKRDECOMP_SYNC_BLOCKING 0 +#define JKRDECOMP_SYNC_NON_BLOCKING 1 + class JKRDecomp : public JKRThread { private: JKRDecomp(long); - virtual ~JKRDecomp(void); + virtual ~JKRDecomp(); /* vt[03] */ virtual void* run(); /* override */ public: - static void create(long); - static void prepareCommand(u8*, u8*, u32, u32, void (*)(u32)); + enum Compression { + NONE = 0, + YAY0 = 1, + YAZ0 = 2, + ASR = 3, + + __COMPRESSION_ENUM_FORCE_S32 = INT32_MAX, + __COMPRESSION_ENUM_FORCE_SIGNED = -1, + }; + + static JKRDecomp* create(long); + static JKRDecompCommand* prepareCommand(u8*, u8*, u32, u32, JKRDecompCommand::AsyncCallback); static void sendCommand(JKRDecompCommand*); - static void sync(JKRDecompCommand*, int); - static void orderAsync(u8*, u8*, u32, u32, void (*)(u32)); - static void orderSync(u8*, u8*, u32, u32); + static bool sync(JKRDecompCommand*, int); + static JKRDecompCommand* orderAsync(u8*, u8*, u32, u32, JKRDecompCommand::AsyncCallback); + static bool orderSync(u8*, u8*, u32, u32); static void decode(u8*, u8*, u32, u32); static void decodeSZP(u8*, u8*, u32, u32); static void decodeSZS(u8*, u8*, u32, u32); - static void checkCompressed(u8*); + static Compression checkCompressed(u8*); }; #endif diff --git a/include/JSystem/JKernel/JKRHeap/JKRHeap.h b/include/JSystem/JKernel/JKRHeap/JKRHeap.h index 8f52d54fb5f..5af14cedcee 100644 --- a/include/JSystem/JKernel/JKRHeap/JKRHeap.h +++ b/include/JSystem/JKernel/JKRHeap/JKRHeap.h @@ -150,4 +150,8 @@ inline void* operator new(u32 size, void* ptr) { return ptr; } +inline void* JKRAllocFromHeap(JKRHeap* heap, u32 size, int alignment) { + return JKRHeap::alloc(size, alignment, heap); +} + #endif \ No newline at end of file diff --git a/include/JSystem/JKernel/JKRThread/JKRThread.h b/include/JSystem/JKernel/JKRThread/JKRThread.h index 1d55d235544..d259de7d11e 100644 --- a/include/JSystem/JKernel/JKRThread/JKRThread.h +++ b/include/JSystem/JKernel/JKRThread/JKRThread.h @@ -20,25 +20,52 @@ public: void setCommon_mesgQueue(JKRHeap* heap, int message_count); void setCommon_heapSpecified(JKRHeap* heap, u32 stack_size, int param_3); - OSThread* getThreadRecord() { return this->mOSThread; } + OSThread* getThreadRecord() const { return mThreadRecord; } + void* getStack() const { return mStackMemory; } + u8 getLoadInfo() const { return field_0x60; } + JKRHeap* getCurrentHeap() const { return mCurrentHeap; } + JKRHeap* getCurrentHeapError() const { return mCurrentHeapError; } + + void resume() { OSResumeThread(mThreadRecord); } + void sendMessage(OSMessage message) { + OSSendMessage(&mMessageQueue, message, OS_MESSAGE_NON_BLOCKING); + } + void sendMessageBlock(OSMessage message) { + OSSendMessage(&mMessageQueue, message, OS_MESSAGE_BLOCKING); + } + OSMessage waitMessage() { + OSMessage message; + OSReceiveMessage(&mMessageQueue, &message, OS_MESSAGE_NON_BLOCKING); + return message; + } + OSMessage waitMessageBlock() { + OSMessage message; + OSReceiveMessage(&mMessageQueue, &message, OS_MESSAGE_BLOCKING); + return message; + } + void jamMessageBlock(OSMessage message) { + OSJamMessage(&mMessageQueue, message, OS_MESSAGE_BLOCKING); + } private: - JSULink mThreadListLink; - JKRHeap* mHeap; - OSThread* mOSThread; - OSMessageQueue mQueue; - OSMessage* mMessages; - int mMessageCount; - void* mStackPtr; - u32 mStackSize; - u8 field_0x60; - u8 padding_0x61[3]; - u32 mCost; - u32 mSwitchCount; - u32 field_0x6c; - u32 field_0x70; - JKRHeap* field_0x74; - JKRHeap* field_0x78; + /* 0x00 */ // vtable + /* 0x04 */ // JKRDisposer + /* 0x18 */ JSULink mThreadListLink; + /* 0x28 */ JKRHeap* mHeap; + /* 0x2C */ OSThread* mThreadRecord; + /* 0x30 */ OSMessageQueue mMessageQueue; + /* 0x50 */ OSMessage* mMessages; + /* 0x54 */ s32 mMessageCount; + /* 0x58 */ void* mStackMemory; + /* 0x5C */ u32 mStackSize; + /* 0x60 */ u8 field_0x60; + /* 0x61 */ u8 padding_0x61[3]; + /* 0x64 */ u32 mCost; + /* 0x68 */ u32 mSwitchCount; + /* 0x6C */ u32 field_0x6c; + /* 0x70 */ u32 field_0x70; + /* 0x74 */ JKRHeap* mCurrentHeap; + /* 0x78 */ JKRHeap* mCurrentHeapError; public: static void* start(void* param_1); diff --git a/include/os/OS.h b/include/os/OS.h index baacf7a496d..98f54e3ab3a 100644 --- a/include/os/OS.h +++ b/include/os/OS.h @@ -6,6 +6,9 @@ #include "dolphin/types.h" +#define OS_MESSAGE_NON_BLOCKING 0 +#define OS_MESSAGE_BLOCKING 1 + /* TODO: more structs, and get rid of the ones that are faked! */ #define OS_MESSAGE_NON_BLOCKING 0 @@ -103,7 +106,8 @@ OSSwitchThreadCallback OSSetSwitchThreadCallback(OSSwitchThreadCallback* callbac void OSInitMessageQueue(OSMessageQueue* queue, OSMessage* messages, int message_count); BOOL OSReceiveMessage(OSMessageQueue* queue, OSMessage message, int flags); -void OSSendMessage(OSMessageQueue* queue, OSMessage message, int flags); +BOOL OSSendMessage(OSMessageQueue* queue, OSMessage message, int flags); +BOOL OSJamMessage(OSMessageQueue* queue, OSMessage message, int flags); s32 OSGetConsoleType(void); s32 OSGetResetCode(void); diff --git a/include/variables.h b/include/variables.h index aca609c7b3b..c76d3e67c3b 100644 --- a/include/variables.h +++ b/include/variables.h @@ -273,10 +273,11 @@ extern u8 lbl_8039D188; // "JKRAramArchive.cpp" extern u8 lbl_803CC3E8; // JKRCompArchive::__vt extern u8 lbl_8039D220; // "JKRCompArchive.cpp" -extern u8 lbl_803CC460[32]; // JKRDecomp::sMessageBuffer +extern OSMessage lbl_803CC460[8]; // JKRDecomp::sMessageBuffer extern OSMessageQueue lbl_803CC480; // JKRDecomp::sMessageQueue -extern u8 lbl_804514B0; // JKRDecomp::sDecompObject -extern u8 lbl_803CC4A0; // JKRDecomp::__vt +class JKRDecomp; +extern JKRDecomp* lbl_804514B0; // JKRDecomp::sDecompObject +extern u8 lbl_803CC4A0; // JKRDecomp::__vt extern u8 lbl_80434378; // JKernel::@491 (global destructor chain) extern u8 lbl_80451428; // JKernel::szpBuf diff --git a/libs/JSystem/JKernel/JKRDecomp.cpp b/libs/JSystem/JKernel/JKRDecomp.cpp index b4c6cde325d..59b39d7237b 100644 --- a/libs/JSystem/JKernel/JKRDecomp.cpp +++ b/libs/JSystem/JKernel/JKRDecomp.cpp @@ -1,77 +1,225 @@ #include "JSystem/JKernel/JKRDecomp/JKRDecomp.h" #include "global.h" -asm void JKRDecomp::create(long) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB680.s" +#include "JSystem/JKernel/JKRAramPiece/JKRAramPiece.h" + +JKRDecomp* JKRDecomp::create(long priority) { + if (!lbl_804514B0) { + lbl_804514B0 = new (JKRHeap::getSystemHeap(), 0) JKRDecomp(priority); + } + + return lbl_804514B0; } -asm JKRDecomp::JKRDecomp(long) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB6E0.s" +JKRDecomp::JKRDecomp(long priority) : JKRThread(0x800, 0x10, priority) { + resume(); } -asm JKRDecomp::~JKRDecomp(void) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB730.s" +JKRDecomp::~JKRDecomp() {} + +void* JKRDecomp::run(void) { + OSInitMessageQueue(&lbl_803CC480, lbl_803CC460, 8); + for (;;) { + OSMessage message; + OSReceiveMessage(&lbl_803CC480, &message, OS_MESSAGE_BLOCKING); + + JKRDecompCommand* command = (JKRDecompCommand*)message; + decode(command->mSrcBuffer, command->mDstBuffer, command->mSrcLength, command->mDstLength); + + if (command->field_0x20 != 0) { + if (command->field_0x20 == 1) { + JKRAramPiece::sendCommand(command->mAMCommand); + } + continue; + } + + if (command->mCallback) { + (*command->mCallback)((u32)command); + continue; + } + + if (command->field_0x1c) { + OSSendMessage(command->field_0x1c, (OSMessage)1, OS_MESSAGE_NON_BLOCKING); + } else { + OSSendMessage(&command->mMessageQueue, (OSMessage)1, OS_MESSAGE_NON_BLOCKING); + } + } } -asm void* JKRDecomp::run(void) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB790.s" +JKRDecompCommand* JKRDecomp::prepareCommand(u8* srcBuffer, u8* dstBuffer, u32 srcLength, + u32 dstLength, + JKRDecompCommand::AsyncCallback callback) { + JKRDecompCommand* command = new (JKRHeap::getSystemHeap(), -4) JKRDecompCommand(); + command->mSrcBuffer = srcBuffer; + command->mDstBuffer = dstBuffer; + command->mSrcLength = srcLength; + command->mDstLength = dstLength; + command->mCallback = callback; + return command; } -asm void JKRDecomp::prepareCommand(u8*, u8*, u32, u32, void (*)(u32)) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB858.s" +void JKRDecomp::sendCommand(JKRDecompCommand* command) { + OSSendMessage(&lbl_803CC480, command, OS_MESSAGE_NON_BLOCKING); } -asm void JKRDecomp::sendCommand(JKRDecompCommand*) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB8D0.s" +JKRDecompCommand* JKRDecomp::orderAsync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength, + JKRDecompCommand::AsyncCallback callback) { + JKRDecompCommand* command = + prepareCommand(srcBuffer, dstBuffer, srcLength, dstLength, callback); + sendCommand(command); + return command; } -asm void JKRDecomp::orderAsync(u8*, u8*, u32, u32, void (*)(u32)) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB900.s" +bool JKRDecomp::sync(JKRDecompCommand* command, int isNonBlocking) { + OSMessage message; + bool result; + if (isNonBlocking == JKRDECOMP_SYNC_BLOCKING) { + OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCKING); + result = true; + } else { + result = + OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NON_BLOCKING) != FALSE; + } + + return result; } -asm void JKRDecomp::sync(JKRDecompCommand*, int) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB934.s" +bool JKRDecomp::orderSync(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength) { + JKRDecompCommand* command = orderAsync(srcBuffer, dstBuffer, srcLength, dstLength, NULL); + bool result = sync(command, JKRDECOMP_SYNC_BLOCKING); + delete command; + return result; } -asm void JKRDecomp::orderSync(u8*, u8*, u32, u32) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB988.s" +void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength) { + Compression compression = checkCompressed(srcBuffer); + if (compression == JKRDecomp::YAY0) { + decodeSZP(srcBuffer, dstBuffer, srcLength, dstLength); + } else if (compression == JKRDecomp::YAZ0) { + decodeSZS(srcBuffer, dstBuffer, srcLength, dstLength); + } } -asm void JKRDecomp::decode(u8*, u8*, u32, u32) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DB9DC.s" -} +#define READ_BIG_ENDIAN_U32(P) \ + (((u32)(((u8*)(P))[0]) << 0x18) | ((u32)(((u8*)(P))[1]) << 0x10) | \ + ((u32)(((u8*)(P))[2]) << 8) | ((u32)(((u8*)(P))[3]))) +#define READ_BIG_ENDIAN_U16(P) (((u32)(((u8*)(P))[0]) << 8) | ((u32)(((u8*)(P))[1]))) + +// All instructions match. Wrong registers are used. +#ifdef NONMATCHING +void JKRDecomp::decodeSZP(u8* src, u8* dst, u32 srcLength, u32 dstLength) { + u32 decodedSize; + s32 srcChunkOffset; + s32 count; + s32 dstOffset; + u32 length; + u32 counter; + u32 srcDataOffset; + u32 linkTableOffset; + s32 offset; + s32 i; + + decodedSize = READ_BIG_ENDIAN_U32(src + 4); + linkTableOffset = READ_BIG_ENDIAN_U32(src + 8); + srcDataOffset = READ_BIG_ENDIAN_U32(src + 12); + + dstOffset = 0; + counter = 0; + srcChunkOffset = 16; + + u32 chunkBits; + if (srcLength == 0) + return; + if (dstLength > decodedSize) + return; + + length = srcLength; + do { + if (counter == 0) { + chunkBits = READ_BIG_ENDIAN_U32(src + srcChunkOffset); + srcChunkOffset += 4; + counter = 32; + } + + if (chunkBits & 0x80000000) { + if (dstLength == 0) { + dst[dstOffset] = src[srcDataOffset]; + length--; + if (length == 0) { + return; + } + } else { + dstLength--; + } + dstOffset++; + srcDataOffset++; + } else { + u32 linkInfo = READ_BIG_ENDIAN_U16(src + linkTableOffset); + linkTableOffset += 2; + + offset = dstOffset - (linkInfo & 0xFFF); + count = ((s32)linkInfo) >> 12; + if (count == 0) { + count = (u32)src[srcDataOffset] + 0x12; + srcDataOffset++; + } else { + count += 2; + } + + if (count > decodedSize - dstOffset) { + count = decodedSize - dstOffset; + } + + for (i = 0; i < count; i++, dstOffset++, offset++) { + if (dstLength == 0) { + dst[dstOffset] = dst[offset - 1]; + length--; + if (length == 0) { + return; + } + } else { + dstLength--; + } + } + } + + chunkBits <<= 1; + counter--; + } while ((s32)dstLength < decodedSize); +} +#else asm void JKRDecomp::decodeSZP(u8*, u8*, u32, u32) { nofralloc #include "JSystem/JKernel/JKRDecomp/asm/func_802DBA58.s" } +#endif -asm void JKRDecomp::decodeSZS(u8*, u8*, u32, u32) { - nofralloc +asm void JKRDecomp::decodeSZS(u8*, u8*, u32, u32){nofralloc #include "JSystem/JKernel/JKRDecomp/asm/func_802DBC14.s" } -asm void JKRDecomp::checkCompressed(u8*) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DBCF8.s" +JKRDecomp::Compression JKRDecomp::checkCompressed(u8* src) { + if ((src[0] == 'Y') && (src[1] == 'a') && (src[3] == '0')) { + if (src[2] == 'y') { + return JKRDecomp::YAY0; + } + if (src[2] == 'z') { + return JKRDecomp::YAZ0; + } + } + if ((src[0] == 'A') && (src[1] == 'S') && (src[2] == 'R')) { + return JKRDecomp::ASR; + } + return JKRDecomp::NONE; } -asm JKRDecompCommand::JKRDecompCommand(void) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DBD70.s" +JKRDecompCommand::JKRDecompCommand() { + OSInitMessageQueue(&mMessageQueue, &mMessage, 1); + mCallback = NULL; + field_0x1c = NULL; + mThis = this; + field_0x20 = 0; } -asm JKRDecompCommand::~JKRDecompCommand(void) { - nofralloc -#include "JSystem/JKernel/JKRDecomp/asm/func_802DBDC0.s" -} +JKRDecompCommand::~JKRDecompCommand() {} diff --git a/libs/JSystem/JKernel/JKRThread.cpp b/libs/JSystem/JKernel/JKRThread.cpp index 59b29907fdc..cb80d65aba9 100644 --- a/libs/JSystem/JKernel/JKRThread.cpp +++ b/libs/JSystem/JKernel/JKRThread.cpp @@ -2,38 +2,36 @@ #include "JSystem/JKernel/JKRHeap/JKRHeap.h" #include "global.h" -// #include "JSystem/JKernel/JKRThread/asm/func_802D1568.s" JKRThread::JKRThread(u32 stack_size, int message_count, int param_3) : mThreadListLink(this) { - this->mSwitchCount = 0; - this->mCost = 0; - this->field_0x6c = 0; - this->field_0x60 = 0; - this->field_0x70 = 0; + mSwitchCount = 0; + mCost = 0; + field_0x6c = 0; + field_0x60 = 0; + field_0x70 = 0; JKRHeap* heap = JKRHeap::findFromRoot(this); if (heap == NULL) { heap = lbl_80451370; } - this->setCommon_heapSpecified(heap, stack_size, param_3); - this->setCommon_mesgQueue(this->mHeap, message_count); + setCommon_heapSpecified(heap, stack_size, param_3); + setCommon_mesgQueue(mHeap, message_count); } -// #include "JSystem/JKernel/JKRThread/asm/func_802D1610.s" JKRThread::JKRThread(JKRHeap* heap, u32 stack_size, int message_count, int param_4) : mThreadListLink(this) { - this->mSwitchCount = 0; - this->mCost = 0; - this->field_0x6c = 0; - this->field_0x60 = 0; - this->field_0x70 = 0; + mSwitchCount = 0; + mCost = 0; + field_0x6c = 0; + field_0x60 = 0; + field_0x70 = 0; if (heap == NULL) { heap = lbl_80451374; } - this->setCommon_heapSpecified(heap, stack_size, param_4); - this->setCommon_mesgQueue(this->mHeap, message_count); + setCommon_heapSpecified(heap, stack_size, param_4); + setCommon_mesgQueue(mHeap, message_count); } asm JKRThread::JKRThread(OSThread* thread, int message_count) { @@ -46,43 +44,39 @@ asm JKRThread::~JKRThread() { #include "JSystem/JKernel/JKRThread/asm/func_802D1758.s" } -// #include "JSystem/JKernel/JKRThread/asm/func_802D1830.s" void JKRThread::setCommon_mesgQueue(JKRHeap* heap, int message_count) { - this->mMessageCount = message_count; - this->mMessages = (OSMessage*)JKRHeap::alloc(this->mMessageCount * sizeof(OSMessage), 0, heap); + mMessageCount = message_count; + mMessages = (OSMessage*)JKRHeap::alloc(mMessageCount * sizeof(OSMessage), 0, heap); - OSInitMessageQueue(&this->mQueue, this->mMessages, this->mMessageCount); - lbl_8043428C.append(&this->mThreadListLink); + OSInitMessageQueue(&mMessageQueue, mMessages, mMessageCount); + lbl_8043428C.append(&mThreadListLink); - this->field_0x74 = (JKRHeap*)NULL; - this->field_0x78 = (JKRHeap*)NULL; + mCurrentHeap = NULL; + mCurrentHeapError = NULL; } -// #include "JSystem/JKernel/JKRThread/asm/func_802D18A4.s" void JKRThread::setCommon_heapSpecified(JKRHeap* heap, u32 stack_size, int param_3) { - this->mHeap = heap; - this->mStackSize = stack_size & 0xffffffe0; - this->mStackPtr = JKRHeap::alloc(this->mStackSize, 0x20, this->mHeap); - this->mOSThread = (OSThread*)JKRHeap::alloc(sizeof(OSThread), 0x20, this->mHeap); + mHeap = heap; + mStackSize = stack_size & 0xffffffe0; + mStackMemory = JKRAllocFromHeap(mHeap, mStackSize, 0x20); + mThreadRecord = (OSThread*)JKRAllocFromHeap(mHeap, sizeof(OSThread), 0x20); - void* stackBase = (void*)((int)this->mStackPtr + this->mStackSize); - OSCreateThread(this->mOSThread, start, this, stackBase, this->mStackSize, param_3, 1); + void* stackBase = (void*)((int)mStackMemory + mStackSize); + OSCreateThread(mThreadRecord, start, this, stackBase, mStackSize, param_3, 1); } -// #include "JSystem/JKernel/JKRThread/asm/func_802D1934.s" void* JKRThread::start(void* param) { JKRThread* thread = (JKRThread*)param; return thread->run(); } #ifdef NONMATCHING -// #include "JSystem/JKernel/JKRThread/asm/func_802D1960.s" JKRThread* JKRThread::searchThread(OSThread* thread) { JSUList* threadList = JKRThread::getList(); JSUListIterator iterator; for (iterator = threadList; iterator != threadList->getEnd(); iterator++) { JKRThread* jkrThread = iterator.getObject(); - if (jkrThread->mOSThread == thread) { + if (jkrThread->mThreadRecord == thread) { return jkrThread; } } @@ -129,7 +123,6 @@ asm void JKRThreadSwitch::draw(JKRThreadName_* param_1, JUTConsole* param_2) { // // -// #include "JSystem/JKernel/JKRThread/asm/func_802D1E14.s" void* JKRThread::run() { return NULL; } diff --git a/tools/clang-format-all.sh b/tools/clang-format-all.sh new file mode 100644 index 00000000000..926dff4c180 --- /dev/null +++ b/tools/clang-format-all.sh @@ -0,0 +1,8 @@ +#!/bin/bash +echo "formatting src/*" +find ./src -iname *.h -o -iname *.cpp | xargs clang-format -i +echo "formatting libs/*" +find ./libs -iname *.h -o -iname *.cpp | xargs clang-format -i +echo "formatting include/*" +find ./include -iname *.h -o -iname *.cpp | xargs clang-format -i +echo "done"