From efdaf621cbebae7d73800cfb2def92a5466127ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Na=C5=9Bciszewski?= Date: Tue, 15 Dec 2020 00:00:08 +0100 Subject: Translating Decompression Hopefully part one of many, some NONMATCHINGs in the larger functions, sadly. --- src/file_system.c | 1431 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1428 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/file_system.c b/src/file_system.c index c328d6a..b2aad05 100644 --- a/src/file_system.c +++ b/src/file_system.c @@ -6,9 +6,22 @@ extern struct OpenedFile gFileCache[64]; extern u32 gFileCacheCursorPosition; extern u32 gUnknown_202D2A4; +extern const u32 gByteShiftLookup[4]; + +extern u32 *gDecompressBufferPtr; +extern u32 *gDecompressBufferStart; +extern u32 gDecompressBufferCurrent; +extern u32 gDecompressBufferByteInInt; + extern int sprintf(char *, const char *, ...); -extern u32 sub_800AAB4(u32 r0, u32 r1, u32 r2); +void DecompressAT_Init(u32 *buffer); +void DecompressAT_AppendByte(char value); +void DecompressAT_Finish(void); +char DecompressAT_GetByte(int index); + +u32 DecompressAT(char *result, u32 resultLength, const char *compressedData); +u32 DecompressATGlobal(u32 *result, u32 resultLength, const char *compressedData); u8 *GetSiroPtr(struct OpenedFile *); void NDS_DecompressRLE(void *); @@ -203,7 +216,1419 @@ void nullsub_175(void) { } -u32 sub_800AAA8(u32 r0, u32 r1, struct UnkFileStruct1 *r2) +u32 DecompressATFile(char *result, u32 resultLength, struct OpenedFile *file) +{ + return DecompressAT(result, resultLength, file->data); +} + +// 800AAB4 +#ifndef NONMATCHING +NAKED +#endif +u32 DecompressAT(char *result, u32 resultLength, const char *compressedData) +{ +#ifdef NONMATCHING + + // This function is an absolute mess, the compiler does some extremely weird things + // which makes matching it difficult. + + // As-is, it's likely that this implementation is nonfunctional + // as I've shuffled things around a lot while trying to make some parts match. + + int flags1; + int flags2; + int flags3; + int flags4; + int flags5; + int flags6; + int flags7; + int flags8; + int flags9; + int compressedLength; + char c10; + char c11; + u32 curIndex; + int v12; + char c13; + const char *p; + int command; + int resultIndex; + int v16; + int cmdBit; + int currentByte; + + compressedLength = compressedData[5] + (compressedData[6] << 8); + resultIndex = 0; + currentByte = 0; + cmdBit = 8; + + if (compressedData[0] == 'A' + && compressedData[1] == 'T' + && compressedData[2] == '4' + && compressedData[3] == 'P') { + if (resultLength != compressedData[0x10] + (compressedData[0x11] << 8) && resultLength != 0) + return 0; + curIndex = 0x12; + } else if (compressedData[0] == 'A' + && compressedData[1] == 'T' + && compressedData[2] == '3' + && compressedData[3] == 'P') { + // Can't get this to match - compiler chooses beq, b pairs instead of bne + // I tried multiple if (... != 'x') return 0; + // I tried != chained with || + // I tried == chained with && + // I tried nested if (... == 'x') + // None of that produced matching code. + curIndex = 0x10; + } else { + return 0; + } + + if (compressedData[5] == 'N') { + // uncompressed mode, unused + int i; + for (i = 0; i < compressedLength; i++) + result[i] = compressedData[i + 7]; + return i; + } + + flags1 = compressedData[0x7] + 3; + flags2 = compressedData[0x8] + 3; + flags3 = compressedData[0x9] + 3; + flags4 = compressedData[0xa] + 3; + flags5 = compressedData[0xb] + 3; + flags6 = compressedData[0xc] + 3; + flags7 = compressedData[0xd] + 3; + flags8 = compressedData[0xe] + 3; + flags9 = compressedData[0xf] + 3; + + // Some mismatches regarding the signedness of these two conditionals, extremely fragile + if (curIndex < compressedLength) { + while (resultLength == 0 || resultIndex < resultLength) { + if (cmdBit == 8) { + currentByte = compressedData[curIndex++]; + cmdBit = 0; + } + if (currentByte & 0x80) { // some weird reordering happens here, couldn't figure it out + result[resultIndex++] = compressedData[curIndex++]; + goto end_800AE08; + } + p = &compressedData[curIndex]; + command = (*p >> 4) + 3; + if (command == flags1) command = 0x1f; + if (command == flags2) command = 0x1e; + if (command == flags3) command = 0x1d; + if (command == flags4) command = 0x1c; + if (command == flags5) command = 0x1b; + if (command == flags6) command = 0x1a; + if (command == flags7) command = 0x19; + if (command == flags8) command = 0x18; + if (command == flags9) command = 0x17; + + switch (command) { + case 0x1f: + c10 = *p & 0xf; + c10 = c10 | (c10 << 4); + result[resultIndex++] = c10; + result[resultIndex++] = c10; + curIndex++; + // if curIndex is incremented inside each case, the compiler leaves them inside, but if curIndex is moved after the switch + // then it moves the second result assignment (just the 'strb' instruction) after the switch. + // Can't figure out how to make the compiler move only one without the other. + break; + case 0x1e: + v12 = *p & 0xf; + v12 = (v12 + 1) & 0xf; + c10 = v12; + result[resultIndex++] = ((*p & 0xf) << 4) | c10; + result[resultIndex++] = (v12 << 4) | c10; + curIndex++; + break; + case 0x1d: + c11 = *p & 0xf; + c10 = c11 << 4; + result[resultIndex++] = ((c11 - 1) & 0xf) | c10; + result[resultIndex++] = c10 | c11; + curIndex++; + break; + case 0x1c: + v12 = *p & 0xf; + c10 = v12; + result[resultIndex++] = (v12 << 4) | c10; + result[resultIndex++] = ((v12 & 0xf) << 4) | c10; + v12--; + curIndex++; + break; + case 0x1b: + c10 = *p; + c11 = c10 & 0xf; + c13 = c11 << 4; + result[resultIndex++] = c13 | c11; + c10 = (c10 & 0xf) - 1; + result[resultIndex++] = c13 | (c10 & 0xf); + curIndex++; + break; + case 0x1a: + v12 = ((*p & 0xf) - 1) & 0xf; + c10 = v12; + result[resultIndex++] = ((*p & 0xf) << 4) | c10; + result[resultIndex++] = (v12 << 4) | c10; + curIndex++; + break; + case 0x19: + c11 = *p & 0xf; + c10 = c11 << 4; + result[resultIndex++] = ((c11 + 1) & 0xf) | c10; + result[resultIndex++] = c10 | c11; + curIndex++; + break; + case 0x18: + v12 = *p & 0xf; + c10 = v12; + result[resultIndex++] = (v12 << 4) | c10; + v12++; + curIndex++; + result[resultIndex++] = ((v12 & 0xf) << 4) | c10; + break; + case 0x17: + c10 = *p; + c11 = c10 & 0xf; + c13 = c11 << 4; + result[resultIndex++] = c11 | c13; + c10 = (c10 & 0xf) + 1; + result[resultIndex++] = c13 | (c10 & 0xf); + curIndex++; + break; + default: + v16 = curIndex + 1; + curIndex += 2; + v16 = ((*p & 0xf) << 8) + compressedData[v16] + (-0x1000) + resultIndex; + while (command) { + result[resultIndex++] = result[v16++]; + command--; + } + break; + } +end_800AE08: + cmdBit++; + currentByte <<= 1; + if (curIndex > compressedLength) + return resultIndex; + } + } + + return 0; +#else + asm_unified( + "DecompressAT:\n" + " push {r4-r7,lr}\n" + " mov r7, r10\n" + " mov r6, r9\n" + " mov r5, r8\n" + " push {r5-r7}\n" + " sub sp, 0x2C\n" + " mov r12, r0\n" + " str r1, [sp, 0x24]\n" + " mov r8, r2\n" + " ldrb r0, [r2, 0x5]\n" + " ldrb r1, [r2, 0x6]\n" + " lsls r1, 8\n" + " adds r0, r1\n" + " str r0, [sp, 0x28]\n" + " movs r6, 0\n" + " mov r10, r6\n" + " movs r0, 0x8\n" + " mov r9, r0\n" + " ldrb r0, [r2]\n" + " cmp r0, 0x41\n" + " bne _0800AB04\n" + " ldrb r0, [r2, 0x1]\n" + " adds r1, r0, 0\n" + " cmp r1, 0x54\n" + " bne _0800AB0C\n" + " ldrb r0, [r2, 0x2]\n" + " cmp r0, 0x34\n" + " bne _0800AB0C\n" + " ldrb r0, [r2, 0x3]\n" + " cmp r0, 0x50\n" + " bne _0800AB0C\n" + " ldrb r1, [r2, 0x10]\n" + " ldrb r0, [r2, 0x11]\n" + " lsls r0, 8\n" + " adds r1, r0\n" + " ldr r2, [sp, 0x24]\n" + " cmp r2, 0\n" + " beq _0800AB08\n" + " cmp r2, r1\n" + " beq _0800AB08\n" + "_0800AB04:\n" + " movs r0, 0\n" + " b _0800AE16\n" + "_0800AB08:\n" + " movs r1, 0x12\n" + " b _0800AB26\n" + "_0800AB0C:\n" + " mov r3, r8\n" + " ldrb r0, [r3]\n" + " cmp r0, 0x41\n" + " bne _0800AB04\n" + " cmp r1, 0x54\n" + " bne _0800AB04\n" + " ldrb r0, [r3, 0x2]\n" + " cmp r0, 0x33\n" + " bne _0800AB04\n" + " ldrb r0, [r3, 0x3]\n" + " cmp r0, 0x50\n" + " bne _0800AB04\n" + " movs r1, 0x10\n" + "_0800AB26:\n" + " mov r2, r8\n" + " ldrb r0, [r2, 0x4]\n" + " cmp r0, 0x4E\n" + " bne _0800AB4A\n" + " movs r7, 0\n" + " b _0800AB40\n" + "_0800AB32:\n" + " mov r1, r12\n" + " adds r0, r1, r7\n" + " mov r2, r8\n" + " adds r1, r7, r2\n" + " ldrb r1, [r1, 0x7]\n" + " strb r1, [r0]\n" + " adds r7, 0x1\n" + "_0800AB40:\n" + " ldr r3, [sp, 0x28]\n" + " cmp r7, r3\n" + " blt _0800AB32\n" + " adds r0, r7, 0\n" + " b _0800AE16\n" + "_0800AB4A:\n" + " mov r2, r8\n" + " ldrb r0, [r2, 0x7]\n" + " adds r0, 0x3\n" + " str r0, [sp]\n" + " ldrb r0, [r2, 0x8]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x4]\n" + " ldrb r0, [r2, 0x9]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x8]\n" + " ldrb r0, [r2, 0xA]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0xC]\n" + " ldrb r0, [r2, 0xB]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x10]\n" + " ldrb r0, [r2, 0xC]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x14]\n" + " ldrb r0, [r2, 0xD]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x18]\n" + " ldrb r0, [r2, 0xE]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x1C]\n" + " ldrb r0, [r2, 0xF]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x20]\n" + " adds r7, r1, 0\n" + " ldr r3, [sp, 0x28]\n" + " cmp r7, r3\n" + " blt _0800AB8C\n" + " b _0800AE14\n" + "_0800AB8C:\n" + " ldr r0, [sp, 0x24]\n" + " cmp r0, 0\n" + " beq _0800AB96\n" + " cmp r6, r0\n" + " bge _0800AB04\n" + "_0800AB96:\n" + " mov r1, r9\n" + " cmp r1, 0x8\n" + " bne _0800ABAA\n" + " mov r2, r8\n" + " adds r0, r2, r7\n" + " ldrb r0, [r0]\n" + " mov r10, r0\n" + " adds r7, 0x1\n" + " movs r3, 0\n" + " mov r9, r3\n" + "_0800ABAA:\n" + " movs r0, 0x80\n" + " mov r1, r10\n" + " ands r0, r1\n" + " cmp r0, 0\n" + " beq _0800ABB6\n" + " b _0800ADF0\n" + "_0800ABB6:\n" + " mov r3, r8\n" + " adds r2, r3, r7\n" + " ldrb r1, [r2]\n" + " lsrs r0, r1, 4\n" + " adds r3, r0, 0x3\n" + " movs r0, 0xF\n" + " ands r0, r1\n" + " lsls r5, r0, 8\n" + " ldr r0, [sp]\n" + " cmp r3, r0\n" + " bne _0800ABCE\n" + " movs r3, 0x1F\n" + "_0800ABCE:\n" + " ldr r0, [sp, 0x4]\n" + " cmp r3, r0\n" + " bne _0800ABD6\n" + " movs r3, 0x1E\n" + "_0800ABD6:\n" + " ldr r0, [sp, 0x8]\n" + " cmp r3, r0\n" + " bne _0800ABDE\n" + " movs r3, 0x1D\n" + "_0800ABDE:\n" + " ldr r0, [sp, 0xC]\n" + " cmp r3, r0\n" + " bne _0800ABE6\n" + " movs r3, 0x1C\n" + "_0800ABE6:\n" + " ldr r0, [sp, 0x10]\n" + " cmp r3, r0\n" + " bne _0800ABEE\n" + " movs r3, 0x1B\n" + "_0800ABEE:\n" + " ldr r0, [sp, 0x14]\n" + " cmp r3, r0\n" + " bne _0800ABF6\n" + " movs r3, 0x1A\n" + "_0800ABF6:\n" + " ldr r0, [sp, 0x18]\n" + " cmp r3, r0\n" + " bne _0800ABFE\n" + " movs r3, 0x19\n" + "_0800ABFE:\n" + " ldr r0, [sp, 0x1C]\n" + " cmp r3, r0\n" + " bne _0800AC06\n" + " movs r3, 0x18\n" + "_0800AC06:\n" + " ldr r0, [sp, 0x20]\n" + " cmp r3, r0\n" + " bne _0800AC0E\n" + " movs r3, 0x17\n" + "_0800AC0E:\n" + " adds r0, r3, 0\n" + " subs r0, 0x17\n" + " cmp r0, 0x8\n" + " bls _0800AC18\n" + " b _0800ADB0\n" + "_0800AC18:\n" + " lsls r0, 2\n" + " ldr r1, _0800AC24\n" + " adds r0, r1\n" + " ldr r0, [r0]\n" + " mov pc, r0\n" + " .align 2, 0\n" + "_0800AC24: .4byte _0800AC28\n" + " .align 2, 0\n" + "_0800AC28:\n" + " .4byte _0800AD7C\n" + " .4byte _0800AD48\n" + " .4byte _0800AD20\n" + " .4byte _0800ACFA\n" + " .4byte _0800ACD6\n" + " .4byte _0800ACB4\n" + " .4byte _0800AC8C\n" + " .4byte _0800AC66\n" + " .4byte _0800AC4C\n" + "_0800AC4C:\n" + " ldrb r1, [r2]\n" + " movs r0, 0xF\n" + " adds r7, 0x1\n" + " mov r3, r12\n" + " adds r2, r3, r6\n" + " ands r0, r1\n" + " lsls r1, r0, 4\n" + " orrs r1, r0\n" + " strb r1, [r2]\n" + " adds r6, 0x1\n" + " adds r0, r3, r6\n" + " strb r1, [r0]\n" + " b _0800ADA4\n" + "_0800AC66:\n" + " ldrb r0, [r2]\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r1, r12\n" + " adds r3, r1, r6\n" + " movs r2, 0xF\n" + " lsls r0, r5, 4\n" + " adds r1, r5, 0x1\n" + " ands r1, r2\n" + " orrs r0, r1\n" + " strb r0, [r3]\n" + " adds r6, 0x1\n" + " mov r3, r12\n" + " adds r2, r3, r6\n" + " lsls r0, r1, 4\n" + " orrs r0, r1\n" + " strb r0, [r2]\n" + " b _0800ADA4\n" + "_0800AC8C:\n" + " ldrb r0, [r2]\n" + " movs r3, 0xF\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r1, r12\n" + " adds r4, r1, r6\n" + " adds r2, r5, 0\n" + " ands r2, r3\n" + " lsls r1, r2, 4\n" + " subs r0, r5, 0x1\n" + " ands r0, r3\n" + " orrs r0, r1\n" + " strb r0, [r4]\n" + " adds r6, 0x1\n" + " mov r3, r12\n" + " adds r0, r3, r6\n" + " orrs r1, r2\n" + " strb r1, [r0]\n" + " b _0800ADA4\n" + "_0800ACB4:\n" + " ldrb r0, [r2]\n" + " movs r3, 0xF\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r1, r12\n" + " adds r2, r1, r6\n" + " adds r1, r5, 0\n" + " ands r1, r3\n" + " lsls r0, r1, 4\n" + " orrs r0, r1\n" + " strb r0, [r2]\n" + " adds r6, 0x1\n" + " mov r0, r12\n" + " adds r2, r0, r6\n" + " subs r0, r5, 0x1\n" + " b _0800AD68\n" + "_0800ACD6:\n" + " ldrb r0, [r2]\n" + " movs r4, 0xF\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r2, r12\n" + " adds r3, r2, r6\n" + " adds r1, r5, 0\n" + " ands r1, r4\n" + " lsls r2, r1, 4\n" + " adds r0, r2, 0\n" + " orrs r0, r1\n" + " strb r0, [r3]\n" + " adds r6, 0x1\n" + " mov r3, r12\n" + " adds r1, r3, r6\n" + " subs r0, r5, 0x1\n" + " b _0800AD9E\n" + "_0800ACFA:\n" + " ldrb r0, [r2]\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r1, r12\n" + " adds r3, r1, r6\n" + " movs r2, 0xF\n" + " lsls r0, r5, 4\n" + " subs r1, r5, 0x1\n" + " ands r1, r2\n" + " orrs r0, r1\n" + " strb r0, [r3]\n" + " adds r6, 0x1\n" + " mov r3, r12\n" + " adds r2, r3, r6\n" + " lsls r0, r1, 4\n" + " orrs r0, r1\n" + " strb r0, [r2]\n" + " b _0800ADA4\n" + "_0800AD20:\n" + " ldrb r0, [r2]\n" + " movs r3, 0xF\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r1, r12\n" + " adds r4, r1, r6\n" + " adds r2, r5, 0\n" + " ands r2, r3\n" + " lsls r1, r2, 4\n" + " adds r0, r5, 0x1\n" + " ands r0, r3\n" + " orrs r0, r1\n" + " strb r0, [r4]\n" + " adds r6, 0x1\n" + " mov r3, r12\n" + " adds r0, r3, r6\n" + " orrs r1, r2\n" + " strb r1, [r0]\n" + " b _0800ADA4\n" + "_0800AD48:\n" + " ldrb r0, [r2]\n" + " movs r3, 0xF\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r1, r12\n" + " adds r2, r1, r6\n" + " adds r1, r5, 0\n" + " ands r1, r3\n" + " lsls r0, r1, 4\n" + " orrs r0, r1\n" + " strb r0, [r2]\n" + " adds r6, 0x1\n" + " mov r0, r12\n" + " adds r2, r0, r6\n" + " adds r0, r5, 0x1\n" + "_0800AD68:\n" + " ands r0, r3\n" + " lsls r0, 4\n" + " orrs r0, r1\n" + " strb r0, [r2]\n" + " adds r6, 0x1\n" + " mov r4, r9\n" + " adds r4, 0x1\n" + " mov r1, r10\n" + " lsls r2, r1, 1\n" + " b _0800AE08\n" + "_0800AD7C:\n" + " ldrb r0, [r2]\n" + " movs r4, 0xF\n" + " movs r5, 0xF\n" + " ands r5, r0\n" + " adds r7, 0x1\n" + " mov r2, r12\n" + " adds r3, r2, r6\n" + " adds r1, r5, 0\n" + " ands r1, r4\n" + " lsls r2, r1, 4\n" + " adds r0, r2, 0\n" + " orrs r0, r1\n" + " strb r0, [r3]\n" + " adds r6, 0x1\n" + " mov r3, r12\n" + " adds r1, r3, r6\n" + " adds r0, r5, 0x1\n" + "_0800AD9E:\n" + " ands r0, r4\n" + " orrs r2, r0\n" + " strb r2, [r1]\n" + "_0800ADA4:\n" + " adds r6, 0x1\n" + " mov r4, r9\n" + " adds r4, 0x1\n" + " mov r0, r10\n" + " lsls r2, r0, 1\n" + " b _0800AE08\n" + "_0800ADB0:\n" + " adds r7, 0x1\n" + " mov r1, r8\n" + " adds r0, r1, r7\n" + " ldrb r0, [r0]\n" + " adds r5, r0\n" + " adds r7, 0x1\n" + " ldr r2, _0800ADEC\n" + " adds r0, r5, r2\n" + " adds r5, r0, r6\n" + " mov r4, r9\n" + " adds r4, 0x1\n" + " mov r0, r10\n" + " lsls r2, r0, 1\n" + " cmp r3, 0\n" + " beq _0800AE08\n" + "_0800ADCE:\n" + " mov r1, r12\n" + " adds r1, r6\n" + " mov r10, r1\n" + " mov r0, r12\n" + " adds r0, r5\n" + " ldrb r1, [r0]\n" + " mov r0, r10\n" + " strb r1, [r0]\n" + " adds r6, 0x1\n" + " adds r5, 0x1\n" + " subs r3, 0x1\n" + " cmp r3, 0\n" + " bne _0800ADCE\n" + " b _0800AE08\n" + " .align 2, 0\n" + "_0800ADEC: .4byte 0xfffff000\n" + "_0800ADF0:\n" + " mov r1, r12\n" + " adds r0, r1, r6\n" + " mov r2, r8\n" + " adds r1, r2, r7\n" + " ldrb r1, [r1]\n" + " strb r1, [r0]\n" + " adds r6, 0x1\n" + " adds r7, 0x1\n" + " mov r4, r9\n" + " adds r4, 0x1\n" + " mov r3, r10\n" + " lsls r2, r3, 1\n" + "_0800AE08:\n" + " mov r9, r4\n" + " mov r10, r2\n" + " ldr r0, [sp, 0x28]\n" + " cmp r7, r0\n" + " bge _0800AE14\n" + " b _0800AB8C\n" + "_0800AE14:\n" + " adds r0, r6, 0\n" + "_0800AE16:\n" + " add sp, 0x2C\n" + " pop {r3-r5}\n" + " mov r8, r3\n" + " mov r9, r4\n" + " mov r10, r5\n" + " pop {r4-r7}\n" + " pop {r1}\n" + " bx r1"); +#endif +} + +u32 DecompressATGlobalFile(u32 *result, u32 resultLength, struct OpenedFile *file) +{ + return DecompressATGlobal(result, resultLength, file->data); +} + +// 800AE34 +#ifndef NONMATCHING +NAKED +#endif +u32 DecompressATGlobal(u32 *result, u32 resultLength, const char *compressedData) { - return sub_800AAB4(r0, r1, r2->unk4); +#ifdef NONMATCHING + + // This function has the same issues as above, except is possibly a bit nicer due to the function calls + // I'd say this one is more likely to be at least correct + + int flags1; + int flags2; + int flags3; + int flags4; + int flags5; + int flags6; + int flags7; + int flags8; + int flags9; + int compressedLength; + u32 c10; + char c11; + u32 curIndex; + const char *p; + int command; + int bytesWritten; + int v16; + int cmdBit; + int currentByte; + + compressedLength = compressedData[5] + (compressedData[6] << 8); + bytesWritten = 0; + currentByte = 0; + cmdBit = 8; + + DecompressAT_Init(result); + + if (compressedData[0] == 'A' + && compressedData[1] == 'T' + && compressedData[2] == '4' + && compressedData[3] == 'P') { + if (resultLength != compressedData[0x10] + (compressedData[0x11] << 8) && resultLength != 0) + return 0; + curIndex = 0x12; + } else if (compressedData[0] == 'A' + && compressedData[1] == 'T' + && compressedData[2] == '3' + && compressedData[3] == 'P') { + curIndex = 0x10; + } else { + return 0; + } + + if (compressedData[5] == 'N') { + // uncompressed mode, unused + int i; + for (i = 0; i < compressedLength; i++) + DecompressAT_AppendByte(compressedData[i + 7]); + DecompressAT_Finish(); + return i; + } + + flags1 = compressedData[0x7] + 3; + flags2 = compressedData[0x8] + 3; + flags3 = compressedData[0x9] + 3; + flags4 = compressedData[0xa] + 3; + flags5 = compressedData[0xb] + 3; + flags6 = compressedData[0xc] + 3; + flags7 = compressedData[0xd] + 3; + flags8 = compressedData[0xe] + 3; + flags9 = compressedData[0xf] + 3; + + // Some mismatches regarding the signedness of these two conditionals, extremely fragile + if (curIndex < compressedLength) { + while (resultLength == 0 || bytesWritten < resultLength) { + if (cmdBit == 8) { + currentByte = compressedData[curIndex++]; + cmdBit = 0; + } + if (currentByte & 0x80) { // some weird reordering happens here, couldn't figure it out + DecompressAT_AppendByte(compressedData[curIndex++]); + goto end_800B198; + } + p = &compressedData[curIndex]; + command = (*p >> 4) + 3; + if (command == flags1) command = 0x1f; + if (command == flags2) command = 0x1e; + if (command == flags3) command = 0x1d; + if (command == flags4) command = 0x1c; + if (command == flags5) command = 0x1b; + if (command == flags6) command = 0x1a; + if (command == flags7) command = 0x19; + if (command == flags8) command = 0x18; + if (command == flags9) command = 0x17; + + switch (command) { + case 0x1f: + c10 = *p & 0xf; + c10 = c10 | (c10 << 4); + DecompressAT_AppendByte(c10); + break; + case 0x1e: + c10 = ((*p & 0xf) + 1) & 0xf; + DecompressAT_AppendByte(((*p & 0xf) << 4) | c10); + c10 |= c10 << 4; + break; + case 0x1d: + c10 = *p & 0xf; + DecompressAT_AppendByte(((c10 - 1) & 0xf) | (c10 << 4)); + c10 |= c10 << 4; + break; + case 0x1c: + c10 = *p & 0xf; + DecompressAT_AppendByte((c10 << 4) | c10); + c10 |= ((c10 - 1) & 0xf) << 4; + break; + case 0x1b: + c11 = *p & 0xf; + c10 = c11 << 4; + DecompressAT_AppendByte(c10 | c11); + c11--; + c10 |= c11 & 0xf; + break; + case 0x1a: + c10 = ((*p & 0xf) - 1) & 0xf; + DecompressAT_AppendByte(((*p & 0xf) << 4) | c10); + c10 |= c10 << 4; + break; + case 0x19: + c10 = *p & 0xf; + DecompressAT_AppendByte(((c10 + 1) & 0xf) | (c10 << 4)); + c10 |= c10 << 4; + break; + case 0x18: + c10 = *p & 0xf; + DecompressAT_AppendByte((c10 << 4) | c10); + c10 |= ((c10 + 1) & 0xf) << 4; + break; + case 0x17: + c11 = *p & 0xf; + c10 = c11 << 4; + DecompressAT_AppendByte(c10 | c11); + c11++; + c10 |= c11 & 0xf; + break; + default: + v16 = curIndex + 1; + curIndex += 2; + v16 = ((*p & 0xf) << 8) + compressedData[v16] + (-0x1000) + bytesWritten; + while (command) { + char c = DecompressAT_GetByte(v16); + DecompressAT_AppendByte(c); + bytesWritten++; + v16++; + command--; + } + goto end_800B198; + } + curIndex++; + DecompressAT_AppendByte(c10); + bytesWritten += 2; +end_800B198: + cmdBit++; + currentByte <<= 1; + if (curIndex > compressedLength) + break; + } + DecompressAT_Finish(); + return bytesWritten; + } + + return 0; +#else + asm_unified( + "DecompressATGlobal:\n" + " push {r4-r7,lr}\n" + " mov r7, r10\n" + " mov r6, r9\n" + " mov r5, r8\n" + " push {r5-r7}\n" + " sub sp, 0x34\n" + " str r1, [sp, 0x24]\n" + " mov r10, r2\n" + " ldrb r2, [r2, 0x5]\n" + " mov r3, r10\n" + " ldrb r1, [r3, 0x6]\n" + " lsls r1, 8\n" + " adds r2, r1\n" + " str r2, [sp, 0x28]\n" + " movs r1, 0\n" + " mov r9, r1\n" + " movs r2, 0\n" + " str r2, [sp, 0x2C]\n" + " movs r3, 0x8\n" + " str r3, [sp, 0x30]\n" + " bl DecompressAT_Init\n" + " mov r1, r10\n" + " ldrb r0, [r1]\n" + " cmp r0, 0x41\n" + " bne _0800AE90\n" + " ldrb r0, [r1, 0x1]\n" + " adds r1, r0, 0\n" + " cmp r1, 0x54\n" + " bne _0800AE98\n" + " mov r2, r10\n" + " ldrb r0, [r2, 0x2]\n" + " cmp r0, 0x34\n" + " bne _0800AE98\n" + " ldrb r0, [r2, 0x3]\n" + " cmp r0, 0x50\n" + " bne _0800AE98\n" + " ldrb r1, [r2, 0x10]\n" + " ldrb r0, [r2, 0x11]\n" + " lsls r0, 8\n" + " adds r1, r0\n" + " ldr r3, [sp, 0x24]\n" + " cmp r3, 0\n" + " beq _0800AE94\n" + " cmp r3, r1\n" + " beq _0800AE94\n" + "_0800AE90:\n" + " movs r0, 0\n" + " b _0800B1AA\n" + "_0800AE94:\n" + " movs r1, 0x12\n" + " b _0800AEB2\n" + "_0800AE98:\n" + " mov r2, r10\n" + " ldrb r0, [r2]\n" + " cmp r0, 0x41\n" + " bne _0800AE90\n" + " cmp r1, 0x54\n" + " bne _0800AE90\n" + " ldrb r0, [r2, 0x2]\n" + " cmp r0, 0x33\n" + " bne _0800AE90\n" + " ldrb r0, [r2, 0x3]\n" + " cmp r0, 0x50\n" + " bne _0800AE90\n" + " movs r1, 0x10\n" + "_0800AEB2:\n" + " mov r3, r10\n" + " ldrb r0, [r3, 0x4]\n" + " cmp r0, 0x4E\n" + " bne _0800AEE0\n" + " movs r0, 0\n" + " mov r8, r0\n" + " ldr r1, [sp, 0x28]\n" + " cmp r8, r1\n" + " bge _0800AED8\n" + "_0800AEC4:\n" + " mov r0, r8\n" + " add r0, r10\n" + " ldrb r0, [r0, 0x7]\n" + " bl DecompressAT_AppendByte\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " ldr r3, [sp, 0x28]\n" + " cmp r8, r3\n" + " blt _0800AEC4\n" + "_0800AED8:\n" + " bl DecompressAT_Finish\n" + " mov r0, r8\n" + " b _0800B1AA\n" + "_0800AEE0:\n" + " mov r2, r10\n" + " ldrb r0, [r2, 0x7]\n" + " adds r0, 0x3\n" + " str r0, [sp]\n" + " ldrb r0, [r2, 0x8]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x4]\n" + " ldrb r0, [r2, 0x9]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x8]\n" + " ldrb r0, [r2, 0xA]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0xC]\n" + " ldrb r0, [r2, 0xB]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x10]\n" + " ldrb r0, [r2, 0xC]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x14]\n" + " ldrb r0, [r2, 0xD]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x18]\n" + " ldrb r0, [r2, 0xE]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x1C]\n" + " ldrb r0, [r2, 0xF]\n" + " adds r0, 0x3\n" + " str r0, [sp, 0x20]\n" + " mov r8, r1\n" + " ldr r3, [sp, 0x28]\n" + " cmp r8, r3\n" + " blt _0800AF22\n" + " b _0800B1A4\n" + "_0800AF22:\n" + " ldr r0, [sp, 0x24]\n" + " cmp r0, 0\n" + " beq _0800AF2C\n" + " cmp r9, r0\n" + " bge _0800AE90\n" + "_0800AF2C:\n" + " ldr r1, [sp, 0x30]\n" + " cmp r1, 0x8\n" + " bne _0800AF42\n" + " mov r0, r10\n" + " add r0, r8\n" + " ldrb r0, [r0]\n" + " str r0, [sp, 0x2C]\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " movs r3, 0\n" + " str r3, [sp, 0x30]\n" + "_0800AF42:\n" + " movs r0, 0x80\n" + " ldr r1, [sp, 0x2C]\n" + " ands r0, r1\n" + " cmp r0, 0\n" + " beq _0800AF4E\n" + " b _0800B180\n" + "_0800AF4E:\n" + " mov r2, r10\n" + " add r2, r8\n" + " ldrb r1, [r2]\n" + " lsrs r0, r1, 4\n" + " adds r3, r0, 0x3\n" + " movs r0, 0xF\n" + " ands r0, r1\n" + " lsls r7, r0, 8\n" + " ldr r0, [sp]\n" + " cmp r3, r0\n" + " bne _0800AF66\n" + " movs r3, 0x1F\n" + "_0800AF66:\n" + " ldr r0, [sp, 0x4]\n" + " cmp r3, r0\n" + " bne _0800AF6E\n" + " movs r3, 0x1E\n" + "_0800AF6E:\n" + " ldr r0, [sp, 0x8]\n" + " cmp r3, r0\n" + " bne _0800AF76\n" + " movs r3, 0x1D\n" + "_0800AF76:\n" + " ldr r0, [sp, 0xC]\n" + " cmp r3, r0\n" + " bne _0800AF7E\n" + " movs r3, 0x1C\n" + "_0800AF7E:\n" + " ldr r0, [sp, 0x10]\n" + " cmp r3, r0\n" + " bne _0800AF86\n" + " movs r3, 0x1B\n" + "_0800AF86:\n" + " ldr r0, [sp, 0x14]\n" + " cmp r3, r0\n" + " bne _0800AF8E\n" + " movs r3, 0x1A\n" + "_0800AF8E:\n" + " ldr r0, [sp, 0x18]\n" + " cmp r3, r0\n" + " bne _0800AF96\n" + " movs r3, 0x19\n" + "_0800AF96:\n" + " ldr r0, [sp, 0x1C]\n" + " cmp r3, r0\n" + " bne _0800AF9E\n" + " movs r3, 0x18\n" + "_0800AF9E:\n" + " ldr r0, [sp, 0x20]\n" + " cmp r3, r0\n" + " bne _0800AFA6\n" + " movs r3, 0x17\n" + "_0800AFA6:\n" + " adds r0, r3, 0\n" + " subs r0, 0x17\n" + " cmp r0, 0x8\n" + " bls _0800AFB0\n" + " b _0800B13C\n" + "_0800AFB0:\n" + " lsls r0, 2\n" + " ldr r1, _0800AFBC\n" + " adds r0, r1\n" + " ldr r0, [r0]\n" + " mov pc, r0\n" + " .align 2, 0\n" + "_0800AFBC: .4byte _0800AFC0\n" + " .align 2, 0\n" + "_0800AFC0:\n" + " .4byte _0800B104\n" + " .4byte _0800B0DE\n" + " .4byte _0800B0BA\n" + " .4byte _0800B090\n" + " .4byte _0800B06E\n" + " .4byte _0800B048\n" + " .4byte _0800B024\n" + " .4byte _0800AFFE\n" + " .4byte _0800AFE4\n" + "_0800AFE4:\n" + " ldrb r0, [r2]\n" + " movs r1, 0xF\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " ands r1, r0\n" + " lsls r4, r1, 4\n" + " orrs r4, r1\n" + " adds r0, r4, 0\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " b _0800B128\n" + "_0800AFFE:\n" + " ldrb r0, [r2]\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " movs r1, 0xF\n" + " lsls r0, r6, 4\n" + " adds r4, r6, 0x1\n" + " ands r4, r1\n" + " orrs r0, r4\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " lsls r0, r4, 4\n" + " orrs r0, r4\n" + " lsls r0, 24\n" + " lsrs r0, 24\n" + " b _0800B12A\n" + "_0800B024:\n" + " ldrb r0, [r2]\n" + " movs r1, 0xF\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " adds r5, r6, 0\n" + " ands r5, r1\n" + " lsls r4, r5, 4\n" + " subs r0, r6, 0x1\n" + " ands r0, r1\n" + " orrs r0, r4\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " orrs r4, r5\n" + " b _0800B128\n" + "_0800B048:\n" + " ldrb r0, [r2]\n" + " movs r5, 0xF\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " adds r4, r6, 0\n" + " ands r4, r5\n" + " lsls r0, r4, 4\n" + " orrs r0, r4\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " subs r0, r6, 0x1\n" + " ands r0, r5\n" + " lsls r0, 4\n" + " orrs r0, r4\n" + " b _0800B12A\n" + "_0800B06E:\n" + " ldrb r0, [r2]\n" + " movs r5, 0xF\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " adds r1, r6, 0\n" + " ands r1, r5\n" + " lsls r4, r1, 4\n" + " adds r0, r4, 0\n" + " orrs r0, r1\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " subs r0, r6, 0x1\n" + " b _0800B124\n" + "_0800B090:\n" + " ldrb r0, [r2]\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " movs r1, 0xF\n" + " lsls r0, r6, 4\n" + " subs r4, r6, 0x1\n" + " ands r4, r1\n" + " orrs r0, r4\n" + " lsls r0, 24\n" + " lsrs r0, 24\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " lsls r0, r4, 4\n" + " orrs r0, r4\n" + " lsls r0, 24\n" + " lsrs r0, 24\n" + " b _0800B12A\n" + "_0800B0BA:\n" + " ldrb r0, [r2]\n" + " movs r1, 0xF\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " adds r5, r6, 0\n" + " ands r5, r1\n" + " lsls r4, r5, 4\n" + " adds r0, r6, 0x1\n" + " ands r0, r1\n" + " orrs r0, r4\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " orrs r4, r5\n" + " b _0800B128\n" + "_0800B0DE:\n" + " ldrb r0, [r2]\n" + " movs r5, 0xF\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " adds r4, r6, 0\n" + " ands r4, r5\n" + " lsls r0, r4, 4\n" + " orrs r0, r4\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " adds r0, r6, 0x1\n" + " ands r0, r5\n" + " lsls r0, 4\n" + " orrs r0, r4\n" + " b _0800B12A\n" + "_0800B104:\n" + " ldrb r0, [r2]\n" + " movs r5, 0xF\n" + " movs r6, 0xF\n" + " ands r6, r0\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " adds r1, r6, 0\n" + " ands r1, r5\n" + " lsls r4, r1, 4\n" + " adds r0, r4, 0\n" + " orrs r0, r1\n" + " bl DecompressAT_AppendByte\n" + " movs r3, 0x1\n" + " add r9, r3\n" + " adds r0, r6, 0x1\n" + "_0800B124:\n" + " ands r0, r5\n" + " orrs r4, r0\n" + "_0800B128:\n" + " adds r0, r4, 0\n" + "_0800B12A:\n" + " bl DecompressAT_AppendByte\n" + " movs r0, 0x1\n" + " add r9, r0\n" + " ldr r5, [sp, 0x30]\n" + " adds r5, 0x1\n" + " ldr r1, [sp, 0x2C]\n" + " lsls r4, r1, 1\n" + " b _0800B198\n" + "_0800B13C:\n" + " movs r2, 0x1\n" + " add r8, r2\n" + " mov r0, r10\n" + " add r0, r8\n" + " ldrb r0, [r0]\n" + " adds r7, r0\n" + " add r8, r2\n" + " ldr r1, _0800B17C\n" + " adds r0, r7, r1\n" + " mov r2, r9\n" + " adds r7, r0, r2\n" + " ldr r5, [sp, 0x30]\n" + " adds r5, 0x1\n" + " ldr r0, [sp, 0x2C]\n" + " lsls r4, r0, 1\n" + " cmp r3, 0\n" + " beq _0800B198\n" + " adds r6, r3, 0\n" + "_0800B160:\n" + " adds r0, r7, 0\n" + " bl DecompressAT_GetByte\n" + " lsls r0, 24\n" + " lsrs r0, 24\n" + " bl DecompressAT_AppendByte\n" + " movs r1, 0x1\n" + " add r9, r1\n" + " adds r7, 0x1\n" + " subs r6, 0x1\n" + " cmp r6, 0\n" + " bne _0800B160\n" + " b _0800B198\n" + " .align 2, 0\n" + "_0800B17C: .4byte 0xfffff000\n" + "_0800B180:\n" + " mov r0, r10\n" + " add r0, r8\n" + " ldrb r0, [r0]\n" + " bl DecompressAT_AppendByte\n" + " movs r2, 0x1\n" + " add r9, r2\n" + " add r8, r2\n" + " ldr r5, [sp, 0x30]\n" + " adds r5, 0x1\n" + " ldr r3, [sp, 0x2C]\n" + " lsls r4, r3, 1\n" + "_0800B198:\n" + " str r5, [sp, 0x30]\n" + " str r4, [sp, 0x2C]\n" + " ldr r0, [sp, 0x28]\n" + " cmp r8, r0\n" + " bge _0800B1A4\n" + " b _0800AF22\n" + "_0800B1A4:\n" + " bl DecompressAT_Finish\n" + " mov r0, r9\n" + "_0800B1AA:\n" + " add sp, 0x34\n" + " pop {r3-r5}\n" + " mov r8, r3\n" + " mov r9, r4\n" + " mov r10, r5\n" + " pop {r4-r7}\n" + " pop {r1}\n" + " bx r1"); +#endif +} + +// 800B1BC +void DecompressAT_Init(u32 *buffer) { + gDecompressBufferPtr = buffer; + gDecompressBufferStart = buffer; + gDecompressBufferCurrent = 0; + gDecompressBufferByteInInt = 0; +} + +// 800B1E0 +#ifndef NONMATCHING +NAKED +#endif +char DecompressAT_GetByte(int index) { +#ifdef NONMATCHING + char result; + u32 data; + int offset; + + offset = index < 0 ? index + 3 : index; + + data = gDecompressBufferStart[offset >> 2]; + // compiler inserts a ldrb here for some reason? + result = data; + index &= 3; + // Need to reorder these somehow to match + if (index == 1) result = data >> 8; + else if (index == 2) result = data >> 16; + else if (index == 3) return data >> 24; + return result; +#else + asm_unified( + "DecompressAT_GetByte:\n" + " push {lr}\n" + " adds r2, r0, 0\n" + " cmp r2, 0\n" + " bge _0800B1EA\n" + " adds r0, r2, 0x3\n" + "_0800B1EA:\n" + " asrs r0, 2\n" + " ldr r1, _0800B20C\n" + " ldr r1, [r1]\n" + " lsls r0, 2\n" + " adds r0, r1\n" + " ldr r0, [r0]\n" + " movs r1, 0x3\n" + " ands r1, r2\n" + " cmp r1, 0x1\n" + " beq _0800B210\n" + " cmp r1, 0x1\n" + " ble _0800B216\n" + " cmp r1, 0x2\n" + " beq _0800B214\n" + " cmp r1, 0x3\n" + " beq _0800B218\n" + " b _0800B216\n" + " .align 2, 0\n" + "_0800B20C: .4byte gDecompressBufferStart\n" + "_0800B210:\n" + " lsrs r0, 8\n" + " b _0800B216\n" + "_0800B214:\n" + " lsrs r0, 16\n" + "_0800B216:\n" + " lsls r0, 24\n" + "_0800B218:\n" + " lsrs r0, 24\n" + " pop {r1}\n" + " bx r1"); +#endif +} + +// 800B220 +void DecompressAT_AppendByte(char value) { + gDecompressBufferCurrent |= value << gByteShiftLookup[gDecompressBufferByteInInt]; + *gDecompressBufferPtr = gDecompressBufferCurrent; + gDecompressBufferByteInInt++; + if (gDecompressBufferByteInInt == 4) { + gDecompressBufferPtr++; + gDecompressBufferCurrent = 0; + gDecompressBufferByteInInt = 0; + } +} + +// 800B270 +void DecompressAT_Finish(void) { + if (gDecompressBufferByteInInt) + *gDecompressBufferPtr = gDecompressBufferCurrent; } -- cgit v1.2.3