Add support for loading the C64 pixcen .GPX format

Pixcen is a C64 picture editor under MS Windows :
http://hammarberg.github.io/pixcen/
This commit is contained in:
Thomas Bernard 2019-04-27 01:57:47 +02:00
parent 653593ba66
commit 682e1a77ad
No known key found for this signature in database
GPG Key ID: 0FF11B67A5C0863C
4 changed files with 187 additions and 0 deletions

View File

@ -141,6 +141,7 @@ enum FILE_FORMATS
FORMAT_CEL, ///< Atari ST Cyber Paint Cell
FORMAT_NEO, ///< Atari ST NeoChrome
FORMAT_C64, ///< Several C64 formats : Koala, FLI, BML, etc.
FORMAT_GPX, ///< pixcen C64 format : .gpx
FORMAT_KCF, ///< KiSS Color File
FORMAT_PAL, ///< raw 6bit palette or Jasc Paint Shop Pro palette
FORMAT_GPL, ///< Gimp palette

View File

@ -111,6 +111,10 @@ void Test_C64(T_IO_Context *, FILE *);
void Load_C64(T_IO_Context *);
void Save_C64(T_IO_Context *);
// -- GPX (pixcen C64)
void Test_GPX(T_IO_Context *, FILE *);
void Load_GPX(T_IO_Context *);
// -- SCR (Amstrad CPC)
void Test_SCR(T_IO_Context *, FILE *);
void Load_SCR(T_IO_Context *);

View File

@ -115,6 +115,7 @@ const T_Format File_formats[] = {
"gif;png;bmp;2bp;pcx;pkm;iff;lbm;ilbm;sham;ham;ham6;ham8;acbm;pic;anim;img;sci;scq;scf;scn;sco;cel;"
"pi1;pc1;pi2;pc2;pi3;pc3;neo;"
"c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;bml;cdu;prg;pmg;rpm;"
"gpx;"
"cpc;scr;win;"
"hgr;dhgr;"
"tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin;map"},
@ -141,6 +142,7 @@ const T_Format File_formats[] = {
{FORMAT_GPL, " gpl", Test_GPL, Load_GPL, Save_GPL, 1, 0, 0, "gpl", "gpl"},
{FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 1, "c64",
"c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;bml;cdu;prg;pmg;rpm"},
{FORMAT_GPX, " gpx", Test_GPX, Load_GPX, NULL, 0, 0, 0, "gpx", "gpx"},
{FORMAT_SCR, " cpc", Test_SCR, Load_SCR, Save_SCR, 0, 0, 0, "scr", "cpc;scr;win"},
{FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"},
{FORMAT_PPH, " pph", Test_PPH, Load_PPH, Save_PPH, 0, 0, 1, "pph", "pph"},

View File

@ -38,6 +38,8 @@
#endif
#endif
#include <zlib.h>
#include "engine.h"
#include "errors.h"
#include "global.h"
@ -4034,6 +4036,184 @@ void Save_C64(T_IO_Context * context)
}
/////////////////////////// pixcen *.GPX ///////////////////////////
void Test_GPX(T_IO_Context * context, FILE * file)
{
byte header[2];
(void)context;
// check for a Zlib compressed stream
File_error = 1;
if (!Read_bytes(file, header, 2))
return;
if ((header[0] & 0x0f) != 8)
return;
if (((header[0] << 8) + header[1]) % 31)
return;
File_error = 0;
}
void Load_GPX(T_IO_Context * context)
{
FILE * file;
unsigned long file_size;
byte * buffer;
File_error = 1;
file = Open_file_read(context);
if (file == NULL)
return;
file_size = File_length_file(file);
buffer = malloc(file_size);
if (buffer == NULL)
{
GFX2_Log(GFX2_ERROR, "Failed to allocate %lu bytes.\n", file_size);
fclose(file);
return;
}
if (Read_bytes(file, buffer, file_size))
{
byte * gpx = NULL;
unsigned long gpx_size = 0;
int r;
do
{
free(gpx);
gpx_size += 65536;
gpx = malloc(gpx_size);
if (gpx == NULL)
{
GFX2_Log(GFX2_ERROR, "Failed to allocate %lu bytes\n", gpx_size);
break;
}
r = uncompress(gpx, &gpx_size, buffer, file_size);
if (r != Z_BUF_ERROR && r != Z_OK)
GFX2_Log(GFX2_ERROR, "uncompress() failed with error %d: %s\n", r, zError(r));
}
while (r == Z_BUF_ERROR); // there was not enough room in the output buffer
if (r == Z_OK)
{
byte * p;
dword version, mode;
/*
mode :
0 BITMAP,
1 MC_BITMAP,
2 SPRITE,
3 MC_SPRITE,
4 CHAR,
5 MC_CHAR,
6 UNUSED1,
7 UNUSED2,
8 UNRESTRICTED,
9 W_UNRESTRICTED
*/
GFX2_Log(GFX2_DEBUG, "inflated %lu bytes to %lu\n", file_size, gpx_size);
#define READU32LE(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24)
version = READU32LE(gpx);
mode = READU32LE(gpx+4);
GFX2_Log(GFX2_DEBUG, "gpx version %u mode %u\n", version, mode);
snprintf(context->Comment, COMMENT_SIZE, "pixcen file version %u mode %u", version, mode);
if (version >= 4)
{
dword count;
const char * key;
word value[256];
int xsize = -1;
int ysize = -1;
int mapsize = -1;
int screensize = -1;
int colorsize = -1;
int backbuffers = -1;
count = READU32LE(gpx+8);
p = gpx + 12;
while (count--)
{
int i = 0;
int int_value = 0;
key = (const char *)p;
while (*p++);
for (;;)
{
value[i] = p[0] + (p[1] << 8);
p += 2;
if (value[i] == 0)
break;
int_value = int_value * 10 + (value[i] - '0');
i++;
}
GFX2_Log(GFX2_DEBUG, "%s=%d\n", key, int_value);
if (0 == strcmp(key, "xsize"))
xsize = int_value;
else if (0 == strcmp(key, "ysize"))
ysize = int_value;
else if (0 == strcmp(key, "mapsize"))
mapsize = int_value;
else if (0 == strcmp(key, "screensize"))
screensize = int_value;
else if (0 == strcmp(key, "colorsize"))
colorsize = int_value;
else if (0 == strcmp(key, "backbuffers"))
backbuffers = int_value;
}
//buffersize = 64 + (64 + mapsize + screensize + colorsize) * backbuffers;
p += 64; // 64 empty bytes ?
File_error = 0;
if (mode & 1)
context->Ratio = PIXEL_WIDE;
else
context->Ratio = PIXEL_SIMPLE;
Pre_load(context, xsize, ysize, file_size, FORMAT_GPX, context->Ratio, 4); // Do this as soon as you can
if (Config.Clear_palette)
memset(context->Palette,0, sizeof(T_Palette));
C64_set_palette(context->Palette);
context->Transparent_color=16;
//foreach backbuffer
if (backbuffers >= 1)
{
byte border, background;
//byte ext0, ext1, ext2;
byte * bitmap, * color, * screen;
//GFX2_LogHexDump(GFX2_DEBUG, "GPX ", p, 0, 64);
p += 47; // Extra bytes
//crippled = p;
p += 6;
//lock = p;
p += 6;
border = *p++;
background = *p++;
/*ext0 = *p++;
ext1 = *p++;
ext2 = *p++;*/
p += 3;
bitmap = p;
p += mapsize;
color = p;
p += colorsize;
screen = p;
p += screensize;
(void)border;
Load_C64_multi(context, bitmap, screen, color, background);
Set_image_mode(context, (mode & 1) ? IMAGE_MODE_C64MULTI : IMAGE_MODE_C64HIRES);
}
}
else
{
GFX2_Log(GFX2_ERROR, "GPX file version %d unsupported\n", version);
}
}
free(gpx);
}
free(buffer);
fclose(file);
}
/**
* Test for SCR file (Amstrad CPC)
*