mirror of
https://github.com/dwsJason/gsla.git
synced 2024-12-28 17:29:27 +00:00
144 lines
3.8 KiB
C++
144 lines
3.8 KiB
C++
|
//
|
||
|
// C++ Encoder/Decoder
|
||
|
// For C2, Paintworks Animation File Format
|
||
|
//
|
||
|
// File Format summary here from Brutal Deluxe
|
||
|
//
|
||
|
//0000.7fff first pic
|
||
|
//8000.8003 length of frame data - 8008
|
||
|
//8004.8007 timing
|
||
|
//8008.800b length of first frame data
|
||
|
//800c.800d first frame index
|
||
|
//800e.800f first frame data
|
||
|
//
|
||
|
// Offset 0, Value FFFF indicates the end of a frame
|
||
|
// 00 00 FF FF
|
||
|
//
|
||
|
#include "c2_file.h"
|
||
|
#include <stdio.h>
|
||
|
|
||
|
// If these structs are the wrong size, there's an issue with type sizes, and
|
||
|
// your compiler
|
||
|
static_assert(sizeof(C2File_Header)==0x800C, "C2File_Header is supposed to be 0x800C bytes");
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Load in a FanFile constructor
|
||
|
//
|
||
|
C2File::C2File(const char *pFilePath)
|
||
|
: m_widthPixels(320)
|
||
|
, m_heightPixels(200)
|
||
|
{
|
||
|
LoadFromFile(pFilePath);
|
||
|
}
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
C2File::~C2File()
|
||
|
{
|
||
|
// Free Up the memory
|
||
|
for (int idx = 0; idx < m_pC1PixelMaps.size(); ++idx)
|
||
|
{
|
||
|
delete[] m_pC1PixelMaps[idx];
|
||
|
m_pC1PixelMaps[ idx ] = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
void C2File::LoadFromFile(const char* pFilePath)
|
||
|
{
|
||
|
// Free Up the memory
|
||
|
for (int idx = 0; idx < m_pC1PixelMaps.size(); ++idx)
|
||
|
{
|
||
|
delete[] m_pC1PixelMaps[idx];
|
||
|
m_pC1PixelMaps[ idx ] = nullptr;
|
||
|
}
|
||
|
|
||
|
m_pC1PixelMaps.clear();
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
std::vector<unsigned char> bytes;
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Read the file into memory
|
||
|
FILE* pFile = nullptr;
|
||
|
errno_t err = fopen_s(&pFile, pFilePath, "rb");
|
||
|
|
||
|
if (0==err)
|
||
|
{
|
||
|
fseek(pFile, 0, SEEK_END);
|
||
|
size_t length = ftell(pFile); // get file size
|
||
|
fseek(pFile, 0, SEEK_SET);
|
||
|
|
||
|
bytes.resize( length ); // make sure buffer is large enough
|
||
|
|
||
|
// Read in the file
|
||
|
fread(&bytes[0], sizeof(unsigned char), bytes.size(), pFile);
|
||
|
fclose(pFile);
|
||
|
}
|
||
|
|
||
|
if (bytes.size())
|
||
|
{
|
||
|
size_t file_offset = 0; // File Cursor
|
||
|
|
||
|
// Bytes are in the buffer, so let's start looking at what we have
|
||
|
C2File_Header* pHeader = (C2File_Header*) &bytes[0];
|
||
|
|
||
|
// Early out if things don't look right
|
||
|
if (!pHeader->IsValid((unsigned int)bytes.size()))
|
||
|
return;
|
||
|
|
||
|
// Grab Initial Frame, and put it in the list
|
||
|
|
||
|
unsigned char* pFrame = new unsigned char[ 0x8000 ];
|
||
|
unsigned char* pCanvas = new unsigned char[ 0x8001 ]; // each frame changes the canvas
|
||
|
m_pC1PixelMaps.push_back(pFrame);
|
||
|
memcpy(pFrame, &bytes[0], 0x8000);
|
||
|
memcpy(pCanvas, &bytes[0], 0x8000);
|
||
|
|
||
|
//----------------------------------------------------------------------
|
||
|
// Process Frames as we encounter them
|
||
|
file_offset += sizeof(C2File_Header);
|
||
|
|
||
|
// Since we always pull 4 bytes
|
||
|
// let's keep us from pulling bytes outside our buffer
|
||
|
size_t eof_size = bytes.size() - 4;
|
||
|
|
||
|
// While we're not at the end of the file
|
||
|
unsigned short offset = 0;
|
||
|
//unsigned short prev_offset = 0;
|
||
|
unsigned short data = 0xFFFF;
|
||
|
while (file_offset <= eof_size)
|
||
|
{
|
||
|
//prev_offset = offset;
|
||
|
|
||
|
offset = (unsigned short)bytes[ file_offset++ ];
|
||
|
offset |= ((unsigned short)bytes[ file_offset++ ])<<8;
|
||
|
|
||
|
data = (unsigned short)bytes[ file_offset++ ];
|
||
|
data |= ((unsigned short)bytes[ file_offset++ ])<<8;
|
||
|
|
||
|
//if (((offset == 0)&&(data == 0xFFFF))||(offset < prev_offset))
|
||
|
if (0 == offset)
|
||
|
{
|
||
|
// End of Frame, capture a copy
|
||
|
pFrame = new unsigned char[ 0x8000 ];
|
||
|
memcpy(pFrame, pCanvas, 0x8000);
|
||
|
m_pC1PixelMaps.push_back(pFrame);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Apply Change to the Canvas
|
||
|
offset &= 0x7FFF; // force the offset into the Canvas
|
||
|
// probably should ignore offsets outside the canvas
|
||
|
pCanvas[ offset ] = data & 0xFF;
|
||
|
pCanvas[ offset+1 ] = (data >> 8) & 0xFF;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete[] pCanvas;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
|