diff options
author | Mateusz Naściszewski <matin1111@wp.pl> | 2020-12-20 08:36:38 +0100 |
---|---|---|
committer | Seth Barberee <seth.barberee@gmail.com> | 2020-12-20 13:50:35 -0600 |
commit | b64320b043fe0a774327d7d880e9f16605db54ee (patch) | |
tree | 7cd8dbb78aaca904ddab2f5e71c4bb951ebe189f /src | |
parent | c68dba15358399a62a37c6dc21de0b168b569664 (diff) |
Match DecompressAT function!
The global variant is still unmatched.
Most of the credit for the hard parts of matching this go to MCBoy, AKA Pidgey on Discord.
Diffstat (limited to 'src')
-rw-r--r-- | src/file_system.c | 906 |
1 files changed, 188 insertions, 718 deletions
diff --git a/src/file_system.c b/src/file_system.c index c709b45..4c295fc 100644 --- a/src/file_system.c +++ b/src/file_system.c @@ -20,8 +20,8 @@ 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); +u32 DecompressAT(char *result, s32 resultLength, const char *compressedData); +u32 DecompressATGlobal(u32 *result, s32 resultLength, const char *compressedData); u8 *GetSiroPtr(struct OpenedFile *); void NDS_DecompressRLE(void *); @@ -216,686 +216,169 @@ void nullsub_175(void) { } -u32 DecompressATFile(char *result, u32 resultLength, struct OpenedFile *file) +u32 DecompressATFile(char *result, s32 resultLength, struct OpenedFile *file) { return DecompressAT(result, resultLength, file->data); } // 800AAB4 -#ifndef NONMATCHING -NAKED -#endif -u32 DecompressAT(char *result, u32 resultLength, const char *compressedData) +u32 DecompressAT(char *result, s32 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 bytesWritten; - int v16; - int cmdBit; - int currentByte; - - compressedLength = compressedData[5] + (compressedData[6] << 8); - bytesWritten = 0; - currentByte = 0; - cmdBit = 8; + s32 compressedLength = compressedData[5] + (compressedData[6] << 8); + s32 bytesWritten = 0; + s32 currentByte = 0; + s32 cmdBit = 8; + s32 curIndex; + s32 flags[9]; + s32 idxStart; if (compressedData[0] == 'A' && compressedData[1] == 'T' && compressedData[2] == '4' && compressedData[3] == 'P') { - if (resultLength != compressedData[0x10] + (compressedData[0x11] << 8) && resultLength != 0) + u32 tmp2 = compressedData[0x10] + (compressedData[0x11] << 8); + if (resultLength != 0 && resultLength != tmp2) return 0; - curIndex = 0x12; + idxStart = 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; + idxStart = 0x10; } else { return 0; } if (compressedData[4] == 'N') { // uncompressed mode, unused - int i; - for (i = 0; i < compressedLength; i++) - result[i] = compressedData[i + 7]; - return i; + for (curIndex = 0; curIndex < compressedLength; curIndex++) { + result[curIndex] = compressedData[curIndex + 7]; + } + return curIndex; } - 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 + flags[0] = compressedData[0x7] + 3; + flags[1] = compressedData[0x8] + 3; + flags[2] = compressedData[0x9] + 3; + flags[3] = compressedData[0xa] + 3; + flags[4] = compressedData[0xb] + 3; + flags[5] = compressedData[0xc] + 3; + flags[6] = compressedData[0xd] + 3; + flags[7] = compressedData[0xe] + 3; + flags[8] = compressedData[0xf] + 3; + + curIndex = idxStart; if (curIndex < compressedLength) { - while (resultLength == 0 || bytesWritten < resultLength) { + + do { + if (resultLength != 0 && bytesWritten >= resultLength) + return 0; + if (cmdBit == 8) { currentByte = compressedData[curIndex++]; cmdBit = 0; } - if (currentByte & 0x80) { // some weird reordering happens here, couldn't figure it out - result[bytesWritten++] = 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[bytesWritten++] = c10; - result[bytesWritten++] = 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[bytesWritten++] = ((*p & 0xf) << 4) | c10; - result[bytesWritten++] = (v12 << 4) | c10; - curIndex++; - break; - case 0x1d: - c11 = *p & 0xf; - c10 = c11 << 4; - result[bytesWritten++] = ((c11 - 1) & 0xf) | c10; - result[bytesWritten++] = c10 | c11; - curIndex++; - break; - case 0x1c: - v12 = *p & 0xf; - c10 = v12; - result[bytesWritten++] = (v12 << 4) | c10; - result[bytesWritten++] = ((v12 & 0xf) << 4) | c10; - v12--; - curIndex++; - break; - case 0x1b: - c10 = *p; - c11 = c10 & 0xf; - c13 = c11 << 4; - result[bytesWritten++] = c13 | c11; - c10 = (c10 & 0xf) - 1; - result[bytesWritten++] = c13 | (c10 & 0xf); - curIndex++; - break; - case 0x1a: - v12 = ((*p & 0xf) - 1) & 0xf; - c10 = v12; - result[bytesWritten++] = ((*p & 0xf) << 4) | c10; - result[bytesWritten++] = (v12 << 4) | c10; - curIndex++; - break; - case 0x19: - c11 = *p & 0xf; - c10 = c11 << 4; - result[bytesWritten++] = ((c11 + 1) & 0xf) | c10; - result[bytesWritten++] = c10 | c11; - curIndex++; - break; - case 0x18: - v12 = *p & 0xf; - c10 = v12; - result[bytesWritten++] = (v12 << 4) | c10; - v12++; - curIndex++; - result[bytesWritten++] = ((v12 & 0xf) << 4) | c10; - break; - case 0x17: - c10 = *p; - c11 = c10 & 0xf; - c13 = c11 << 4; - result[bytesWritten++] = c11 | c13; - c10 = (c10 & 0xf) + 1; - result[bytesWritten++] = c13 | (c10 & 0xf); - curIndex++; - break; - default: - v16 = curIndex + 1; - curIndex += 2; - v16 = ((*p & 0xf) << 8) + compressedData[v16] + (-0x1000) + bytesWritten; - while (command) { - result[bytesWritten++] = result[v16++]; - command--; + if ((currentByte & 0x80) == 0) { + // if bit is unset, process command + u32 command = (compressedData[curIndex] >> 4) + 3; + u32 tmp = (compressedData[curIndex] & 0xf) << 8; + u32 c; + + if (command == flags[0]) command = 0x1f; + if (command == flags[1]) command = 0x1e; + if (command == flags[2]) command = 0x1d; + if (command == flags[3]) command = 0x1c; + if (command == flags[4]) command = 0x1b; + if (command == flags[5]) command = 0x1a; + if (command == flags[6]) command = 0x19; + if (command == flags[7]) command = 0x18; + if (command == flags[8]) command = 0x17; + + switch (command) { + case 0x1f: { // aaaa + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + break; + } + case 0x1e: { // abbb + u8 byte = compressedData[curIndex]; + c = 0xF; + c = byte & c; + curIndex++; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 1) & 0xf)); + result[bytesWritten++] = ((((c + 1) & 0xf) << 4) | ((c + 1) & 0xf)); + break; + } + case 0x1d: { // babb + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c - 1) & 0xf)); + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + break; + } + case 0x1c: { // bbab + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + result[bytesWritten++] = ((((c - 1) & 0xf) << 4) | ((c + 0) & 0xf)); + break; + } + case 0x1b: { // bbba + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c - 1) & 0xf)); + break; + } + case 0x1a: { // baaa -- the horrible, hard-to-match case + u8 byte = compressedData[curIndex]; + c = 0xF; + c = byte & c; + curIndex++; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c - 1) & 0xf)); + result[bytesWritten++] = ((((c - 1) & 0xf) << 4) | ((c - 1) & 0xf)); + break; + } + case 0x19: { // abaa + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 1) & 0xf)); + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + break; + } + case 0x18: { // aaba + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + result[bytesWritten++] = ((((c + 1) & 0xf) << 4) | ((c + 0) & 0xf)); + break; + } + case 0x17: { // aaab + c = compressedData[curIndex++] & 0xf; + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); + result[bytesWritten++] = ((((c + 0) & 0xf) << 4) | ((c + 1) & 0xf)); + break; + } + default: { + tmp += (compressedData[curIndex++, curIndex++]); + tmp += bytesWritten - 0x1000; + for(;command;command--) + { + result[bytesWritten++] = result[tmp]; + tmp++; + } + } } - break; + } else { + // if bit is set, just copy next byte + result[bytesWritten++] = (compressedData[curIndex]); + curIndex++; } -end_800AE08: cmdBit++; currentByte <<= 1; - if (curIndex > compressedLength) - return bytesWritten; - } + } while (curIndex < compressedLength); } - 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 + return bytesWritten; } -u32 DecompressATGlobalFile(u32 *result, u32 resultLength, struct OpenedFile *file) +u32 DecompressATGlobalFile(u32 *result, s32 resultLength, struct OpenedFile *file) { return DecompressATGlobal(result, resultLength, file->data); } @@ -904,28 +387,27 @@ u32 DecompressATGlobalFile(u32 *result, u32 resultLength, struct OpenedFile *fil #ifndef NONMATCHING NAKED #endif -u32 DecompressATGlobal(u32 *result, u32 resultLength, const char *compressedData) +u32 DecompressATGlobal(u32 *result, s32 resultLength, const char *compressedData) { #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; - int curIndex; - int command; - int bytesWritten; - int cmdBit; - int currentByte; + s32 compressedLength; + s32 curIndex; + s32 bytesWritten; + s32 cmdBit; + s32 currentByte; + s32 flags1; + s32 flags2; + s32 flags3; + s32 flags4; + s32 flags5; + s32 flags6; + s32 flags7; + s32 flags8; + s32 flags9; + u32 command; + u32 tmp; + u32 tmp2; + u32 c; compressedLength = compressedData[5] + (compressedData[6] << 8); bytesWritten = 0; @@ -938,9 +420,9 @@ u32 DecompressATGlobal(u32 *result, u32 resultLength, const char *compressedData && compressedData[1] == 'T' && compressedData[2] == '4' && compressedData[3] == 'P') { - // compiler swaps comparison order somehow - if (resultLength != compressedData[0x10] + (compressedData[0x11] << 8) && resultLength != 0) - return 0; + tmp2 = compressedData[0x10] + (compressedData[0x11] << 8); + if (resultLength != 0 && resultLength != tmp2) + return bytesWritten; curIndex = 0x12; } else if (compressedData[0] == 'A' && compressedData[1] == 'T' @@ -970,24 +452,21 @@ u32 DecompressATGlobal(u32 *result, u32 resultLength, const char *compressedData flags8 = compressedData[0xe] + 3; flags9 = compressedData[0xf] + 3; - // Some mismatches regarding the signedness of these two conditionals, extremely fragile without explicit casts - // TODO: clean this up later - if ((int)curIndex < (int)compressedLength) { - // '<' comparison compiles to wrong branch, but if I add another 'return bytesWritten;' - // after the while loop, the compiler merges it with the earlier uncompressed case which breaks stuff. - if (resultLength == 0 || (int)bytesWritten < (int)resultLength) return 0; + if (curIndex < compressedLength) { + do { + if (resultLength != 0 && bytesWritten >= resultLength) + return 0; + if (cmdBit == 8) { currentByte = compressedData[curIndex++]; cmdBit = 0; } - if (currentByte & 0x80) { // some weird reordering happens here, couldn't figure it out - // do NOT try inverting the above condition and moving this to the bottom - // it really won't end well - DecompressAT_AppendByte(compressedData[curIndex++]); - bytesWritten++; - } else { + if ((currentByte & 0x80) == 0) { + // if bit is unset, process command command = (compressedData[curIndex] >> 4) + 3; + tmp2 = (compressedData[curIndex] & 0xf) << 8; + if (command == flags1) command = 0x1f; if (command == flags2) command = 0x1e; if (command == flags3) command = 0x1d; @@ -999,85 +478,76 @@ u32 DecompressATGlobal(u32 *result, u32 resultLength, const char *compressedData if (command == flags9) command = 0x17; switch (command) { - case 0x1f: { - char c = compressedData[curIndex++] & 0xf; + case 0x1f: { // aaaa + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; break; } - case 0x1e: { - char c = compressedData[curIndex++] & 0xf; + case 0x1e: { // abbb + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 1) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 1) & 0xf) << 4) | ((c + 1) & 0xf)); bytesWritten++; - break; // rather large mismatch + break; } - case 0x1d: { - char c = compressedData[curIndex] & 0xf; - curIndex++; + case 0x1d: { // babb + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c - 1) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; break; } - case 0x1c: { - char c = compressedData[curIndex] & 0xf; - curIndex++; + case 0x1c: { // bbab + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c - 1) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; break; } - case 0x1b: { - char c = compressedData[curIndex] & 0xf; - curIndex++; + case 0x1b: { // bbba + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c - 1) & 0xf)); bytesWritten++; break; } - case 0x1a: { - char c = compressedData[curIndex] & 0xf; - // weird movs/adds here - possibly regalloc - curIndex++; - // missing u8 cast for argument, twice + case 0x1a: { // baaa -- the horrible, unmatching case + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c - 1) & 0xf)); bytesWritten++; - DecompressAT_AppendByte((((c - 1) & 0xf) << 4) | ((c - 1) & 0xf)); bytesWritten++; - break; // second call is inlined! Should end up after switch code - // and yes, I tried extracting (c-1)&0xf into its own variable, and in 0x1e as well - // which had little effect + c -= 1; + DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; + break; } - case 0x19: { - char c = compressedData[curIndex] & 0xf; - curIndex++; + case 0x19: { // abaa + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 1) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; break; } - case 0x18: { - char c = compressedData[curIndex] & 0xf; - curIndex++; + case 0x18: { // aaba + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 1) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; break; } - case 0x17: { - char c = compressedData[curIndex] & 0xf; - curIndex++; + case 0x17: { // aaab + c = compressedData[curIndex++] & 0xf; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 0) & 0xf)); bytesWritten++; DecompressAT_AppendByte((((c + 0) & 0xf) << 4) | ((c + 1) & 0xf)); bytesWritten++; break; } default: { - unsigned tmp = curIndex + 1; - tmp = bytesWritten - 0x1000 + ((compressedData[curIndex++] & 0xf) << 8) + compressedData[tmp]; - curIndex++; + tmp = compressedData[curIndex++, curIndex++] + tmp2 - 0x1000 + bytesWritten; for (; command != 0; tmp++, command--) { - char c = DecompressAT_GetByte(tmp); - DecompressAT_AppendByte(c); bytesWritten++; + DecompressAT_AppendByte(DecompressAT_GetByte(tmp)); bytesWritten++; } } } + } else { + // if bit is set, just copy next byte + DecompressAT_AppendByte(compressedData[curIndex]); bytesWritten++; + curIndex++; } cmdBit++; currentByte <<= 1; - } while ((int)curIndex < (int)compressedLength); + } while (curIndex < compressedLength); DecompressAT_Finish(); } |