// // Generated by dtk // Translation Unit: JKRDecomp.cpp // #include "JSystem/JSystem.h" // IWYU pragma: keep #include "JSystem/JKernel/JKRDecomp.h" #include "JSystem/JKernel/JKRAramPiece.h" #include "dolphin/types.h" JKRDecomp* JKRDecomp::sDecompObject; /* 802BE890-802BE8F0 .text create__9JKRDecompFl */ JKRDecomp* JKRDecomp::create(s32 priority) { if (!sDecompObject) { sDecompObject = new (JKRHeap::getSystemHeap(), 0) JKRDecomp(priority); } return sDecompObject; } OSMessage JKRDecomp::sMessageBuffer[4] = {NULL}; OSMessageQueue JKRDecomp::sMessageQueue = {0}; /* 802BE8F0-802BE940 .text __ct__9JKRDecompFl */ JKRDecomp::JKRDecomp(s32 priority) : JKRThread(0x4000, 0x10, priority) { resume(); } /* 802BE940-802BE9A0 .text __dt__9JKRDecompFv */ JKRDecomp::~JKRDecomp() {} /* 802BE9A0-802BEA68 .text run__9JKRDecompFv */ void* JKRDecomp::run() { OSInitMessageQueue(&sMessageQueue, sMessageBuffer, 4); while (true) { OSMessage message; OSReceiveMessage(&sMessageQueue, &message, OS_MESSAGE_BLOCK); JKRDecompCommand* command = (JKRDecompCommand*)message; decode(command->mSrcBuffer, command->mDstBuffer, command->mSrcLength, command->mDstLength); if (command->field_0x20 != 0) { if (command->field_0x20 == 1) { 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_NOBLOCK); } else { OSSendMessage(&command->mMessageQueue, (OSMessage)1, OS_MESSAGE_NOBLOCK); } } } /* 802BEA68-802BEAE0 .text prepareCommand__9JKRDecompFPUcPUcUlUlPFUl_v */ 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; } /* 802BEAE0-802BEB10 .text sendCommand__9JKRDecompFP16JKRDecompCommand */ void JKRDecomp::sendCommand(JKRDecompCommand* command) { OSSendMessage(&sMessageQueue, command, OS_MESSAGE_BLOCK); } /* 802BEB10-802BEB44 .text orderAsync__9JKRDecompFPUcPUcUlUlPFUl_v */ 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; } /* 802BEB44-802BEB98 .text sync__9JKRDecompFP16JKRDecompCommandi */ bool JKRDecomp::sync(JKRDecompCommand* command, int isNonBlocking) { OSMessage message; bool result; if (isNonBlocking == JKRDECOMP_SYNC_BLOCKING) { OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_BLOCK); result = true; } else { result = OSReceiveMessage(&command->mMessageQueue, &message, OS_MESSAGE_NOBLOCK) != FALSE; } return result; } /* 802BEB98-802BEBEC .text orderSync__9JKRDecompFPUcPUcUlUl */ 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; } /* 802BEBEC-802BEC68 .text decode__9JKRDecompFPUcPUcUlUl */ void JKRDecomp::decode(u8* srcBuffer, u8* dstBuffer, u32 srcLength, u32 dstLength) { JKRCompression compression = checkCompressed(srcBuffer); if (compression == COMPRESSION_YAY0) { decodeSZP(srcBuffer, dstBuffer, srcLength, dstLength); } else if (compression == COMPRESSION_YAZ0) { decodeSZS(srcBuffer, dstBuffer, srcLength, dstLength); } } /* 802BEC68-802BEE24 .text decodeSZP__9JKRDecompFPUcPUcUlUl */ void JKRDecomp::decodeSZP(u8* src, u8* dst, u32 srcLength, u32 dstLength) { int srcChunkOffset; int count; int dstOffset; u32 length = srcLength; int linkInfo; int offset; int i; int decodedSize = READU32_BE(src, 4); int linkTableOffset = READU32_BE(src, 8); int srcDataOffset = READU32_BE(src, 12); dstOffset = 0; u32 counter = 0; srcChunkOffset = 16; u32 chunkBits; if (srcLength == 0) return; if (dstLength > decodedSize) return; do { if (counter == 0) { chunkBits = READU32_BE(src, srcChunkOffset); srcChunkOffset += sizeof(u32); counter = sizeof(u32) * 8; } if (chunkBits & 0x80000000) { if (dstLength == 0) { dst[dstOffset] = src[srcDataOffset]; length--; if (length == 0) return; } else { dstLength--; } dstOffset++; srcDataOffset++; } else { linkInfo = src[linkTableOffset] << 8 | src[linkTableOffset + 1]; linkTableOffset += sizeof(u16); offset = dstOffset - (linkInfo & 0xFFF); count = (linkInfo >> 12); if (count == 0) { count = (u32)src[srcDataOffset++] + 0x12; } else count += 2; if (count > decodedSize - dstOffset) count = decodedSize - dstOffset; for (i = 0; i < count; i++, dstOffset++, offset++) { if (dstLength == 0) { dst[dstOffset] = dst[offset - 1]; length--; if (length == 0) return; } else dstLength--; } } chunkBits <<= 1; counter--; } while (dstOffset < decodedSize); } /* 802BEE24-802BEF08 .text decodeSZS__9JKRDecompFPUcPUcUlUl */ void JKRDecomp::decodeSZS(u8* src_buffer, u8* dst_buffer, u32 srcSize, u32 dstSize) { u8* decompEnd; u8* copyStart; s32 copyByteCount; s32 chunkBitsLeft = 0; s32 chunkBits; decompEnd = dst_buffer + *(int*)(src_buffer + 4) - dstSize; if (srcSize == 0) { return; } if (dstSize > *(u32*)src_buffer) { return; } u8* curSrcPos = src_buffer + 0x10; do { if (chunkBitsLeft == 0) { chunkBits = curSrcPos[0]; chunkBitsLeft = 8; curSrcPos++; } if ((chunkBits & 0x80) != 0) { if (dstSize == 0) { dst_buffer[0] = curSrcPos[0]; srcSize--; dst_buffer++; if (srcSize == 0) return; } else { dstSize--; } curSrcPos++; } else { u32 local_28 = curSrcPos[1] | (curSrcPos[0] & 0xF) << 8; u32 r31 = curSrcPos[0] >> 4; curSrcPos += 2; copyStart = dst_buffer - local_28; if (r31 == 0) { copyByteCount = curSrcPos[0] + 0x12; curSrcPos++; } else { copyByteCount = r31 + 2; } do { if (dstSize == 0) { dst_buffer[0] = copyStart[-1]; srcSize--; dst_buffer++; if (srcSize == 0) return; } else { dstSize--; } copyByteCount--; copyStart++; } while (copyByteCount != 0); } chunkBits <<= 1; chunkBitsLeft--; } while (dst_buffer != decompEnd); } /* 802BEF08-802BEF58 .text checkCompressed__9JKRDecompFPUc */ JKRCompression JKRDecomp::checkCompressed(u8* src) { if ((src[0] == 'Y') && (src[1] == 'a') && (src[3] == '0')) { if (src[2] == 'y') { return COMPRESSION_YAY0; } if (src[2] == 'z') { return COMPRESSION_YAZ0; } } return COMPRESSION_NONE; } /* 802BEF58-802BEFA8 .text __ct__16JKRDecompCommandFv */ JKRDecompCommand::JKRDecompCommand() { OSInitMessageQueue(&mMessageQueue, &mMessage, 1); mCallback = NULL; field_0x1c = NULL; mThis = this; field_0x20 = 0; } /* 802BEFA8-802BEFE4 .text __dt__16JKRDecompCommandFv */ JKRDecompCommand::~JKRDecompCommand() {}