mirror of https://github.com/libAthena/athena.git
Merge pull request #59 from lioncash/cast
Compression/LZ77: Remove unnecessary pointer casts
This commit is contained in:
commit
8b0a010e78
|
@ -1,7 +1,12 @@
|
|||
#include "LZ77/LZLookupTable.hpp"
|
||||
#include "LZ77/LZType10.hpp"
|
||||
#include <athena/MemoryWriter.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "LZ77/LZLookupTable.hpp"
|
||||
|
||||
#include <athena/MemoryWriter.hpp>
|
||||
|
||||
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<atUint8[]>(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<atUint32>(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<atUint64>(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<atUint32>(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<atUint8[]>(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<atUint32>(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<atUint16>((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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
#include "LZ77/LZLookupTable.hpp"
|
||||
#include "LZ77/LZType11.hpp"
|
||||
#include <athena/MemoryWriter.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "LZ77/LZLookupTable.hpp"
|
||||
|
||||
#include <athena/MemoryWriter.hpp>
|
||||
|
||||
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<atUint8[]>(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<atUint32>(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<atUint8*>(&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<atUint32>(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<atUint64>(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<atUint32>(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<atUint8[]>(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<atUint8*>(&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
|
||||
// If the offset to look for uncompressed is passed the
|
||||
// current uncompresed data then the data is not compressed
|
||||
{
|
||||
delete[] uncompressedData;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue