diff --git a/src/LZ77/LZType10.cpp b/src/LZ77/LZType10.cpp index ee033a9..5b57200 100644 --- a/src/LZ77/LZType10.cpp +++ b/src/LZ77/LZType10.cpp @@ -1,7 +1,12 @@ -#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZType10.hpp" -#include + +#include #include +#include + +#include "LZ77/LZLookupTable.hpp" + +#include LZType10::LZType10(atInt32 MinimumOffset, atInt32 SlidingWindow, atInt32 MinimumMatch, atInt32 BlockSize) : LZBase(MinimumOffset, SlidingWindow, MinimumMatch, BlockSize) { @@ -17,25 +22,25 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe athena::io::MemoryCopyWriter outbuf("tmp"); outbuf.writeUint32(encodeSize); - atUint8* ptrStart = (atUint8*)src; - atUint8* ptrEnd = (atUint8*)(src + srcLength); + const atUint8* ptrStart = src; + const atUint8* ptrEnd = src + srcLength; // At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be // compressed it would take blockSize*2 bytes - atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written + auto compressedBytes = std::unique_ptr(new atUint8[m_blockSize * 2]); // Holds the compressed bytes yet to be written while (ptrStart < ptrEnd) { atUint8 blockLen = 0; // In Binary represents 1 if byte is compressed or 0 if not compressed // For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed - atUint8* ptrBytes = compressedBytes; + atUint8* ptrBytes = compressedBytes.get(); for (atInt32 i = 0; i < m_blockSize; i++) { // length_offset searchResult=Search(ptrStart, filedata, ptrEnd); - LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); + const LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); // If the number of bytes to be compressed is at least the size of the Minimum match - if (searchResult.length >= (atUint32)m_minMatch) { + if (searchResult.length >= static_cast(m_minMatch)) { // Gotta swap the bytes since system is wii is big endian and most computers are little endian atUint16 lenOff = (((searchResult.length - m_minMatch) & 0xF) << 12) | ((searchResult.offset - 1) & 0xFFF); athena::utility::BigUint16(lenOff); @@ -49,45 +54,50 @@ atUint32 LZType10::compress(const atUint8* src, atUint8** dstBuf, atUint32 srcLe blockLen |= (1 << (7 - i)); // Stores which of the next 8 bytes is compressed // bit 1 for compress and bit 0 for not compressed - } else + } else { *ptrBytes++ = *ptrStart++; + } } outbuf.writeByte(blockLen); - outbuf.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + outbuf.writeUBytes(compressedBytes.get(), static_cast(ptrBytes - compressedBytes.get())); } - delete[] compressedBytes; - compressedBytes = nullptr; - // Add zeros until the file is a multiple of 4 - while ((outbuf.position() % 4) != 0) + while ((outbuf.position() % 4) != 0) { outbuf.writeByte(0); + } *dstBuf = outbuf.data(); outbuf.save(); - return (atUint32)outbuf.length(); + return static_cast(outbuf.length()); } atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) { - if (*(atUint8*)(src) != 0x10) + if (*src != 0x10) { return 0; + } - atUint32 uncompressedSize = *(atUint32*)(src); // Size of data when it is uncompressed - athena::utility::LittleUint32(uncompressedSize); // The compressed file has the filesize encoded in little endian - uncompressedSize = uncompressedSize >> 8; // first byte is the encode flag + // Size of data when it is uncompressed + atUint32 uncompressedSize; + std::memcpy(&uncompressedSize, src, sizeof(uncompressedSize)); - atUint8* uncompressedData = new atUint8[uncompressedSize]; - atUint8* outputPtr = uncompressedData; - atUint8* outputEndPtr = uncompressedData + uncompressedSize; - atUint8* inputPtr = (atUint8*)src + 4; - atUint8* inputEndPtr = (atUint8*)src + srcLength; + // The compressed file has the filesize encoded in little endian + athena::utility::LittleUint32(uncompressedSize); + + // first byte is the encode flag + uncompressedSize = uncompressedSize >> 8; + + auto uncompressedData = std::unique_ptr(new atUint8[uncompressedSize]); + atUint8* outputPtr = uncompressedData.get(); + atUint8* outputEndPtr = uncompressedData.get() + uncompressedSize; + const atUint8* inputPtr = src + 4; + const atUint8* inputEndPtr = src + srcLength; while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) { + const atUint8 isCompressed = *inputPtr++; - atUint8 isCompressed = *inputPtr++; - - for (atUint32 i = 0; i < (atUint32)m_blockSize; i++) { + for (atUint32 i = 0; i < static_cast(m_blockSize); i++) { // Checks to see if the next byte is compressed by looking // at its binary representation - E.g 10010000 // This says that the first extracted byte and the four extracted byte is compressed @@ -101,28 +111,29 @@ atUint32 LZType10::decompress(const atUint8* src, atUint8** dst, atUint32 srcLen decoding.length = (lenOff >> 12) + m_minMatch; decoding.offset = static_cast((lenOff & 0xFFF) + 1); - if ((outputPtr - decoding.offset) < uncompressedData) { + if ((outputPtr - decoding.offset) < uncompressedData.get()) { // If the offset to look for uncompressed is passed the current uncompresed data then the data is not // compressed - delete[] uncompressedData; - uncompressedData = nullptr; dst = nullptr; return 0; } - for (atUint32 j = 0; j < decoding.length; ++j) + for (size_t j = 0; j < decoding.length; ++j) { outputPtr[j] = (outputPtr - decoding.offset)[j]; + } outputPtr += decoding.length; - } else + } else { *outputPtr++ = *inputPtr++; + } - if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) + if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) { break; + } } } - *dst = uncompressedData; + *dst = uncompressedData.release(); return uncompressedSize; } diff --git a/src/LZ77/LZType11.cpp b/src/LZ77/LZType11.cpp index de26bd8..912c71b 100644 --- a/src/LZ77/LZType11.cpp +++ b/src/LZ77/LZType11.cpp @@ -1,7 +1,12 @@ -#include "LZ77/LZLookupTable.hpp" #include "LZ77/LZType11.hpp" -#include + +#include #include +#include + +#include "LZ77/LZLookupTable.hpp" + +#include LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimumMatch, atInt32 blockSize) : LZBase(minimumOffset, slidingWindow, minimumMatch, blockSize) { @@ -12,32 +17,32 @@ LZType11::LZType11(atInt32 minimumOffset, atInt32 slidingWindow, atInt32 minimum atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLength) { athena::io::MemoryCopyWriter outbuff("tmp"); - if (srcLength > 0xFFFFFF) // If length is greater than 24 bits or 16 Megs - { + if (srcLength > 0xFFFFFF) { // If length is greater than 24 bits or 16 Megs atUint32 encodeFlag = 0x11; athena::utility::LittleUint32(encodeFlag); athena::utility::LittleUint32(srcLength); // Filesize data is little endian outbuff.writeUint32(encodeFlag); outbuff.writeUint32(srcLength); - } else { atUint32 encodeSize = (srcLength << 8) | (0x11); athena::utility::LittleUint32(encodeSize); outbuff.writeUint32(encodeSize); } - atUint8* ptrStart = (atUint8*)src; - atUint8* ptrEnd = (atUint8*)(src + srcLength); + const atUint8* ptrStart = src; + const atUint8* ptrEnd = src + srcLength; // At most their will be two bytes written if the bytes can be compressed. So if all bytes in the block can be // compressed it would take blockSize*2 bytes - atUint8* compressedBytes = new atUint8[m_blockSize * 2]; // Holds the compressed bytes yet to be written - atUint8 maxTwoByteMatch = 0xF + 1; - atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1 - atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch; - atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1 - atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch; + // Holds the compressed bytes yet to be written + auto compressedBytes = std::unique_ptr(new atUint8[m_blockSize * 2]); + + const atUint8 maxTwoByteMatch = 0xF + 1; + const atUint8 minThreeByteMatch = maxTwoByteMatch + 1; // Minimum Three byte match is maximum TwoByte match + 1 + const atUint16 maxThreeByteMatch = 0xFF + minThreeByteMatch; + const atUint16 minFourByteMatch = maxThreeByteMatch + 1; // Minimum Four byte match is maximum Three Byte match + 1 + const atInt32 maxFourByteMatch = 0xFFFF + minFourByteMatch; /* Normaliazation Example: If MIN_MATCH is 3 then 3 gets mapped to 2 and 16 gets mapped to 15. @@ -57,14 +62,14 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt atUint8 blockSize = 0; // In Binary represents 1 if byte is compressed or 0 if not compressed // For example 01001000 means that the second and fifth byte in the blockSize from the left is compressed - atUint8* ptrBytes = compressedBytes; + atUint8* ptrBytes = compressedBytes.get(); for (atInt32 i = 0; i < m_blockSize; i++) { // length_offset searchResult=Search(filedata,ptrStart,ptrEnd); - LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); + const LZLengthOffset searchResult = m_lookupTable.search(ptrStart, src, ptrEnd); // If the number of bytes to be compressed is at least the size of the Minimum match - if (searchResult.length >= (atUint32)m_minMatch) { + if (searchResult.length >= static_cast(m_minMatch)) { // Gotta swap the bytes since system is wii is big endian and most computers are little endian if (searchResult.length <= maxTwoByteMatch) { @@ -79,10 +84,10 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt ((searchResult.offset - 1) & 0xFFF) // Bits 11-0 ); athena::utility::BigUint32(lenOff); - memcpy(ptrBytes, (atUint8*)&lenOff + 1, + memcpy(ptrBytes, reinterpret_cast(&lenOff) + 1, 3); // Make sure to copy the lower 24 bits. 0x12345678- This statement copies 0x123456 ptrBytes += 3; - } else if (searchResult.length <= (atUint32)maxFourByteMatch) { + } else if (searchResult.length <= static_cast(maxFourByteMatch)) { atUint32 lenOff = ((1 << 28) | // Bits 31-28 Flag to say that this is four bytes (((searchResult.length - minFourByteMatch) & 0xFFFF) << 12) | // Bits 28-12 ((searchResult.offset - 1) & 0xFFF) // Bits 11-0 @@ -97,83 +102,80 @@ atUint32 LZType11::compress(const atUint8* src, atUint8** dst, atUint32 srcLengt blockSize |= (1 << (7 - i)); // Stores which of the next 8 bytes is compressed // bit 1 for compress and bit 0 for not compressed - } else + } else { *ptrBytes++ = *ptrStart++; + } } outbuff.writeByte(blockSize); - outbuff.writeUBytes(compressedBytes, (atUint64)(ptrBytes - compressedBytes)); + outbuff.writeUBytes(compressedBytes.get(), static_cast(ptrBytes - compressedBytes.get())); } - delete[] compressedBytes; - compressedBytes = nullptr; - // Add zeros until the file is a multiple of 4 - while ((outbuff.position() % 4) != 0) + while ((outbuff.position() % 4) != 0) { outbuff.writeByte(0); + } *dst = outbuff.data(); - return (atUint32)outbuff.length(); + return static_cast(outbuff.length()); } atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLength) { - if (*(atUint8*)(src) != 0x11) + if (*src != 0x11) { return 0; + } - atUint32 uncompressedLen = *(atUint32*)(src); + atUint32 uncompressedLen; + std::memcpy(&uncompressedLen, src, sizeof(uncompressedLen)); athena::utility::LittleUint32(uncompressedLen); // The compressed file has the filesize encoded in little endian uncompressedLen = uncompressedLen >> 8; // First byte is the encode flag atUint32 currentOffset = 4; - if (uncompressedLen == - 0) // If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes - { - atUint32 filesize = *(atUint32*)(src + 4); + // If the filesize var is zero then the true filesize is over 14MB and must be read in from the next 4 bytes + if (uncompressedLen == 0) { + atUint32 filesize; + std::memcpy(&filesize, src + 4, sizeof(filesize)); filesize = athena::utility::LittleUint32(filesize); currentOffset += 4; } - atUint8* uncompressedData = new atUint8[uncompressedLen]; - atUint8* outputPtr = uncompressedData; - atUint8* outputEndPtr = uncompressedData + uncompressedLen; - atUint8* inputPtr = (atUint8*)src + currentOffset; - atUint8* inputEndPtr = (atUint8*)src + srcLength; + auto uncompressedData = std::unique_ptr(new atUint8[uncompressedLen]); + atUint8* outputPtr = uncompressedData.get(); + atUint8* outputEndPtr = uncompressedData.get() + uncompressedLen; + const atUint8* inputPtr = src + currentOffset; + const atUint8* inputEndPtr = src + srcLength; LZLengthOffset decoding; - atUint8 maxTwoByteMatch = 0xF + 1; - atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes - atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm; - atUint16 fourByteDenorm = maxThreeByteMatch + 1; + const atUint8 maxTwoByteMatch = 0xF + 1; + const atUint8 threeByteDenorm = maxTwoByteMatch + 1; // Amount to add to length when compression is 3 bytes + const atUint16 maxThreeByteMatch = 0xFF + threeByteDenorm; + const atUint16 fourByteDenorm = maxThreeByteMatch + 1; while (inputPtr < inputEndPtr && outputPtr < outputEndPtr) { - - atUint8 isCompressed = *inputPtr++; + const atUint8 isCompressed = *inputPtr++; for (atInt32 i = 0; i < m_blockSize; i++) { // Checks to see if the next byte is compressed by looking // at its binary representation - E.g 10010000 // This says that the first extracted byte and the four extracted byte is compressed if ((isCompressed >> (7 - i)) & 0x1) { - atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits + const atUint8 metaDataSize = *inputPtr >> 4; // Look at the top 4 bits - if (metaDataSize >= 2) // Two Bytes of Length/Offset MetaData - { + if (metaDataSize >= 2) { // Two Bytes of Length/Offset MetaData atUint16 lenOff = 0; memcpy(&lenOff, inputPtr, 2); inputPtr += 2; athena::utility::BigUint16(lenOff); decoding.length = (lenOff >> 12) + 1; decoding.offset = (lenOff & 0xFFF) + 1; - } else if (metaDataSize == 0) // Three Bytes of Length/Offset MetaData - { + } else if (metaDataSize == 0) { // Three Bytes of Length/Offset MetaData atUint32 lenOff = 0; - memcpy((atUint8*)&lenOff + 1, inputPtr, 3); + memcpy(reinterpret_cast(&lenOff) + 1, inputPtr, 3); inputPtr += 3; athena::utility::BigUint32(lenOff); decoding.length = (lenOff >> 12) + threeByteDenorm; decoding.offset = (lenOff & 0xFFF) + 1; - } else if (metaDataSize == 1) // Four Bytes of Length/Offset MetaData - { + } else if (metaDataSize == 1) { // Four Bytes of Length/Offset MetaData atUint32 lenOff = 0; memcpy(&lenOff, inputPtr, 4); inputPtr += 4; @@ -182,30 +184,30 @@ atUint32 LZType11::decompress(const atUint8* src, atUint8** dst, atUint32 srcLen decoding.length = ((lenOff >> 12) & 0xFFFF) + fourByteDenorm; // Gets rid of the Four byte flag decoding.offset = (lenOff & 0xFFF) + 1; } else { - delete[] uncompressedData; - uncompressedData = nullptr; return 0; } - if ((outputPtr - decoding.offset) < uncompressedData) // If the offset to look for uncompressed is passed the - // current uncompresed data then the data is not compressed - { - delete[] uncompressedData; + // If the offset to look for uncompressed is passed the + // current uncompresed data then the data is not compressed + if ((outputPtr - decoding.offset) < uncompressedData.get()) { return 0; } - for (atUint32 j = 0; j < decoding.length; ++j) + for (size_t j = 0; j < decoding.length; ++j) { outputPtr[j] = (outputPtr - decoding.offset)[j]; + } outputPtr += decoding.length; - } else + } else { *outputPtr++ = *inputPtr++; + } - if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) + if (!(inputPtr < inputEndPtr && outputPtr < outputEndPtr)) { break; + } } } - *dst = uncompressedData; + *dst = uncompressedData.release(); return uncompressedLen; } diff --git a/src/athena/Compression.cpp b/src/athena/Compression.cpp index 2f7ac54..4ede938 100644 --- a/src/athena/Compression.cpp +++ b/src/athena/Compression.cpp @@ -303,8 +303,9 @@ atUint32 simpleEnc(const atUint8* src, atInt32 size, atInt32 pos, atUint32* pMat } atUint32 decompressLZ77(const atUint8* src, atUint32 srcLen, atUint8** dst) { - if (*(atUint8*)src == 0x11) + if (*src == 0x11) { return LZType11().decompress(src, dst, srcLen); + } return LZType10(2).decompress(src, dst, srcLen); }