diff options
| author | Elijah Thomas <42302100+elijah-thomas774@users.noreply.github.com> | 2024-10-01 20:24:25 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-01 20:24:25 -0400 |
| commit | dc221b4795f415c8500740dd33e2243f91d527a6 (patch) | |
| tree | 095409d798350dbc60e3f730437519767b11be2f /src/egg/core/eggStreamDecomp.cpp | |
| parent | 7ee2ac2d38bba2aa24fce7a72dd01dc07d509e72 (diff) | |
Misc Egg (#37)
* EGG: Archive, DvdFile, DvdRipper
* start eggStream
* FrmHeap and AssertHeap OK
* progress on EggController
* port in WPAD stuff
* update WPAD/WUD/KPAD/SC symbols
* eggController OK
* bytematch more CoreController virtual funcs
* eggDecomp/eggStreamDecomp Ok
* eggDvdRipper OK
* EGG gfx splits
* Finished Splitting EGG
* create egg Files
* eggDecomp.h -> eggStreamDecomp.h
* Revert some format changes
Diffstat (limited to 'src/egg/core/eggStreamDecomp.cpp')
| -rw-r--r-- | src/egg/core/eggStreamDecomp.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/egg/core/eggStreamDecomp.cpp b/src/egg/core/eggStreamDecomp.cpp new file mode 100644 index 00000000..1a9e2e5b --- /dev/null +++ b/src/egg/core/eggStreamDecomp.cpp @@ -0,0 +1,209 @@ +#include <egg/core/eggStreamDecomp.h> + +namespace EGG { + +// *********************************** LZ ********************************** // + +bool StreamDecompLZ::init(void *pDest, u32 maxCompressedSize) { + mpDest = pDest; + mMaxCompressedSize = maxCompressedSize; + CXInitUncompContextLZ(&mContext); + return true; +} + +bool StreamDecompLZ::decomp(const void *pSrc, u32 len) { + return CXReadUncompLZ(&mContext, pSrc, len) == CX_READ_OK; +} + +// *********************************** RL ********************************** // + +bool StreamDecompRL::init(void *pDest, u32 maxCompressedSize) { + mpDest = pDest; + mMaxCompressedSize = maxCompressedSize; + CXInitUncompContextRL(&mContext); + return true; +} + +bool StreamDecompRL::decomp(const void *pSrc, u32 len) { + return CXReadUncompRL(&mContext, pSrc, len) == CX_READ_OK; +} + +// *********************************** LH ********************************** // + +bool StreamDecompLH::init(void *pDest, u32 maxCompressedSize) { + mpDest = pDest; + mMaxCompressedSize = maxCompressedSize; + CXInitUncompContextLH(&mContext); + return true; +} + +bool StreamDecompLH::decomp(const void *pSrc, u32 len) { + return CXReadUncompLH(&mContext, pSrc, len) == CX_READ_OK; +} + +// ********************************** LRC ********************************** // + +bool StreamDecompLRC::init(void *pDest, u32 maxCompressedSize) { + mpDest = pDest; + mMaxCompressedSize = maxCompressedSize; + CXInitUncompContextLRC(&mContext); + return true; +} + +bool StreamDecompLRC::decomp(const void *pSrc, u32 len) { + return CXReadUncompLRC(&mContext, pSrc, len) == CX_READ_OK; +} + +// ********************************** SZS ********************************** // + +u32 UncompContextSZS::getUncompressedSize(const void *pSrc) { + const u8 *pData = (u8 *)pSrc; + return (pData[4] << 24) | (pData[5] << 16) | (pData[6] << 8) | (pData[7] << 0); +} + +void UncompContextSZS::initUncompContext(void *pDest) { + mpDest = (u8 *)pDest; + mUncompSize = 0; + mHeaderLen = 0x10; + mMaxUncompSize = 0; + mGroupHead = 0; + mSecondByte = 0; + mFirstByte = 0; + mState = 0; + mCopySrc = 0; +} + +s32 UncompContextSZS::readHeader(u8 *pHeaderLen, s32 *pUncompSize, const u8 *src, u32 maxCompLen, s32 maxUncompSize) { + s32 read_amount = 0; + while (*pHeaderLen != 0) { + (*pHeaderLen)--; + if (*pHeaderLen == 0xF) { + if (*src != (u8)'Y') { + return -1; + } + } else if (*pHeaderLen == 0xE) { + if (*src != (u8)'a') { + return -1; + } + } else if (*pHeaderLen == 0xD) { + if (*src != (u8)'z') { + return -1; + } + } else if (*pHeaderLen == 0xC) { + if (*src != (u8)'0') { + return -1; + } + } else if (*pHeaderLen >= 0x8) { + *pUncompSize |= *src << ((*pHeaderLen - 8) << 3); + } + + maxCompLen--; + src++; + read_amount++; + + if (maxCompLen == 0 && *pHeaderLen != 0) { + return read_amount; + } + } + if (maxUncompSize > 0 && maxUncompSize < *pUncompSize) { + *pUncompSize = maxUncompSize; + } + return read_amount; +} + +s32 UncompContextSZS::readUncomp(const void *pSrca, u32 len) { + const u8 *pSrc = static_cast<const u8 *>(pSrca); + if (mHeaderLen != 0) { + s32 read_len = readHeader(&mHeaderLen, &mUncompSize, pSrc, len, mMaxUncompSize); + pSrc += read_len; + len -= read_len; + + if (len == 0) { + if (mHeaderLen == 0) { + return mUncompSize; + } + return CX_READ_ERR_1; + } + } + + while (mUncompSize > 0) { + if (mState == 2) { + u32 num_bytes = *pSrc++ + 0x12; + len--; + if (num_bytes > mUncompSize) { + if (mMaxUncompSize == 0) { + return CX_READ_ERR_4; + } + num_bytes = (u16)mUncompSize; + } + mUncompSize -= num_bytes; + do { + *mpDest = *(mpDest - mCopySrc); + mpDest++; + } while (--num_bytes); + mState = 0; + } else if (mState == 1) { + len--; + u32 b1 = (mFirstByte << 8) | *pSrc++; + u32 num_bytes = b1 >> 12; + mCopySrc = (b1 & 0xFFF) + 1; + + if (num_bytes == 0) { + mState = 2; + } else { + num_bytes += 2; + if (num_bytes > mUncompSize) { + if (mMaxUncompSize == 0) { + return CX_READ_ERR_4; + } + num_bytes = (u16)mUncompSize; + } + mUncompSize -= num_bytes; + do { + *mpDest = *(mpDest - mCopySrc); + mpDest++; + } while (--num_bytes); + mState = 0; + } + } else { + if (mGroupHead == 0) { + len--; + mSecondByte = *pSrc++; + mGroupHead = 0x80; + if (len == 0) { + break; + } + } + if (mSecondByte & mGroupHead) { + *mpDest++ = *pSrc++; + mUncompSize--; + } else { + mFirstByte = *pSrc++; + mState = 1; + } + len--; + mGroupHead >>= 1; + } + if (len == 0) { + break; + } + } + + if (mUncompSize == 0 && mMaxUncompSize == 0 && len > 0x20) { + return CX_READ_ERR_3; + } + return mUncompSize; +} + +bool StreamDecompSZS::init(void *pDest, u32 maxCompressedSize) { + mpDest = pDest; + mMaxCompressedSize = maxCompressedSize; + mContext.initUncompContext(pDest); + return true; +} + +bool StreamDecompSZS::decomp(const void *pSrc, u32 len) { + return mContext.readUncomp((const u8 *)pSrc, len) == CX_READ_OK; +} + +} // namespace EGG |
