From bb916c15e251962e2d3c6d22a815e95514fe3bda Mon Sep 17 00:00:00 2001 From: "JASON-6700K\\jandersen" Date: Sat, 18 Jul 2020 16:41:01 -0400 Subject: [PATCH] GSLA: WIP --- source/gsla_file.cpp | 16 +++++----- source/lzb.cpp | 72 ++++++++++++++++++++++++++++++++++++++------ source/lzb.h | 4 ++- 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/source/gsla_file.cpp b/source/gsla_file.cpp index 159274c..3d9b8ce 100644 --- a/source/gsla_file.cpp +++ b/source/gsla_file.cpp @@ -289,7 +289,7 @@ void GSLAFile::UnpackAnimation(GSLA_ANIM* pANIM, GSLA_Header* pHeader) // // Append a copy of raw image data into the class // -void GSLA::AddImages( const std::vector& pFrameBytes ) +void GSLAFile::AddImages( const std::vector& pFrameBytes ) { for (int idx = 0; idx < pFrameBytes.size(); ++idx) { @@ -303,7 +303,7 @@ void GSLA::AddImages( const std::vector& pFrameBytes ) // // Compress / Serialize a new GSLA File // -void GSLA::SaveToFile(const char* pFilenamePath) +void GSLAFile::SaveToFile(const char* pFilenamePath) { // We're not going to even try encoding an empty file if (m_pC1PixelMaps.size() < 1) @@ -330,11 +330,11 @@ void GSLA::SaveToFile(const char* pFilenamePath) pHeader->version = 0x8000; // Version 0, with a Ring/Loop Frame at the end pHeader->width = m_widthPixels >> 1; - pHeader->height = m_widthHeight; + pHeader->height = m_heightPixels; pHeader->frame_size = m_frameSize; - pHeader->frame_count = m_pC1PixelMaps.size() + 1; // + 1 for the ring frame + pHeader->frame_count = (unsigned int)m_pC1PixelMaps.size() + 1; // + 1 for the ring frame //-------------------------------------------------------------------------- // Add the INITial frame chunk @@ -387,7 +387,7 @@ void GSLA::SaveToFile(const char* pFilenamePath) size_t anim_offset = bytes.size(); // Add Space for the ANIM Header - bytes.resize( bytes.size() + sizeof(GLSA_ANIM) ); + bytes.resize( bytes.size() + sizeof(GSLA_ANIM) ); GSLA_ANIM* pANIM = (GSLA_ANIM*) &bytes[ anim_offset ]; pANIM->A = 'A'; pANIM->N = 'N'; pANIM->I ='I'; pANIM->M = 'M'; @@ -435,11 +435,11 @@ void GSLA::SaveToFile(const char* pFilenamePath) bytes.push_back( 0x00 ); // Update the chunk length - pFRAM = (FanFile_FRAM*)&bytes[ fram_offset ]; - pFRAM->chunk_length = (unsigned int) (bytes.size() - fram_offset); + pANIM = (GSLA_ANIM*)&bytes[ anim_offset ]; + pANIM->chunk_length = (unsigned int) (bytes.size() - anim_offset); // Update the header - pHeader = (FanFile_Header*)&bytes[0]; // Required + pHeader = (GSLA_Header*)&bytes[0]; // Required pHeader->file_length = (unsigned int)bytes.size(); // get some valid data in there // Try not to leak memory, even though we probably do diff --git a/source/lzb.cpp b/source/lzb.cpp index 544aa2e..98caa18 100644 --- a/source/lzb.cpp +++ b/source/lzb.cpp @@ -575,18 +575,72 @@ void LZB_Decompress(unsigned char* pDest, unsigned char* pSource, int destSize) //------------------------------------------------------------------------------ // -// Encode a Frame in GSLA LZB Format +// Compress a Frame in the GSLA LZB Format // -int LZBA_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize, unsigned char* pDataStart, int dictionarySize) +int LZBA_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize, + unsigned char* pDataStart, unsigned char* pDictionary, + int dictionarySize) { -} +// printf("LZBA Compress %d bytes\n", sourceSize); + + unsigned char *pOriginalDest = pDest; + + DataString sourceData; + DataString dictionaryData; + DataString candidateData; + + // Source Data Stream - will compress until the size is zero + sourceData.pData = pSource; + sourceData.size = sourceSize; + + // Dictionary is the Frame Buffer + dictionaryData.pData = pDictionary; + dictionaryData.size = dictionarySize; + + // dumb last emit is a literal stuff + bool bLastEmitIsLiteral = false; + unsigned char* pLastLiteralDest = nullptr; + + while (sourceData.size > 0) + { + candidateData = LongestMatch(sourceData, dictionaryData); + + // If no match, or the match is too small, then take the next byte + // and emit as literal + if ((0 == candidateData.size)) // || (candidateData.size < 4)) + { + candidateData.size = 1; + candidateData.pData = sourceData.pData; + } + + // Adjust source stream + sourceData.pData += candidateData.size; + sourceData.size -= candidateData.size; + + dictionaryData.size = AddDictionary(candidateData, dictionaryData.size); + + if (candidateData.size > 3) + { + // Emit a dictionary reference + pDest += (int)EmitReference(pDest, (int)(candidateData.pData - dictionaryData.pData), candidateData); + bLastEmitIsLiteral = false; + } + else if (bLastEmitIsLiteral) + { + // Concatenate this literal onto the previous literal + pDest += ConcatLiteral(pLastLiteralDest, candidateData); + } + else + { + // Emit a new literal + pLastLiteralDest = pDest; + bLastEmitIsLiteral = true; + pDest += EmitLiteral(pDest, candidateData); + } + } + + return (int)(pDest - pOriginalDest); -//------------------------------------------------------------------------------ -// -// Decompress a Frame in the GSLA LZB Format -// -int LZBA_Decompress(unsigned char* pDest, unsigned char* pSource, unsigned char* pDataStart) -{ } //------------------------------------------------------------------------------ diff --git a/source/lzb.h b/source/lzb.h index d8d624e..964c985 100644 --- a/source/lzb.h +++ b/source/lzb.h @@ -14,7 +14,9 @@ void LZB_Decompress(unsigned char* pDest, unsigned char* pSource, int destSize); // // LZB Compressor that uses GSLA Opcodes while encoding // -int LZBA_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize, unsigned char* pDataStart, unsigned char* pDictionary, int dictionarySize=0); +int LZBA_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize, + unsigned char* pDataStart, unsigned char* pDictionary, + int dictionarySize=0); int LZBA_Decompress(unsigned char* pDest, unsigned char* pSource, unsigned char* pDataStart); #endif // LZB_H