mirror of
https://github.com/dwsJason/gsla.git
synced 2024-11-21 05:31:21 +00:00
GSLA encoder: WIP
This commit is contained in:
parent
89f6eb72e5
commit
7712398e0c
@ -114,17 +114,21 @@
|
||||
//
|
||||
// xxx_xxxx_xxxx_xxx is the number of bytes 1-16384 to follow (0 == 1 byte)
|
||||
//
|
||||
//%0xxx_xxxx_xxxx_xxx0 - Copy Bytes - straight copy bytes
|
||||
//%0xxx_xxxx_xxxx_xxx1 - Copy Bytes - straight copy bytes
|
||||
//%1xxx_xxxx_xxxx_xxx1 - Skip Bytes - skip bytes / move the cursor
|
||||
//%1xxx_xxxx_xxxx_xxx0 - Dictionary Copy Bytes from frame buffer to frame buffer
|
||||
//
|
||||
//%0000_0000_0000_0001- Source Skip -> Source pointer skips to next bank of data
|
||||
//%0000_0000_0000_0011- End of Frame - end of frame
|
||||
//%0000_0000_0000_0111- End of Animation / End of File / no more frames
|
||||
//%0000_0000_0000_0000- Source Skip -> Source pointer skips to next bank of data
|
||||
//%0000_0000_0000_0010- End of Frame - end of frame
|
||||
//%0000_0000_0000_0110- End of Animation / End of File / no more frames
|
||||
//
|
||||
//
|
||||
// other remaining codes, are reserved for future expansion
|
||||
|
||||
#include "gsla_file.h"
|
||||
|
||||
#include "lzb.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// If these structs are the wrong size, there's an issue with type sizes, and
|
||||
@ -143,6 +147,17 @@ GSLAFile::GSLAFile(const char *pFilePath)
|
||||
{
|
||||
LoadFromFile(pFilePath);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
GSLAFile::GSLAFile(int iWidthPixels, int iHeightPixels, int iFrameSizeBytes )
|
||||
: m_widthPixels(iWidthPixels)
|
||||
, m_heightPixels(iHeightPixels)
|
||||
, m_frameSize( iFrameSizeBytes )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
GSLAFile::~GSLAFile()
|
||||
@ -270,3 +285,177 @@ void GSLAFile::UnpackAnimation(GSLA_ANIM* pANIM, GSLA_Header* pHeader)
|
||||
//DecompressAnim(pTargetBuffer, pData);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Append a copy of raw image data into the class
|
||||
//
|
||||
void GSLA::AddImages( const std::vector<unsigned char*>& pFrameBytes )
|
||||
{
|
||||
for (int idx = 0; idx < pFrameBytes.size(); ++idx)
|
||||
{
|
||||
unsigned char* pPixels = new unsigned char[ m_frameSize ];
|
||||
memcpy(pPixels, pFrameBytes[ idx ], m_frameSize );
|
||||
m_pC1PixelMaps.push_back( pPixels );
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Compress / Serialize a new GSLA File
|
||||
//
|
||||
void GSLA::SaveToFile(const char* pFilenamePath)
|
||||
{
|
||||
// We're not going to even try encoding an empty file
|
||||
if (m_pC1PixelMaps.size() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// serialize to memory, then save that to a file
|
||||
std::vector<unsigned char> bytes;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Add the header
|
||||
bytes.resize( bytes.size() + sizeof(GSLA_Header) );
|
||||
|
||||
//$$JGA Rememeber, you have to set the pointer, before every access
|
||||
//$$JGA to the header data, because vector is going to change out
|
||||
//$$JGA memory addresses from underneath you
|
||||
GSLA_Header* pHeader = (GSLA_Header*)&bytes[0];
|
||||
|
||||
pHeader->G = 'G'; pHeader->S = 'S'; pHeader->L = 'L'; pHeader->A = 'A';
|
||||
|
||||
pHeader->file_length = 0; // Temp File Length
|
||||
|
||||
pHeader->version = 0x8000; // Version 0, with a Ring/Loop Frame at the end
|
||||
|
||||
pHeader->width = m_widthPixels >> 1;
|
||||
pHeader->height = m_widthHeight;
|
||||
|
||||
pHeader->frame_size = m_frameSize;
|
||||
|
||||
pHeader->frame_count = m_pC1PixelMaps.size() + 1; // + 1 for the ring frame
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Add the INITial frame chunk
|
||||
//
|
||||
// If there's only an initial frame, I guess this becomes a picture
|
||||
//
|
||||
|
||||
size_t init_offset = bytes.size();
|
||||
|
||||
// Add space for the INIT header
|
||||
bytes.resize( bytes.size() + sizeof(GSLA_INIT) );
|
||||
GSLA_INIT* pINIT = (GSLA_INIT*) &bytes[ init_offset ];
|
||||
|
||||
pINIT->I = 'I'; pINIT->N = 'N'; pINIT->i = 'I'; pINIT->T = 'T';
|
||||
pINIT->chunk_length = 0; // temp chunk size
|
||||
|
||||
// Need a place to put compressed data, in theory it could be bigger
|
||||
// than the original data, I think if that happens, the image was probably
|
||||
// designed to break this, anyway, give double theoretical max
|
||||
unsigned char* pWorkBuffer = new unsigned char[ m_frameSize * 2 ];
|
||||
|
||||
unsigned char* pInitialFrame = m_pC1PixelMaps[ 0 ];
|
||||
|
||||
// We're not worried about bank wrap on the first frame, and we don't have a pre-populated
|
||||
// dictionary
|
||||
int compressedSize = LZBA_Compress(pWorkBuffer, pInitialFrame, m_frameSize,
|
||||
pInitialFrame, pInitialFrame);
|
||||
|
||||
for (int compressedIndex = 0; compressedIndex < compressedSize; ++compressedIndex)
|
||||
{
|
||||
bytes.push_back(pWorkBuffer[ compressedIndex ]);
|
||||
}
|
||||
|
||||
// Insert EOF/ End of Animation Done opcode
|
||||
bytes.push_back( 0x06 );
|
||||
bytes.push_back( 0x00 );
|
||||
|
||||
|
||||
// Reset pointer to the pINIT (as the baggage may have shifted)
|
||||
pINIT = (GSLA_INIT*) &bytes[ init_offset ];
|
||||
pINIT->chunk_length = (unsigned int) (bytes.size() - init_offset);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Add the ANIMation frames chunk
|
||||
//
|
||||
// We always add this, because we always add a Ring/Loop frame, we always
|
||||
// end up with at least 2 frames
|
||||
//
|
||||
|
||||
size_t anim_offset = bytes.size();
|
||||
|
||||
// Add Space for the ANIM Header
|
||||
bytes.resize( bytes.size() + sizeof(GLSA_ANIM) );
|
||||
GSLA_ANIM* pANIM = (GSLA_ANIM*) &bytes[ anim_offset ];
|
||||
|
||||
pANIM->A = 'A'; pANIM->N = 'N'; pANIM->I ='I'; pANIM->M = 'M';
|
||||
pANIM->chunk_length = 0; // temporary chunk size
|
||||
|
||||
// Initialize the Canvas with the initial frame (we alread exported this)
|
||||
unsigned char *pCanvas = new unsigned char[ m_frameSize ];
|
||||
memcpy(pCanvas, m_pC1PixelMaps[0], m_frameSize);
|
||||
|
||||
memcpy(pCanvas, m_pC1PixelMaps[0], m_frameSize);
|
||||
|
||||
// Let's encode some frames buddy
|
||||
for (int frameIndex = 1; frameIndex < m_pC1PixelMaps.size(); ++frameIndex)
|
||||
{
|
||||
// I don't want random data in the bank gaps, so initialize this
|
||||
// buffer with zero
|
||||
memset(pWorkBuffer, 0, m_frameSize * 2);
|
||||
|
||||
int frameSize = LZBA_Compress(pWorkBuffer, m_pC1PixelMaps[ frameIndex],
|
||||
m_frameSize, pWorkBuffer-bytes.size(),
|
||||
pCanvas, m_frameSize );
|
||||
|
||||
for (int frameIndex = 0; frameIndex < frameSize; ++frameIndex)
|
||||
{
|
||||
bytes.push_back(pWorkBuffer[ frameIndex ]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the RING Frame
|
||||
memset(pWorkBuffer, 0, m_frameSize * 2);
|
||||
|
||||
int ringSize = LZBA_Compress(pWorkBuffer, m_pC1PixelMaps[ 0 ],
|
||||
m_frameSize, pWorkBuffer-bytes.size(),
|
||||
pCanvas, m_frameSize );
|
||||
|
||||
for (int ringIndex = 0; ringIndex < ringSize; ++ringIndex)
|
||||
{
|
||||
bytes.push_back(pWorkBuffer[ ringIndex ]);
|
||||
}
|
||||
|
||||
delete[] pCanvas; pCanvas = nullptr;
|
||||
|
||||
// Insert End of file/ End of Animation Done opcode
|
||||
bytes.push_back( 0x06 );
|
||||
bytes.push_back( 0x00 );
|
||||
|
||||
// Update the chunk length
|
||||
pFRAM = (FanFile_FRAM*)&bytes[ fram_offset ];
|
||||
pFRAM->chunk_length = (unsigned int) (bytes.size() - fram_offset);
|
||||
|
||||
// Update the header
|
||||
pHeader = (FanFile_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
|
||||
delete[] pWorkBuffer;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create the file and write it
|
||||
FILE* pFile = nullptr;
|
||||
errno_t err = fopen_s(&pFile, pFilenamePath, "wb");
|
||||
|
||||
if (0==err)
|
||||
{
|
||||
fwrite(&bytes[0], sizeof(unsigned char), bytes.size(), pFile);
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -112,9 +112,13 @@ class GSLAFile
|
||||
public:
|
||||
// Load in a C2 File
|
||||
GSLAFile(const char *pFilePath);
|
||||
|
||||
~GSLAFile();
|
||||
|
||||
// Creation
|
||||
GSLAFile(int iWidthPixels, int iHeightPixels, int iFrameSizeBytes);
|
||||
void AddImages( const std::vector<unsigned char*>& pFrameBytes );
|
||||
void SaveToFile(const char* pFilenamePath);
|
||||
|
||||
// Retrieval
|
||||
void LoadFromFile(const char* pFilePath);
|
||||
int GetFrameCount() { return (int)m_pC1PixelMaps.size(); }
|
||||
|
@ -574,4 +574,20 @@ void LZB_Decompress(unsigned char* pDest, unsigned char* pSource, int destSize)
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Encode a Frame in GSLA LZB Format
|
||||
//
|
||||
int LZBA_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize, unsigned char* pDataStart, int dictionarySize)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Decompress a Frame in the GSLA LZB Format
|
||||
//
|
||||
int LZBA_Decompress(unsigned char* pDest, unsigned char* pSource, unsigned char* pDataStart)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -11,5 +11,11 @@ int LZB_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize);
|
||||
int Old_LZB_Compress(unsigned char* pDest, unsigned char* pSource, int sourceSize);
|
||||
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_Decompress(unsigned char* pDest, unsigned char* pSource, unsigned char* pDataStart);
|
||||
|
||||
#endif // LZB_H
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
//
|
||||
// GSLA - GS LZB Animation Tool
|
||||
//
|
||||
// Look in gsla_file.cpp/h for more information about the file format
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
@ -7,16 +9,20 @@
|
||||
#include <string>
|
||||
|
||||
#include "c2_file.h"
|
||||
#include "gsla_file.h"
|
||||
|
||||
#include "lzb.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void helpText()
|
||||
{
|
||||
printf("GSLA - v0.0\n");
|
||||
printf("GSLA - v1.0\n");
|
||||
printf("--------------\n");
|
||||
printf("GS Lzb Animation Tool\n");
|
||||
printf("GS Lzb Animation Creation Tool\n");
|
||||
printf("\n");
|
||||
printf("\ngsla [options] <input_file> <outfile>\n");
|
||||
printf("\n\n There are no [options] yet\n");
|
||||
printf("Converts from C2 to GSLA\n");
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
@ -111,8 +117,25 @@ int main(int argc, char* argv[])
|
||||
helpText();
|
||||
}
|
||||
|
||||
if (pOutfilePath)
|
||||
{
|
||||
const std::vector<unsigned char*>& c1Datas = c2data.GetPixelMaps();
|
||||
|
||||
printf("Saving %s with %d frames\n", pOutfilePath, (int)c1Datas.size());
|
||||
|
||||
GSLAFile anim(320,200, 0x8000);
|
||||
|
||||
anim.AddImages(c1Datas);
|
||||
|
||||
anim.SaveToFile(pOutfilePath);
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
const std::vector<unsigned char*>& c1Datas = c2data.GetPixelMaps();
|
||||
|
||||
// LZB Testing Code, that I should probalby remove from this file
|
||||
// Just ignore this block of code
|
||||
#if 1
|
||||
unsigned char workbuffer[64*1024];
|
||||
for (int idx = 0; idx < frameCount; ++idx)
|
||||
@ -160,6 +183,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user