From d58a81af829551399d6909bdd697f2d920c5f150 Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 09:15:30 +0200 Subject: [PATCH 1/7] reassemble AtexSubCode1 (AtexSubCode1New) --- SourceFiles/AtexAsm.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/SourceFiles/AtexAsm.cpp b/SourceFiles/AtexAsm.cpp index 8d15c04..cc27e94 100644 --- a/SourceFiles/AtexAsm.cpp +++ b/SourceFiles/AtexAsm.cpp @@ -1,9 +1,12 @@ #include "pch.h" #include "AtexAsm.h" -void AtexSubCode1_(unsigned int a, unsigned int b, unsigned int c); -void AtexSubCode2_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f); +struct SImageData; +void AtexSubCode1_(uint32_t* array1, uint32_t* array2, unsigned int count); +void AtexSubCode1New(uint32_t* array1, uint32_t* array2, unsigned int count); +void AtexSubCode2_(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void AtexSubCode2New(uint32_t* outBuffer, int dcmpBuffer1, int dcmpBuffer2, int imageData, int blockCount, int blockSize); +void AtexSubCode2New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); void AtexSubCode3_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f); void AtexSubCode4_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, @@ -126,7 +129,7 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && (ImageFormat == 0x11 || ImageFormat == 0x10)) { - AtexSubCode1_((unsigned int)DcmpBuffer1, (unsigned int)DcmpBuffer2, BlockCount); + AtexSubCode1New(DcmpBuffer1, DcmpBuffer2, BlockCount); } if (CompressionCode & 1 && ColorDataSize && ! AlphaDataSize && ! AlphaDataSize2) { @@ -206,6 +209,18 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned delete[] (unsigned char*)DcmpBuffer1; } +void AtexSubCode1New(uint32_t* array1, uint32_t* array2, unsigned int count) +{ + for (auto i = 0u; i < count; ++i) { + const uint32_t mask = 1 << (i & 0x1F); + if ((mask & 0xC0000003) != 0 || ((1 << ((i >> 6) & 0x1F)) & 0xC0000003) != 0) { + const uint32_t array_index = i >> 5; // 4 * (i >> 5), but uint32_t* points to 4 bytes + array1[array_index] |= mask; + array2[array_index] |= mask; + } + } +} + void __declspec(naked) AtexSubCode1() { __asm { From 6e9ff4e3f4deeaba78ff0a4b5090081576f96c8c Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 09:18:34 +0200 Subject: [PATCH 2/7] reassemble AtexSubCode2 --- SourceFiles/AtexAsm.cpp | 120 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 7 deletions(-) diff --git a/SourceFiles/AtexAsm.cpp b/SourceFiles/AtexAsm.cpp index cc27e94..962332d 100644 --- a/SourceFiles/AtexAsm.cpp +++ b/SourceFiles/AtexAsm.cpp @@ -5,7 +5,6 @@ struct SImageData; void AtexSubCode1_(uint32_t* array1, uint32_t* array2, unsigned int count); void AtexSubCode1New(uint32_t* array1, uint32_t* array2, unsigned int count); void AtexSubCode2_(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); -void AtexSubCode2New(uint32_t* outBuffer, int dcmpBuffer1, int dcmpBuffer2, int imageData, int blockCount, int blockSize); void AtexSubCode2New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); void AtexSubCode3_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f); @@ -52,7 +51,7 @@ int ImgFmt(unsigned int Format) struct SImageData { - unsigned int *DataPos, *EndPos, _44, _40, _3C, xres, yres; + unsigned int *DataPos, *EndPos, remainingBits, currentBits, nextBits, xres, yres; }; void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned int ImageFormat, @@ -117,12 +116,12 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned if (CompressionCode) { - ImageData._40 = ImageData._44 = ImageData._3C = 0; + ImageData.currentBits = ImageData.remainingBits = ImageData.nextBits = 0; ImageData.EndPos = ImageData.DataPos + ((DataSize - 8) >> 2); if (ImageData.DataPos != ImageData.EndPos) { - ImageData._40 = ImageData.DataPos[0]; + ImageData.currentBits = ImageData.DataPos[0]; ImageData.DataPos++; } @@ -133,8 +132,7 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned } if (CompressionCode & 1 && ColorDataSize && ! AlphaDataSize && ! AlphaDataSize2) { - AtexSubCode2_((unsigned int)OutBuffer, (unsigned int)DcmpBuffer1, (unsigned int)DcmpBuffer2, - (unsigned int)&ImageData, BlockCount, BlockSize); + AtexSubCode2New(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) { @@ -155,7 +153,7 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned ImageData.DataPos--; } - unsigned int* DataEnd = InputBuffer + ((HeaderSize + DataSize) >> 2); + [[maybe_unused]] unsigned int* DataEnd = InputBuffer + ((HeaderSize + DataSize) >> 2); if ((AlphaDataSize || AlphaDataSize2) && BlockCount) { @@ -288,6 +286,114 @@ void AtexSubCode1_(unsigned int a, unsigned int b, unsigned int c) } } +void AtexSubCode2New(uint32_t *outBuffer, uint32_t *dcmpBuffer1, uint32_t *dcmpBuffer2, SImageData *imageData, uint32_t blockCount, uint32_t blockSize) +{ + if (blockCount == 0) { + return; + } + + uint32_t block_index = 0; + int extractedBits; + uint32_t* dataPosition; + uint32_t currentWord; + + while (block_index < blockCount) + { + const auto shiftLeft = imageData->currentBits >> 26; + const auto shiftValue = byte_79053C[2 * shiftLeft]; + int remainingBits = byte_79053D[2 * shiftLeft] + 1; + + if (shiftValue) { + imageData->currentBits = (imageData->currentBits << shiftValue) | (imageData->nextBits >> (32 - shiftValue)); + } + + uint32_t bitCount = imageData->remainingBits; + + if (shiftValue > bitCount) + { + dataPosition = imageData->DataPos; + + if (dataPosition == imageData->EndPos) + { + extractedBits = 0; + imageData->nextBits = 0; + } + else + { + currentWord = *dataPosition; + imageData->DataPos = dataPosition + 1; + imageData->nextBits = currentWord; + imageData->currentBits |= currentWord >> (bitCount - shiftValue + 32); + imageData->nextBits = currentWord << (shiftValue - bitCount); + extractedBits = bitCount - shiftValue + 32; + } + } + else + { + extractedBits = bitCount - shiftValue; + imageData->nextBits <<= shiftValue; + } + + const uint64_t combinedValue = (static_cast(imageData->currentBits) << 32) | imageData->nextBits; + imageData->remainingBits = extractedBits; + imageData->currentBits = static_cast(combinedValue >> 31); + int bitMask = static_cast(combinedValue >> 63); + + if (imageData->remainingBits) + { + imageData->nextBits = static_cast(combinedValue << 1); + imageData->remainingBits -= 1; + } + else + { + dataPosition = imageData->DataPos; + + if (dataPosition == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + const auto curPos = *dataPosition; + imageData->DataPos = dataPosition + 1; + currentWord = curPos; + imageData->currentBits |= currentWord >> 31; + imageData->remainingBits = 31; + imageData->nextBits = 2 * currentWord; + } + } + + while (remainingBits > 0 && block_index < blockCount) + { + const int bitPosition = 1 << (block_index & 0x1F); + const int bufferIndex = block_index >> 5; + + if ((bitPosition & dcmpBuffer2[bufferIndex]) == 0) + { + if (bitMask) + { + outBuffer[0] = static_cast(-2); + outBuffer[1] = static_cast(-1); + dcmpBuffer2[bufferIndex] |= bitPosition; + dcmpBuffer1[bufferIndex] |= bitPosition; + bitMask = static_cast(combinedValue >> 63); + } + remainingBits -= 1; + } + + block_index++; + outBuffer += blockSize; + } + + while (block_index < blockCount && (1 << (block_index & 0x1F) & dcmpBuffer2[block_index >> 5]) != 0) + { + block_index++; + outBuffer += blockSize; + } + } +} + void __declspec(naked) AtexSubCode2() { __asm { From 459f2f441aca2432fa23f44f70082118da21dc7d Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 10:15:26 +0200 Subject: [PATCH 3/7] reassemble AtexSubCode3 --- SourceFiles/AtexAsm.cpp | 188 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 4 deletions(-) diff --git a/SourceFiles/AtexAsm.cpp b/SourceFiles/AtexAsm.cpp index 962332d..0ba529d 100644 --- a/SourceFiles/AtexAsm.cpp +++ b/SourceFiles/AtexAsm.cpp @@ -6,8 +6,8 @@ void AtexSubCode1_(uint32_t* array1, uint32_t* array2, unsigned int count); void AtexSubCode1New(uint32_t* array1, uint32_t* array2, unsigned int count); void AtexSubCode2_(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); void AtexSubCode2New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); -void AtexSubCode3_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f); +void AtexSubCode3_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f); +void AtexSubCode3New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); void AtexSubCode4_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f); void AtexSubCode5_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, @@ -136,8 +136,7 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned } if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) { - AtexSubCode3_((unsigned int)OutBuffer, (unsigned int)DcmpBuffer1, (unsigned int)DcmpBuffer2, - (unsigned int)&ImageData, BlockCount, BlockSize); + AtexSubCode3New(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 4 && ImageFormat >= 0x12 && ImageFormat <= 0x15) { @@ -639,6 +638,187 @@ void AtexSubCode2_(unsigned int a, unsigned int b, unsigned int c, unsigned int } } +void AtexSubCode3New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) +{ + const unsigned int current_bits = imageData->currentBits; + const int currentDataPos = (16 * current_bits) | (imageData->nextBits >> 28); + const unsigned int remainingBits = imageData->remainingBits; + unsigned int tempBits = 0; + int bitDifference; + int bufferArray[4]{}; + int bitCounter; + uint32_t* bufferPos = outBuffer; + + imageData->currentBits = currentDataPos; + + if (remainingBits < 4) + { + unsigned int* dataPtr = imageData->DataPos; + if (imageData->DataPos == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + unsigned int newBits = *dataPtr; + imageData->DataPos = dataPtr + 1; + imageData->nextBits = newBits; + imageData->currentBits = (newBits >> (remainingBits + 28)) | currentDataPos; + imageData->remainingBits = remainingBits + 28; + imageData->nextBits = newBits << (4 - remainingBits); + } + } + else + { + imageData->nextBits *= 16; + imageData->remainingBits = remainingBits - 4; + } + + if (blockCount == 0) + { + return; + } + + while (tempBits != blockCount) + { + int bitShifted = imageData->currentBits >> 26; + int bitShiftedBy = byte_79053D[2 * bitShifted] + 1; + unsigned int bitField = byte_79053C[2 * bitShifted]; + + if (byte_79053C[2 * bitShifted]) + { + imageData->currentBits = (imageData->currentBits << bitField) | (imageData->nextBits >> (32 - bitField)); + } + + int flagBits = imageData->remainingBits; + unsigned int bitMask = flagBits; + + if (bitField > flagBits) + { + if (imageData->DataPos == imageData->EndPos) + { + bitDifference = 0; + imageData->nextBits = 0; + } + else + { + unsigned int dataOffset = *imageData->DataPos++; + imageData->nextBits = dataOffset; + bitCounter = bitMask - bitField + 32; + imageData->currentBits |= dataOffset >> bitCounter; + imageData->nextBits = dataOffset << (bitField - flagBits); + bitDifference = bitCounter; + } + } + else + { + bitDifference = flagBits - bitField; + imageData->nextBits <<= bitField; + } + + imageData->remainingBits = bitDifference; + unsigned int curBits = imageData->currentBits; + imageData->currentBits = (2 * curBits) | (imageData->nextBits >> 31); + flagBits = curBits >> 31; + + if (imageData->remainingBits) + { + imageData->nextBits *= 2; + imageData->remainingBits -= 1; + } + else + { + unsigned int* bufferPtr = imageData->DataPos; + if (imageData->DataPos == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + unsigned int finalShift = *bufferPtr; + imageData->DataPos = bufferPtr + 1; + imageData->nextBits = finalShift; + int bufferOffset = (finalShift >> 31) | imageData->currentBits; + imageData->currentBits = bufferOffset; + imageData->nextBits = 2 * finalShift; + imageData->remainingBits = 31; + } + } + + int bitIndex = flagBits; + bitCounter = flagBits; + + if (flagBits) + { + unsigned int combinedBitsShifted = imageData->currentBits; + imageData->currentBits = (2 * combinedBitsShifted) | (imageData->nextBits >> 31); + const int bitRemainingShift = imageData->remainingBits; + int finalBitShift = combinedBitsShifted >> 31; + + if (bitRemainingShift) + { + imageData->nextBits *= 2; + imageData->remainingBits = bitRemainingShift - 1; + } + else + { + if (imageData->DataPos == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + imageData->nextBits = *imageData->DataPos++; + imageData->currentBits |= imageData->nextBits >> 31; + imageData->nextBits *= 2; + imageData->remainingBits = 31; + } + } + + bitIndex = finalBitShift + flagBits; + bitCounter = finalBitShift + flagBits; + } + + while (bitShiftedBy) + { + while (tempBits != blockCount) + { + const int nextBitOffset = 1 << (tempBits & 0x1F); + const int finalShiftedBits = tempBits >> 5; + + if ((nextBitOffset & dcmpBuffer2[finalShiftedBits]) == 0) + { + if (bitIndex) + { + bufferPos[0] = bufferArray[2 * bitIndex]; + bufferPos[1] = bufferArray[2 * bitCounter + 1]; + dcmpBuffer1[finalShiftedBits] |= nextBitOffset; + bitIndex = bitCounter; + } + bitShiftedBy--; + } + + tempBits++; + bufferPos += blockSize; + + if (!bitShiftedBy) + break; + } + + while (((1 << (tempBits & 0x1F)) & dcmpBuffer2[tempBits >> 5]) != 0) + { + bufferPos += blockSize; + + if (++tempBits == blockCount) + return; + } + } + } +} + void __declspec(naked) AtexSubCode3() { __asm { From b0a20aba2a736fd4e5c1a10dbbc1f59f6fe60307 Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 14:48:28 +0200 Subject: [PATCH 4/7] refactor c++ decompression stuff out of AtexAsm --- .gitignore | 2 + GuildWarsMapBrowser.vcxproj | 2 + SourceFiles/AtexAsm.cpp | 533 +-------------------------------- SourceFiles/AtexAsm.h | 23 +- SourceFiles/AtexDecompress.cpp | 471 +++++++++++++++++++++++++++++ SourceFiles/AtexDecompress.h | 47 +++ SourceFiles/AtexReader.cpp | 2 +- SourceFiles/pch.h | 2 +- 8 files changed, 546 insertions(+), 536 deletions(-) create mode 100644 SourceFiles/AtexDecompress.cpp create mode 100644 SourceFiles/AtexDecompress.h diff --git a/.gitignore b/.gitignore index 92bcf4f..1b1a4e0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +.idea + # User-specific files *.rsuser *.suo diff --git a/GuildWarsMapBrowser.vcxproj b/GuildWarsMapBrowser.vcxproj index d0b2946..5487b08 100644 --- a/GuildWarsMapBrowser.vcxproj +++ b/GuildWarsMapBrowser.vcxproj @@ -214,6 +214,7 @@ + @@ -395,6 +396,7 @@ + diff --git a/SourceFiles/AtexAsm.cpp b/SourceFiles/AtexAsm.cpp index 0ba529d..0924b62 100644 --- a/SourceFiles/AtexAsm.cpp +++ b/SourceFiles/AtexAsm.cpp @@ -1,222 +1,6 @@ -#include "pch.h" +#include "pch.h" #include "AtexAsm.h" - -struct SImageData; -void AtexSubCode1_(uint32_t* array1, uint32_t* array2, unsigned int count); -void AtexSubCode1New(uint32_t* array1, uint32_t* array2, unsigned int count); -void AtexSubCode2_(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); -void AtexSubCode2New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); -void AtexSubCode3_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f); -void AtexSubCode3New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); -void AtexSubCode4_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f); -void AtexSubCode5_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f, unsigned int g); -void AtexSubCode6(); -void AtexSubCode7_(unsigned int a, unsigned int b); - -unsigned int ImageFormats[] = {0x0B2, 0x12, 0x0B2, 0x72, 0x12, 0x12, 0x12, 0x100, - 0x1A4, 0x1A4, 0x1A4, 0x104, 0x0A2, 0x78, 0x400, 0x71, - 0x0B1, 0x0B1, 0x0B1, 0x0B1, 0x0A1, 0x11, 0x201}; - -unsigned char byte_79053C[] = { - 0x6, 0x10, 0x6, 0x0F, 0x6, 0x0E, 0x6, 0x0D, 0x6, 0x0C, 0x6, 0x0B, 0x6, 0x0A, 0x6, 0x9, - 0x6, 0x8, 0x6, 0x7, 0x6, 0x6, 0x6, 0x5, 0x6, 0x4, 0x6, 0x3, 0x6, 0x2, 0x6, 0x1, - 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, - 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, - 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, - 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, - 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, - 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0}; - -unsigned char byte_79053D[] = { - 0x10, 0x6, 0x0F, 0x6, 0x0E, 0x6, 0x0D, 0x6, 0x0C, 0x6, 0x0B, 0x6, 0x0A, 0x6, 0x9, 0x6, - 0x8, 0x6, 0x7, 0x6, 0x6, 0x6, 0x5, 0x6, 0x4, 0x6, 0x3, 0x6, 0x2, 0x6, 0x1, 0x2, - 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, - 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x1, - 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, - 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, - 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, - 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0}; - -int ImgFmt(unsigned int Format) -{ - if (Format >= 0x17) - { - printf("ERROR: bad image format (%d)!", Format); - exit(0); - } - return ImageFormats[Format]; -} - -struct SImageData -{ - unsigned int *DataPos, *EndPos, remainingBits, currentBits, nextBits, xres, yres; -}; - -void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned int ImageFormat, - SImageDescriptor ImageDescriptor, unsigned int* OutBuffer) -{ - unsigned int HeaderSize = 12; - - SImageData ImageData; - - int AlphaDataSize2 = ((ImageFormat && 21) - 1) & 2; - - int ColorDataSize = ImgFmt(ImageFormat); - int AlphaDataSize = ColorDataSize; - - AlphaDataSize &= 640; - if (AlphaDataSize) - { - AlphaDataSize = 2; - } - - ColorDataSize &= 528; - if (ColorDataSize) - { - ColorDataSize = 2; - } - - int BlockSize = ColorDataSize + AlphaDataSize2 + AlphaDataSize; - - int BlockCount = ImageDescriptor.xres * ImageDescriptor.yres / 16; - - if (! BlockCount) - { - printf("BlockCount zero\n"); - return; - } - - unsigned int* DcmpBuffer1 = new unsigned int[BlockCount]; - unsigned int* DcmpBuffer2 = DcmpBuffer1 + BlockCount / 2; - memset(DcmpBuffer1, 0, BlockCount * 4); - - ImageData.xres = ImageDescriptor.xres; - ImageData.yres = ImageDescriptor.yres; - - unsigned int DataSize = InputBuffer[HeaderSize >> 2]; - - if (HeaderSize + 8 >= BufferSize) - { - printf("Error 567h\n"); - } - if (DataSize <= 8) - { - printf("Error 569h\n"); - } - if (DataSize + HeaderSize > BufferSize) - { - printf("Error 56Ah\n"); - } - - int CompressionCode = InputBuffer[(HeaderSize + 4) >> 2]; - - ImageData.DataPos = InputBuffer + ((HeaderSize + 8) >> 2); - - if (CompressionCode) - { - ImageData.currentBits = ImageData.remainingBits = ImageData.nextBits = 0; - ImageData.EndPos = ImageData.DataPos + ((DataSize - 8) >> 2); - - if (ImageData.DataPos != ImageData.EndPos) - { - ImageData.currentBits = ImageData.DataPos[0]; - ImageData.DataPos++; - } - - if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && - (ImageFormat == 0x11 || ImageFormat == 0x10)) - { - AtexSubCode1New(DcmpBuffer1, DcmpBuffer2, BlockCount); - } - if (CompressionCode & 1 && ColorDataSize && ! AlphaDataSize && ! AlphaDataSize2) - { - AtexSubCode2New(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); - } - if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) - { - AtexSubCode3New(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); - } - if (CompressionCode & 4 && ImageFormat >= 0x12 && ImageFormat <= 0x15) - { - AtexSubCode4_((unsigned int)OutBuffer, (unsigned int)DcmpBuffer1, (unsigned int)DcmpBuffer2, - (unsigned int)&ImageData, BlockCount, BlockSize); - } - if (CompressionCode & 8 && ColorDataSize) - { - AtexSubCode5_((unsigned int)OutBuffer + AlphaDataSize2 + AlphaDataSize * 4, - (unsigned int)DcmpBuffer1, (unsigned int)DcmpBuffer2, (unsigned int)&ImageData, - BlockCount, BlockSize, ImageFormat == 0xf); - } - ImageData.DataPos--; - } - - [[maybe_unused]] unsigned int* DataEnd = InputBuffer + ((HeaderSize + DataSize) >> 2); - - if ((AlphaDataSize || AlphaDataSize2) && BlockCount) - { - unsigned int* BufferVar = OutBuffer; - - for (int x = 0; x < BlockCount; x++) - { - if (! (DcmpBuffer1[x >> 5] & 1 << x)) - { - BufferVar[0] = ImageData.DataPos[0]; - BufferVar[1] = ImageData.DataPos[1]; - ImageData.DataPos += 2; - } - BufferVar += BlockSize; - } - } - - if (ColorDataSize && BlockCount) - { - unsigned int* BufferVar = OutBuffer + AlphaDataSize2 + AlphaDataSize; - - for (int x = 0; x < BlockCount; x++) - { - if (! (DcmpBuffer2[x >> 5] & 1 << x)) - { - BufferVar[0] = ImageData.DataPos[0]; - ImageData.DataPos++; - } - BufferVar += BlockSize; - } - - BufferVar = OutBuffer + AlphaDataSize2 + AlphaDataSize + 1; - - for (int x = 0; x < BlockCount; x++) - { - if (! (DcmpBuffer2[x >> 5] & 1 << x)) - { - BufferVar[0] = ImageData.DataPos[0]; - ImageData.DataPos++; - } - BufferVar += BlockSize; - } - } - - if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && - (ImageFormat == 0x10 || ImageFormat == 0x11)) - { - AtexSubCode7_((unsigned int)OutBuffer, BlockCount); - } - - delete[] (unsigned char*)DcmpBuffer1; -} - -void AtexSubCode1New(uint32_t* array1, uint32_t* array2, unsigned int count) -{ - for (auto i = 0u; i < count; ++i) { - const uint32_t mask = 1 << (i & 0x1F); - if ((mask & 0xC0000003) != 0 || ((1 << ((i >> 6) & 0x1F)) & 0xC0000003) != 0) { - const uint32_t array_index = i >> 5; // 4 * (i >> 5), but uint32_t* points to 4 bytes - array1[array_index] |= mask; - array2[array_index] |= mask; - } - } -} +#include "AtexDecompress.h" void __declspec(naked) AtexSubCode1() { @@ -275,7 +59,7 @@ void __declspec(naked) AtexSubCode1() } } -void AtexSubCode1_(unsigned int a, unsigned int b, unsigned int c) +void AtexSubCode1_Asm(unsigned int a, unsigned int b, unsigned int c) { __asm { mov ecx, a @@ -285,114 +69,6 @@ void AtexSubCode1_(unsigned int a, unsigned int b, unsigned int c) } } -void AtexSubCode2New(uint32_t *outBuffer, uint32_t *dcmpBuffer1, uint32_t *dcmpBuffer2, SImageData *imageData, uint32_t blockCount, uint32_t blockSize) -{ - if (blockCount == 0) { - return; - } - - uint32_t block_index = 0; - int extractedBits; - uint32_t* dataPosition; - uint32_t currentWord; - - while (block_index < blockCount) - { - const auto shiftLeft = imageData->currentBits >> 26; - const auto shiftValue = byte_79053C[2 * shiftLeft]; - int remainingBits = byte_79053D[2 * shiftLeft] + 1; - - if (shiftValue) { - imageData->currentBits = (imageData->currentBits << shiftValue) | (imageData->nextBits >> (32 - shiftValue)); - } - - uint32_t bitCount = imageData->remainingBits; - - if (shiftValue > bitCount) - { - dataPosition = imageData->DataPos; - - if (dataPosition == imageData->EndPos) - { - extractedBits = 0; - imageData->nextBits = 0; - } - else - { - currentWord = *dataPosition; - imageData->DataPos = dataPosition + 1; - imageData->nextBits = currentWord; - imageData->currentBits |= currentWord >> (bitCount - shiftValue + 32); - imageData->nextBits = currentWord << (shiftValue - bitCount); - extractedBits = bitCount - shiftValue + 32; - } - } - else - { - extractedBits = bitCount - shiftValue; - imageData->nextBits <<= shiftValue; - } - - const uint64_t combinedValue = (static_cast(imageData->currentBits) << 32) | imageData->nextBits; - imageData->remainingBits = extractedBits; - imageData->currentBits = static_cast(combinedValue >> 31); - int bitMask = static_cast(combinedValue >> 63); - - if (imageData->remainingBits) - { - imageData->nextBits = static_cast(combinedValue << 1); - imageData->remainingBits -= 1; - } - else - { - dataPosition = imageData->DataPos; - - if (dataPosition == imageData->EndPos) - { - imageData->nextBits = 0; - imageData->remainingBits = 0; - } - else - { - const auto curPos = *dataPosition; - imageData->DataPos = dataPosition + 1; - currentWord = curPos; - imageData->currentBits |= currentWord >> 31; - imageData->remainingBits = 31; - imageData->nextBits = 2 * currentWord; - } - } - - while (remainingBits > 0 && block_index < blockCount) - { - const int bitPosition = 1 << (block_index & 0x1F); - const int bufferIndex = block_index >> 5; - - if ((bitPosition & dcmpBuffer2[bufferIndex]) == 0) - { - if (bitMask) - { - outBuffer[0] = static_cast(-2); - outBuffer[1] = static_cast(-1); - dcmpBuffer2[bufferIndex] |= bitPosition; - dcmpBuffer1[bufferIndex] |= bitPosition; - bitMask = static_cast(combinedValue >> 63); - } - remainingBits -= 1; - } - - block_index++; - outBuffer += blockSize; - } - - while (block_index < blockCount && (1 << (block_index & 0x1F) & dcmpBuffer2[block_index >> 5]) != 0) - { - block_index++; - outBuffer += blockSize; - } - } -} - void __declspec(naked) AtexSubCode2() { __asm { @@ -624,7 +300,7 @@ void __declspec(naked) AtexSubCode2() } } -void AtexSubCode2_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, +void AtexSubCode2_Asm(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f) { __asm { @@ -638,187 +314,6 @@ void AtexSubCode2_(unsigned int a, unsigned int b, unsigned int c, unsigned int } } -void AtexSubCode3New(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) -{ - const unsigned int current_bits = imageData->currentBits; - const int currentDataPos = (16 * current_bits) | (imageData->nextBits >> 28); - const unsigned int remainingBits = imageData->remainingBits; - unsigned int tempBits = 0; - int bitDifference; - int bufferArray[4]{}; - int bitCounter; - uint32_t* bufferPos = outBuffer; - - imageData->currentBits = currentDataPos; - - if (remainingBits < 4) - { - unsigned int* dataPtr = imageData->DataPos; - if (imageData->DataPos == imageData->EndPos) - { - imageData->nextBits = 0; - imageData->remainingBits = 0; - } - else - { - unsigned int newBits = *dataPtr; - imageData->DataPos = dataPtr + 1; - imageData->nextBits = newBits; - imageData->currentBits = (newBits >> (remainingBits + 28)) | currentDataPos; - imageData->remainingBits = remainingBits + 28; - imageData->nextBits = newBits << (4 - remainingBits); - } - } - else - { - imageData->nextBits *= 16; - imageData->remainingBits = remainingBits - 4; - } - - if (blockCount == 0) - { - return; - } - - while (tempBits != blockCount) - { - int bitShifted = imageData->currentBits >> 26; - int bitShiftedBy = byte_79053D[2 * bitShifted] + 1; - unsigned int bitField = byte_79053C[2 * bitShifted]; - - if (byte_79053C[2 * bitShifted]) - { - imageData->currentBits = (imageData->currentBits << bitField) | (imageData->nextBits >> (32 - bitField)); - } - - int flagBits = imageData->remainingBits; - unsigned int bitMask = flagBits; - - if (bitField > flagBits) - { - if (imageData->DataPos == imageData->EndPos) - { - bitDifference = 0; - imageData->nextBits = 0; - } - else - { - unsigned int dataOffset = *imageData->DataPos++; - imageData->nextBits = dataOffset; - bitCounter = bitMask - bitField + 32; - imageData->currentBits |= dataOffset >> bitCounter; - imageData->nextBits = dataOffset << (bitField - flagBits); - bitDifference = bitCounter; - } - } - else - { - bitDifference = flagBits - bitField; - imageData->nextBits <<= bitField; - } - - imageData->remainingBits = bitDifference; - unsigned int curBits = imageData->currentBits; - imageData->currentBits = (2 * curBits) | (imageData->nextBits >> 31); - flagBits = curBits >> 31; - - if (imageData->remainingBits) - { - imageData->nextBits *= 2; - imageData->remainingBits -= 1; - } - else - { - unsigned int* bufferPtr = imageData->DataPos; - if (imageData->DataPos == imageData->EndPos) - { - imageData->nextBits = 0; - imageData->remainingBits = 0; - } - else - { - unsigned int finalShift = *bufferPtr; - imageData->DataPos = bufferPtr + 1; - imageData->nextBits = finalShift; - int bufferOffset = (finalShift >> 31) | imageData->currentBits; - imageData->currentBits = bufferOffset; - imageData->nextBits = 2 * finalShift; - imageData->remainingBits = 31; - } - } - - int bitIndex = flagBits; - bitCounter = flagBits; - - if (flagBits) - { - unsigned int combinedBitsShifted = imageData->currentBits; - imageData->currentBits = (2 * combinedBitsShifted) | (imageData->nextBits >> 31); - const int bitRemainingShift = imageData->remainingBits; - int finalBitShift = combinedBitsShifted >> 31; - - if (bitRemainingShift) - { - imageData->nextBits *= 2; - imageData->remainingBits = bitRemainingShift - 1; - } - else - { - if (imageData->DataPos == imageData->EndPos) - { - imageData->nextBits = 0; - imageData->remainingBits = 0; - } - else - { - imageData->nextBits = *imageData->DataPos++; - imageData->currentBits |= imageData->nextBits >> 31; - imageData->nextBits *= 2; - imageData->remainingBits = 31; - } - } - - bitIndex = finalBitShift + flagBits; - bitCounter = finalBitShift + flagBits; - } - - while (bitShiftedBy) - { - while (tempBits != blockCount) - { - const int nextBitOffset = 1 << (tempBits & 0x1F); - const int finalShiftedBits = tempBits >> 5; - - if ((nextBitOffset & dcmpBuffer2[finalShiftedBits]) == 0) - { - if (bitIndex) - { - bufferPos[0] = bufferArray[2 * bitIndex]; - bufferPos[1] = bufferArray[2 * bitCounter + 1]; - dcmpBuffer1[finalShiftedBits] |= nextBitOffset; - bitIndex = bitCounter; - } - bitShiftedBy--; - } - - tempBits++; - bufferPos += blockSize; - - if (!bitShiftedBy) - break; - } - - while (((1 << (tempBits & 0x1F)) & dcmpBuffer2[tempBits >> 5]) != 0) - { - bufferPos += blockSize; - - if (++tempBits == blockCount) - return; - } - } - } -} - void __declspec(naked) AtexSubCode3() { __asm { @@ -1534,20 +1029,20 @@ void __declspec(naked) AtexSubCode4() } } -void AtexSubCode4_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f) +void AtexSubCode4_Asm(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) { __asm { - mov ecx, a - mov edx, b - push f - push e - push d - push c + mov ecx, outBuffer + mov edx, dcmpBuffer1 + push blockSize + push blockCount + push imageData + push dcmpBuffer2 call AtexSubCode4 } } +void AtexSubCode6(); void __declspec(naked) AtexSubCode5() { __asm { @@ -1835,7 +1330,7 @@ void __declspec(naked) AtexSubCode5() } } -void AtexSubCode5_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, +void AtexSubCode5_Asm(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g) { __asm { @@ -2333,7 +1828,7 @@ void __declspec(naked) AtexSubCode7() } } -void AtexSubCode7_(unsigned int a, unsigned int b) +void AtexSubCode7_Asm(unsigned int a, unsigned int b) { __asm { mov ecx, a diff --git a/SourceFiles/AtexAsm.h b/SourceFiles/AtexAsm.h index df9d084..bfba49b 100644 --- a/SourceFiles/AtexAsm.h +++ b/SourceFiles/AtexAsm.h @@ -1,16 +1,9 @@ -#pragma once +#pragma once -struct SImageDescriptor -{ - int xres, yres; - unsigned char* Data; - int a; - int b; - unsigned char* image; - int imageformat; - int c; -}; - -int DecompressAtex(int a, int b, int imageformat, int d, int e, int f, int g); -void AtexDecompress(unsigned int* input, unsigned int unknown, unsigned int imageformat, - SImageDescriptor ImageDescriptor, unsigned int* output); +struct SImageData; +void AtexSubCode1_Asm(uint32_t* array1, uint32_t* array2, unsigned int count); +void AtexSubCode2_Asm(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void AtexSubCode3_Asm(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void AtexSubCode4_Asm(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void AtexSubCode5_Asm(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g); +void AtexSubCode7_Asm(unsigned int a, unsigned int b); diff --git a/SourceFiles/AtexDecompress.cpp b/SourceFiles/AtexDecompress.cpp new file mode 100644 index 0000000..b1a35fc --- /dev/null +++ b/SourceFiles/AtexDecompress.cpp @@ -0,0 +1,471 @@ +#include "pch.h" +#include "AtexDecompress.h" +#include "AtexAsm.h" + +struct SImageData; + +void DecompressUnknownAtexRoutine(uint32_t* array1, uint32_t* array2, unsigned int count); +void DecompressAtex1Routine(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void DecompressAtex2Routine(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); + +int ImgFmt(unsigned int Format) +{ + if (Format >= 0x17) + { + printf("ERROR: bad image format (%d)!", Format); + exit(0); + } + return ImageFormats[Format]; +} + +void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned int ImageFormat, SImageDescriptor ImageDescriptor, unsigned int* OutBuffer) +{ + unsigned int HeaderSize = 12; + + SImageData ImageData; + + int AlphaDataSize2 = ((ImageFormat && 21) - 1) & 2; + + int ColorDataSize = ImgFmt(ImageFormat); + int AlphaDataSize = ColorDataSize; + + AlphaDataSize &= 640; + if (AlphaDataSize) + { + AlphaDataSize = 2; + } + + ColorDataSize &= 528; + if (ColorDataSize) + { + ColorDataSize = 2; + } + + int BlockSize = ColorDataSize + AlphaDataSize2 + AlphaDataSize; + + int BlockCount = ImageDescriptor.xres * ImageDescriptor.yres / 16; + + if (! BlockCount) + { + printf("BlockCount zero\n"); + return; + } + + unsigned int* DcmpBuffer1 = new unsigned int[BlockCount]; + unsigned int* DcmpBuffer2 = DcmpBuffer1 + BlockCount / 2; + memset(DcmpBuffer1, 0, BlockCount * 4); + + ImageData.xres = ImageDescriptor.xres; + ImageData.yres = ImageDescriptor.yres; + + unsigned int DataSize = InputBuffer[HeaderSize >> 2]; + + if (HeaderSize + 8 >= BufferSize) + { + printf("Error 567h\n"); + } + if (DataSize <= 8) + { + printf("Error 569h\n"); + } + if (DataSize + HeaderSize > BufferSize) + { + printf("Error 56Ah\n"); + } + + int CompressionCode = InputBuffer[(HeaderSize + 4) >> 2]; + + ImageData.DataPos = InputBuffer + ((HeaderSize + 8) >> 2); + + if (CompressionCode) + { + ImageData.currentBits = ImageData.remainingBits = ImageData.nextBits = 0; + ImageData.EndPos = ImageData.DataPos + ((DataSize - 8) >> 2); + + if (ImageData.DataPos != ImageData.EndPos) + { + ImageData.currentBits = ImageData.DataPos[0]; + ImageData.DataPos++; + } + + if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && + (ImageFormat == 0x11 || ImageFormat == 0x10)) + { + DecompressUnknownAtexRoutine(DcmpBuffer1, DcmpBuffer2, BlockCount); + } + if (CompressionCode & 1 && ColorDataSize && ! AlphaDataSize && ! AlphaDataSize2) + { + DecompressAtex1Routine(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + } + if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) + { + DecompressAtex2Routine(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + } + if (CompressionCode & 4 && ImageFormat >= 0x12 && ImageFormat <= 0x15) + { + AtexSubCode4_Asm(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + } + if (CompressionCode & 8 && ColorDataSize) + { + AtexSubCode5_Asm((unsigned int)OutBuffer + AlphaDataSize2 + AlphaDataSize * 4, + (unsigned int)DcmpBuffer1, (unsigned int)DcmpBuffer2, (unsigned int)&ImageData, + BlockCount, BlockSize, ImageFormat == 0xf); + } + ImageData.DataPos--; + } + + [[maybe_unused]] unsigned int* DataEnd = InputBuffer + ((HeaderSize + DataSize) >> 2); + + if ((AlphaDataSize || AlphaDataSize2) && BlockCount) + { + unsigned int* BufferVar = OutBuffer; + + for (int x = 0; x < BlockCount; x++) + { + if (! (DcmpBuffer1[x >> 5] & 1 << x)) + { + BufferVar[0] = ImageData.DataPos[0]; + BufferVar[1] = ImageData.DataPos[1]; + ImageData.DataPos += 2; + } + BufferVar += BlockSize; + } + } + + if (ColorDataSize && BlockCount) + { + unsigned int* BufferVar = OutBuffer + AlphaDataSize2 + AlphaDataSize; + + for (int x = 0; x < BlockCount; x++) + { + if (! (DcmpBuffer2[x >> 5] & 1 << x)) + { + BufferVar[0] = ImageData.DataPos[0]; + ImageData.DataPos++; + } + BufferVar += BlockSize; + } + + BufferVar = OutBuffer + AlphaDataSize2 + AlphaDataSize + 1; + + for (int x = 0; x < BlockCount; x++) + { + if (! (DcmpBuffer2[x >> 5] & 1 << x)) + { + BufferVar[0] = ImageData.DataPos[0]; + ImageData.DataPos++; + } + BufferVar += BlockSize; + } + } + + if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && + (ImageFormat == 0x10 || ImageFormat == 0x11)) + { + AtexSubCode7_Asm((unsigned int)OutBuffer, BlockCount); + } + + delete[] (unsigned char*)DcmpBuffer1; +} + +void DecompressUnknownAtexRoutine(uint32_t* array1, uint32_t* array2, unsigned int count) +{ + for (auto i = 0u; i < count; ++i) { + const uint32_t mask = 1 << (i & 0x1F); + if ((mask & 0xC0000003) != 0 || ((1 << ((i >> 6) & 0x1F)) & 0xC0000003) != 0) { + const uint32_t array_index = i >> 5; // 4 * (i >> 5), but uint32_t* points to 4 bytes + array1[array_index] |= mask; + array2[array_index] |= mask; + } + } +} + +void DecompressAtex1Routine(uint32_t *outBuffer, uint32_t *dcmpBuffer1, uint32_t *dcmpBuffer2, SImageData *imageData, uint32_t blockCount, uint32_t blockSize) +{ + if (blockCount == 0) { + return; + } + + uint32_t block_index = 0; + int extractedBits; + uint32_t* dataPosition; + uint32_t currentWord; + + while (block_index < blockCount) + { + const auto shiftLeft = imageData->currentBits >> 26; + const auto shiftValue = byte_79053C[2 * shiftLeft]; + int remainingBits = byte_79053D[2 * shiftLeft] + 1; + + if (shiftValue) { + imageData->currentBits = (imageData->currentBits << shiftValue) | (imageData->nextBits >> (32 - shiftValue)); + } + + uint32_t bitCount = imageData->remainingBits; + + if (shiftValue > bitCount) + { + dataPosition = imageData->DataPos; + + if (dataPosition == imageData->EndPos) + { + extractedBits = 0; + imageData->nextBits = 0; + } + else + { + currentWord = *dataPosition; + imageData->DataPos = dataPosition + 1; + imageData->nextBits = currentWord; + imageData->currentBits |= currentWord >> (bitCount - shiftValue + 32); + imageData->nextBits = currentWord << (shiftValue - bitCount); + extractedBits = bitCount - shiftValue + 32; + } + } + else + { + extractedBits = bitCount - shiftValue; + imageData->nextBits <<= shiftValue; + } + + const uint64_t combinedValue = (static_cast(imageData->currentBits) << 32) | imageData->nextBits; + imageData->remainingBits = extractedBits; + imageData->currentBits = static_cast(combinedValue >> 31); + int bitMask = static_cast(combinedValue >> 63); + + if (imageData->remainingBits) + { + imageData->nextBits = static_cast(combinedValue << 1); + imageData->remainingBits -= 1; + } + else + { + dataPosition = imageData->DataPos; + + if (dataPosition == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + const auto curPos = *dataPosition; + imageData->DataPos = dataPosition + 1; + currentWord = curPos; + imageData->currentBits |= currentWord >> 31; + imageData->remainingBits = 31; + imageData->nextBits = 2 * currentWord; + } + } + + while (remainingBits > 0 && block_index < blockCount) + { + const int bitPosition = 1 << (block_index & 0x1F); + const int bufferIndex = block_index >> 5; + + if ((bitPosition & dcmpBuffer2[bufferIndex]) == 0) + { + if (bitMask) + { + outBuffer[0] = static_cast(-2); + outBuffer[1] = static_cast(-1); + dcmpBuffer2[bufferIndex] |= bitPosition; + dcmpBuffer1[bufferIndex] |= bitPosition; + bitMask = static_cast(combinedValue >> 63); + } + remainingBits -= 1; + } + + block_index++; + outBuffer += blockSize; + } + + while (block_index < blockCount && (1 << (block_index & 0x1F) & dcmpBuffer2[block_index >> 5]) != 0) + { + block_index++; + outBuffer += blockSize; + } + } +} + +void DecompressAtex2Routine(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) +{ + const unsigned int current_bits = imageData->currentBits; + const int currentDataPos = (16 * current_bits) | (imageData->nextBits >> 28); + const unsigned int remainingBits = imageData->remainingBits; + unsigned int tempBits = 0; + int bitDifference; + int bufferArray[4]{}; + int bitCounter; + uint32_t* bufferPos = outBuffer; + + imageData->currentBits = currentDataPos; + + if (remainingBits < 4) + { + unsigned int* dataPtr = imageData->DataPos; + if (imageData->DataPos == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + unsigned int newBits = *dataPtr; + imageData->DataPos = dataPtr + 1; + imageData->nextBits = newBits; + imageData->currentBits = (newBits >> (remainingBits + 28)) | currentDataPos; + imageData->remainingBits = remainingBits + 28; + imageData->nextBits = newBits << (4 - remainingBits); + } + } + else + { + imageData->nextBits *= 16; + imageData->remainingBits = remainingBits - 4; + } + + if (blockCount == 0) + { + return; + } + + while (tempBits != blockCount) + { + int bitShifted = imageData->currentBits >> 26; + int bitShiftedBy = byte_79053D[2 * bitShifted] + 1; + unsigned int bitField = byte_79053C[2 * bitShifted]; + + if (byte_79053C[2 * bitShifted]) + { + imageData->currentBits = (imageData->currentBits << bitField) | (imageData->nextBits >> (32 - bitField)); + } + + unsigned int flagBits = imageData->remainingBits; + unsigned int bitMask = flagBits; + + if (bitField > flagBits) + { + if (imageData->DataPos == imageData->EndPos) + { + bitDifference = 0; + imageData->nextBits = 0; + } + else + { + unsigned int dataOffset = *imageData->DataPos++; + imageData->nextBits = dataOffset; + bitCounter = bitMask - bitField + 32; + imageData->currentBits |= dataOffset >> bitCounter; + imageData->nextBits = dataOffset << (bitField - flagBits); + bitDifference = bitCounter; + } + } + else + { + bitDifference = flagBits - bitField; + imageData->nextBits <<= bitField; + } + + imageData->remainingBits = bitDifference; + unsigned int curBits = imageData->currentBits; + imageData->currentBits = (2 * curBits) | (imageData->nextBits >> 31); + flagBits = curBits >> 31; + + if (imageData->remainingBits) + { + imageData->nextBits *= 2; + imageData->remainingBits -= 1; + } + else + { + unsigned int* bufferPtr = imageData->DataPos; + if (imageData->DataPos == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + unsigned int finalShift = *bufferPtr; + imageData->DataPos = bufferPtr + 1; + imageData->nextBits = finalShift; + int bufferOffset = (finalShift >> 31) | imageData->currentBits; + imageData->currentBits = bufferOffset; + imageData->nextBits = 2 * finalShift; + imageData->remainingBits = 31; + } + } + + int bitIndex = flagBits; + bitCounter = flagBits; + + if (flagBits) + { + unsigned int combinedBitsShifted = imageData->currentBits; + imageData->currentBits = (2 * combinedBitsShifted) | (imageData->nextBits >> 31); + const int bitRemainingShift = imageData->remainingBits; + int finalBitShift = combinedBitsShifted >> 31; + + if (bitRemainingShift) + { + imageData->nextBits *= 2; + imageData->remainingBits = bitRemainingShift - 1; + } + else + { + if (imageData->DataPos == imageData->EndPos) + { + imageData->nextBits = 0; + imageData->remainingBits = 0; + } + else + { + imageData->nextBits = *imageData->DataPos++; + imageData->currentBits |= imageData->nextBits >> 31; + imageData->nextBits *= 2; + imageData->remainingBits = 31; + } + } + + bitIndex = finalBitShift + flagBits; + bitCounter = finalBitShift + flagBits; + } + + while (bitShiftedBy) + { + while (tempBits != blockCount) + { + const int nextBitOffset = 1 << (tempBits & 0x1F); + const int finalShiftedBits = tempBits >> 5; + + if ((nextBitOffset & dcmpBuffer2[finalShiftedBits]) == 0) + { + if (bitIndex) + { + bufferPos[0] = bufferArray[2 * bitIndex]; + bufferPos[1] = bufferArray[2 * bitCounter + 1]; + dcmpBuffer1[finalShiftedBits] |= nextBitOffset; + bitIndex = bitCounter; + } + bitShiftedBy--; + } + + tempBits++; + bufferPos += blockSize; + + if (!bitShiftedBy) + break; + } + + while (((1 << (tempBits & 0x1F)) & dcmpBuffer2[tempBits >> 5]) != 0) + { + bufferPos += blockSize; + + if (++tempBits == blockCount) + return; + } + } + } +} + diff --git a/SourceFiles/AtexDecompress.h b/SourceFiles/AtexDecompress.h new file mode 100644 index 0000000..af7ed7e --- /dev/null +++ b/SourceFiles/AtexDecompress.h @@ -0,0 +1,47 @@ +#pragma once + +struct SImageDescriptor +{ + int xres, yres; + unsigned char* Data; + int a; + int b; + unsigned char* image; + int imageformat; + int c; +}; + +struct SImageData +{ + unsigned int *DataPos, *EndPos, remainingBits, currentBits, nextBits, xres, yres; +}; + + + +constexpr unsigned int ImageFormats[] = {0x0B2, 0x12, 0x0B2, 0x72, 0x12, 0x12, 0x12, 0x100, + 0x1A4, 0x1A4, 0x1A4, 0x104, 0x0A2, 0x78, 0x400, 0x71, + 0x0B1, 0x0B1, 0x0B1, 0x0B1, 0x0A1, 0x11, 0x201}; + +constexpr unsigned char byte_79053C[] = { + 0x6, 0x10, 0x6, 0x0F, 0x6, 0x0E, 0x6, 0x0D, 0x6, 0x0C, 0x6, 0x0B, 0x6, 0x0A, 0x6, 0x9, + 0x6, 0x8, 0x6, 0x7, 0x6, 0x6, 0x6, 0x5, 0x6, 0x4, 0x6, 0x3, 0x6, 0x2, 0x6, 0x1, + 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, + 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, + 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, + 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0}; + +constexpr unsigned char byte_79053D[] = { + 0x10, 0x6, 0x0F, 0x6, 0x0E, 0x6, 0x0D, 0x6, 0x0C, 0x6, 0x0B, 0x6, 0x0A, 0x6, 0x9, 0x6, + 0x8, 0x6, 0x7, 0x6, 0x6, 0x6, 0x5, 0x6, 0x4, 0x6, 0x3, 0x6, 0x2, 0x6, 0x1, 0x2, + 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, + 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x2, 0x11, 0x1, + 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, + 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, + 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, + 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0}; + +int DecompressAtex(int a, int b, int imageformat, int d, int e, int f, int g); +void AtexDecompress(unsigned int* input, unsigned int unknown, unsigned int imageformat, + SImageDescriptor ImageDescriptor, unsigned int* output); diff --git a/SourceFiles/AtexReader.cpp b/SourceFiles/AtexReader.cpp index 65c5875..0d51f61 100644 --- a/SourceFiles/AtexReader.cpp +++ b/SourceFiles/AtexReader.cpp @@ -1,6 +1,6 @@ #include "pch.h" -#include "AtexAsm.h" +#include "AtexDecompress.h" #pragma pack(1) diff --git a/SourceFiles/pch.h b/SourceFiles/pch.h index b067223..027b17f 100644 --- a/SourceFiles/pch.h +++ b/SourceFiles/pch.h @@ -71,7 +71,7 @@ #include "ImGuiFileDialog.h" #include "GWUnpacker.h" -#include "AtexAsm.h" +#include "AtexDecompress.h" #include "AtexReader.h" #ifdef _DEBUG From 6b9bf3ae3d489f6fcb04875849587912f4880f7b Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 17:08:14 +0200 Subject: [PATCH 5/7] fix function names --- SourceFiles/AtexAsm.cpp | 38 ++++++++++++++++------------------ SourceFiles/AtexDecompress.cpp | 6 +++--- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/SourceFiles/AtexAsm.cpp b/SourceFiles/AtexAsm.cpp index 0924b62..7c68a6a 100644 --- a/SourceFiles/AtexAsm.cpp +++ b/SourceFiles/AtexAsm.cpp @@ -59,12 +59,12 @@ void __declspec(naked) AtexSubCode1() } } -void AtexSubCode1_Asm(unsigned int a, unsigned int b, unsigned int c) +void AtexSubCode1_Asm(uint32_t* array1, uint32_t* array2, unsigned int count) { __asm { - mov ecx, a - mov edx, b - push c + mov ecx, array1 + mov edx, array2 + push count call AtexSubCode1 } } @@ -300,16 +300,15 @@ void __declspec(naked) AtexSubCode2() } } -void AtexSubCode2_Asm(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f) +void AtexSubCode2_Asm(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) { __asm { - mov ecx, a - mov edx, b - push f - push e - push d - push c + mov ecx, outBuffer + mov edx, dcmpBuffer1 + push blockSize + push blockCount + push imageData + push dcmpBuffer2 call AtexSubCode2 } } @@ -669,16 +668,15 @@ void __declspec(naked) AtexSubCode3() } } -void AtexSubCode3_(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, - unsigned int f) +void AtexSubCode3_Asm(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) { __asm { - mov ecx, a - mov edx, b - push f - push e - push d - push c + mov ecx, outBuffer + mov edx, dcmpBuffer1 + push blockSize + push blockCount + push imageData + push dcmpBuffer2 call AtexSubCode3 } } diff --git a/SourceFiles/AtexDecompress.cpp b/SourceFiles/AtexDecompress.cpp index b1a35fc..34f9696 100644 --- a/SourceFiles/AtexDecompress.cpp +++ b/SourceFiles/AtexDecompress.cpp @@ -91,15 +91,15 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && (ImageFormat == 0x11 || ImageFormat == 0x10)) { - DecompressUnknownAtexRoutine(DcmpBuffer1, DcmpBuffer2, BlockCount); + AtexSubCode1_Asm(DcmpBuffer1, DcmpBuffer2, BlockCount); } if (CompressionCode & 1 && ColorDataSize && ! AlphaDataSize && ! AlphaDataSize2) { - DecompressAtex1Routine(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + AtexSubCode2_Asm(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) { - DecompressAtex2Routine(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + AtexSubCode3_Asm(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 4 && ImageFormat >= 0x12 && ImageFormat <= 0x15) { From aaf7cb68c28d14b124eabf22163566bfe02cc059 Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 17:19:39 +0200 Subject: [PATCH 6/7] rename functions back to AtexSubCodeN_Cpp to make switching between them easier --- SourceFiles/AtexDecompress.cpp | 20 ++++++++++---------- SourceFiles/AtexDecompress.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SourceFiles/AtexDecompress.cpp b/SourceFiles/AtexDecompress.cpp index 34f9696..9b32132 100644 --- a/SourceFiles/AtexDecompress.cpp +++ b/SourceFiles/AtexDecompress.cpp @@ -4,9 +4,9 @@ struct SImageData; -void DecompressUnknownAtexRoutine(uint32_t* array1, uint32_t* array2, unsigned int count); -void DecompressAtex1Routine(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); -void DecompressAtex2Routine(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void AtexSubCode1_Cpp(uint32_t* array1, uint32_t* array2, unsigned int count); +void AtexSubCode2_Cpp(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +void AtexSubCode3_Cpp(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); int ImgFmt(unsigned int Format) { @@ -18,7 +18,7 @@ int ImgFmt(unsigned int Format) return ImageFormats[Format]; } -void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned int ImageFormat, SImageDescriptor ImageDescriptor, unsigned int* OutBuffer) +void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned int ImageFormat, const SImageDescriptor& ImageDescriptor, unsigned int* OutBuffer) { unsigned int HeaderSize = 12; @@ -91,15 +91,15 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned if (CompressionCode & 0x10 && ImageData.xres == 256 && ImageData.yres == 256 && (ImageFormat == 0x11 || ImageFormat == 0x10)) { - AtexSubCode1_Asm(DcmpBuffer1, DcmpBuffer2, BlockCount); + AtexSubCode1_Cpp(DcmpBuffer1, DcmpBuffer2, BlockCount); } if (CompressionCode & 1 && ColorDataSize && ! AlphaDataSize && ! AlphaDataSize2) { - AtexSubCode2_Asm(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + AtexSubCode2_Cpp(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) { - AtexSubCode3_Asm(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + AtexSubCode3_Cpp(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 4 && ImageFormat >= 0x12 && ImageFormat <= 0x15) { @@ -168,7 +168,7 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned delete[] (unsigned char*)DcmpBuffer1; } -void DecompressUnknownAtexRoutine(uint32_t* array1, uint32_t* array2, unsigned int count) +void AtexSubCode1_Cpp(uint32_t* array1, uint32_t* array2, unsigned int count) { for (auto i = 0u; i < count; ++i) { const uint32_t mask = 1 << (i & 0x1F); @@ -180,7 +180,7 @@ void DecompressUnknownAtexRoutine(uint32_t* array1, uint32_t* array2, unsigned i } } -void DecompressAtex1Routine(uint32_t *outBuffer, uint32_t *dcmpBuffer1, uint32_t *dcmpBuffer2, SImageData *imageData, uint32_t blockCount, uint32_t blockSize) +void AtexSubCode2_Cpp(uint32_t *outBuffer, uint32_t *dcmpBuffer1, uint32_t *dcmpBuffer2, SImageData *imageData, uint32_t blockCount, uint32_t blockSize) { if (blockCount == 0) { return; @@ -288,7 +288,7 @@ void DecompressAtex1Routine(uint32_t *outBuffer, uint32_t *dcmpBuffer1, uint32_t } } -void DecompressAtex2Routine(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) +void AtexSubCode3_Cpp(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize) { const unsigned int current_bits = imageData->currentBits; const int currentDataPos = (16 * current_bits) | (imageData->nextBits >> 28); diff --git a/SourceFiles/AtexDecompress.h b/SourceFiles/AtexDecompress.h index af7ed7e..aaee90a 100644 --- a/SourceFiles/AtexDecompress.h +++ b/SourceFiles/AtexDecompress.h @@ -44,4 +44,4 @@ constexpr unsigned char byte_79053D[] = { int DecompressAtex(int a, int b, int imageformat, int d, int e, int f, int g); void AtexDecompress(unsigned int* input, unsigned int unknown, unsigned int imageformat, - SImageDescriptor ImageDescriptor, unsigned int* output); + const SImageDescriptor& ImageDescriptor, unsigned int* output); From 8dea921ba3f273e902cf1886085b21f2d789072e Mon Sep 17 00:00:00 2001 From: DubbleClick Date: Wed, 4 Sep 2024 19:20:34 +0200 Subject: [PATCH 7/7] use AtexSubCode3_Asm instead of _Cpp because of highlights being lost --- SourceFiles/AtexDecompress.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SourceFiles/AtexDecompress.cpp b/SourceFiles/AtexDecompress.cpp index 9b32132..4d5f488 100644 --- a/SourceFiles/AtexDecompress.cpp +++ b/SourceFiles/AtexDecompress.cpp @@ -6,6 +6,7 @@ struct SImageData; void AtexSubCode1_Cpp(uint32_t* array1, uint32_t* array2, unsigned int count); void AtexSubCode2_Cpp(uint32_t* outBuffer, uint32_t* dcmpBuffer1, uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); +// currently loses some highlights, but I have no idea why. even a direct translation has this issue void AtexSubCode3_Cpp(uint32_t* outBuffer, uint32_t* dcmpBuffer1, const uint32_t* dcmpBuffer2, SImageData* imageData, unsigned int blockCount, unsigned int blockSize); int ImgFmt(unsigned int Format) @@ -99,7 +100,7 @@ void AtexDecompress(unsigned int* InputBuffer, unsigned int BufferSize, unsigned } if (CompressionCode & 2 && ImageFormat >= 0x10 && ImageFormat <= 0x11) { - AtexSubCode3_Cpp(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); + AtexSubCode3_Asm(OutBuffer, DcmpBuffer1, DcmpBuffer2, &ImageData, BlockCount, BlockSize); } if (CompressionCode & 4 && ImageFormat >= 0x12 && ImageFormat <= 0x15) {