Load_C64() unpack more formats

This commit is contained in:
Thomas Bernard 2018-11-23 01:10:01 +01:00
parent 105b5f7ffe
commit b418c27aa5
No known key found for this signature in database
GPG Key ID: 0FF11B67A5C0863C

View File

@ -2243,6 +2243,8 @@ static const char *c64_format_names[] = {
"FLI"
};
static long C64_unpack_doodle(byte ** file_buffer, long file_size);
/**
* Test for a C64 picture file
*
@ -2340,6 +2342,7 @@ void Test_C64(T_IO_Context * context, FILE * file)
}
File_error = 0;
break;
case 17218:
case 17409:
// $3c00 => FLI-designer v1.1
// ? $3ff0 => FLI designer 2 ?
@ -2349,12 +2352,33 @@ void Test_C64(T_IO_Context * context, FILE * file)
// $3b00 => FLI Graph 2
case 17665:
// $3b00 => FLI editor
case 17666:
// $3b00 => FLI Graph
case 10277: // multicolor CDU-Paint + loadaddr
// $7EEF
File_error = 0;
break;
default: // then we don't know for now.
File_error = 1;
if (load_addr == 0x6000 || load_addr == 0x5c00)
{
long unpacked_size;
byte * buffer = malloc(file_size);
if (buffer == NULL)
return;
fseek(file, SEEK_SET, 0);
if (!Read_bytes(file, buffer, file_size))
return;
unpacked_size = C64_unpack_doodle(&buffer, file_size);
free(buffer);
switch (unpacked_size)
{
case 9024: // Doodle hi color
case 9216:
case 10001: // Koala painter 2
case 10070:
File_error = 0;
}
}
}
}
@ -2549,6 +2573,93 @@ void Load_C64_fli(T_IO_Context *context, byte *bitmap, byte *screen_ram, byte *c
}
}
/**
* Count the length of the unpacked data
*
* RLE encoding is either ESCAPE CODE, COUNT, VALUE
* or ESCAPE CODE, VALUE, COUNT
*
* @param buffer the packed data
* @param input_size the packed data byte count
* @param RLE_code the escape code
* @param order 0 for ESCAPE, COUNT, VALUE, 1 for ESCAPE, VALUE, COUNT
* @return the unpacked data byte count
*/
static long C64_unpack_get_length(const byte * buffer, long input_size, byte RLE_code, int order)
{
const byte * end;
long unpacked_size = 0;
end = buffer + input_size;
while(buffer < end)
{
if (*buffer == RLE_code)
{
if (order)
{ // ESCAPE, VALUE, COUNT
buffer += 2; // skip value
unpacked_size += *buffer;
}
else
{ // ESCAPE, COUNT, VALUE
buffer++;
if (*buffer == 0)
break;
unpacked_size += *buffer++;
}
}
else
unpacked_size++;
buffer++;
}
return unpacked_size;
}
/**
* unpack RLE packed data
*
* RLE encoding is either ESCAPE CODE, COUNT, VALUE
* or ESCAPE CODE, VALUE, COUNT
*
* @param unpacked buffer to received unpacked data
* @param buffer the packed data
* @param input_size the packed data byte count
* @param RLE_code the escape code
* @param order 0 for ESCAPE, COUNT, VALUE, 1 for ESCAPE, VALUE, COUNT
*/
static void C64_unpack(byte * unpacked, const byte * buffer, long input_size, byte RLE_code, int order)
{
const byte * end;
end = buffer + input_size;
while(buffer < end)
{
if (*buffer == RLE_code)
{
byte count;
byte value;
buffer++;
if (order)
{ // ESCAPE, VALUE, COUNT
value = *buffer++;
count = *buffer;
}
else
{ // ESCAPE, COUNT, VALUE
count = *buffer++;
value = *buffer;
}
if (count == 0)
break;
while (count-- > 0)
*unpacked++ = value;
}
else
*unpacked++ = *buffer;
buffer++;
}
}
/**
* Unpack the Amica Paint RLE packing
*
@ -2561,50 +2672,20 @@ void Load_C64_fli(T_IO_Context *context, byte *bitmap, byte *screen_ram, byte *c
*/
static long C64_unpack_amica(byte ** file_buffer, long file_size)
{
long unpacked_size = 0;
long unpacked_size;
byte * unpacked_buffer;
byte * current, * end;
byte * unpacked;
const byte RLE_code = 0xC2;
if (file_size <= 16 || file_buffer == NULL || *file_buffer == NULL)
return -1;
// First pass to know unpacked size
end = *file_buffer + file_size;
for (current = *file_buffer + 2; current < end; current++)
{
if (*current == RLE_code)
{
current++;
if (*current == 0)
break;
unpacked_size += *current++;
}
else
unpacked_size++;
}
unpacked_size = C64_unpack_get_length(*file_buffer + 2, file_size - 2, RLE_code, 0);
GFX2_Log(GFX2_DEBUG, "C64_unpack_amica() unpacked_size=%ld\n", unpacked_size);
// 2nd pass to unpack
unpacked_buffer = malloc(unpacked_size);
if (unpacked_buffer == NULL)
return -1;
unpacked = unpacked_buffer;
C64_unpack(unpacked_buffer, *file_buffer + 2, file_size - 2, RLE_code, 0);
for (current = *file_buffer + 2; current < end; current++)
{
if (*current == RLE_code)
{
byte count;
current++;
count = *current++;
if (count == 0)
break;
while (count-- > 0)
*unpacked++ = *current;
}
else
*unpacked++ = *current;
}
free(*file_buffer);
*file_buffer = unpacked_buffer;
return unpacked_size;
@ -2623,49 +2704,48 @@ static long C64_unpack_amica(byte ** file_buffer, long file_size)
*/
static long C64_unpack_draz(byte ** file_buffer, long file_size)
{
long unpacked_size = 0;
long unpacked_size;
byte * unpacked_buffer;
byte * current, * end;
byte * unpacked;
byte RLE_code;
if (file_size <= 16 || file_buffer == NULL || *file_buffer == NULL)
return -1;
RLE_code = (*file_buffer)[15];
GFX2_Log(GFX2_DEBUG, "C64_unpack_draz() \"%.13s\" RLE code=$%02X RLE data length=%ld\n",
*file_buffer + 2, RLE_code, file_size - 16);
// First pass to know unpacked size
end = *file_buffer + file_size;
for (current = *file_buffer + 16; current < end; current++)
{
if (*current == RLE_code)
{
current++;
unpacked_size += *current++;
}
else
unpacked_size++;
}
GFX2_Log(GFX2_DEBUG, "C64_unpack_draz() unpacked_size=%ld\n", unpacked_size);
unpacked_size = C64_unpack_get_length(*file_buffer + 16, file_size - 16, RLE_code, 0);
GFX2_Log(GFX2_DEBUG, "C64_unpack_draz() \"%.13s\" RLE code=$%02X RLE data length=%ld unpacked_size=%ld\n",
*file_buffer + 2, RLE_code, file_size - 16, unpacked_size);
// 2nd pass to unpack
unpacked_buffer = malloc(unpacked_size);
if (unpacked_buffer == NULL)
return -1;
unpacked = unpacked_buffer;
C64_unpack(unpacked_buffer, *file_buffer + 16, file_size - 16, RLE_code, 0);
free(*file_buffer);
*file_buffer = unpacked_buffer;
return unpacked_size;
}
for (current = *file_buffer + 16; current < end; current++)
{
if (*current == RLE_code)
{
byte count;
current++;
count = *current++;
while (count-- > 0)
*unpacked++ = *current;
}
else
*unpacked++ = *current;
}
/**
* Unpack doodle/koala painter 2 data
*
* @return the unpacked data size or -1 in case of error
*/
static long C64_unpack_doodle(byte ** file_buffer, long file_size)
{
long unpacked_size;
byte * unpacked_buffer;
const byte RLE_code = 0xFE;
if (file_size <= 16 || file_buffer == NULL || *file_buffer == NULL)
return -1;
// First pass to know unpacked size
unpacked_size = C64_unpack_get_length(*file_buffer + 2, file_size - 2, RLE_code, 1);
GFX2_Log(GFX2_DEBUG, "C64_unpack_doodle() unpacked_size=%ld\n", unpacked_size);
// 2nd pass to unpack
unpacked_buffer = malloc(unpacked_size);
if (unpacked_buffer == NULL)
return -1;
C64_unpack(unpacked_buffer, *file_buffer + 2, file_size - 2, RLE_code, 1);
free(*file_buffer);
*file_buffer = unpacked_buffer;
return unpacked_size;
@ -2728,6 +2808,8 @@ void Load_C64(T_IO_Context * context)
file_size = C64_unpack_draz(&file_buffer, file_size);
else if(load_addr == 0x4000 && file_buffer[file_size-2] == 0xC2 && file_buffer[file_size-1] == 0)
file_size = C64_unpack_amica(&file_buffer, file_size);
else if (file_size < 8000 && (load_addr == 0x6000 || load_addr == 0x5c00))
file_size = C64_unpack_doodle(&file_buffer, file_size);
switch (file_size)
{
@ -2767,6 +2849,14 @@ void Load_C64(T_IO_Context * context)
screen_ram=file_buffer+8002; // length: 1000
break;
case 9024: // Doodle (unpacked from .jj)
case 9216:
hasLoadAddr=0;
loadFormat=F_hires;
screen_ram=file_buffer; // length: 1000 (+24 padding)
bitmap=file_buffer+1024; // length: 8000
break;
case 9218: // Doodle (.dd)
hasLoadAddr=1;
loadFormat=F_hires;
@ -2789,6 +2879,7 @@ void Load_C64(T_IO_Context * context)
break;
case 10001: // multicolor
case 10070: // unpacked file.
hasLoadAddr=0;
loadFormat=F_multi;
bitmap=file_buffer+0; // length: 8000
@ -2928,6 +3019,7 @@ void Load_C64(T_IO_Context * context)
bitmap=file_buffer+9474; // length: 8000
break;
case 17218:
case 17409: // FLI-Designer v1.1 (+loadaddr)
case 17410: // => FLI MATIC (background at 2+1024+8192+8000+65 ?)
hasLoadAddr=1;
@ -2938,6 +3030,15 @@ void Load_C64(T_IO_Context * context)
bitmap=file_buffer+8192+1024+2; // length: 8000
break;
case 17666: // FLI Graph
hasLoadAddr=1;
loadFormat=F_fli;
background=file_buffer+2;
color_ram=file_buffer+256+2; // length: 1000 (+ padding 24)
screen_ram=file_buffer+1024+256+2; // length: 8192
bitmap=file_buffer+8192+1024+256+2; // length: 8000
break;
case 17665: // FLI Editor
hasLoadAddr=1;
loadFormat=F_fli;