Load_SCR() iMPdraw v2 files

This commit is contained in:
Thomas Bernard 2019-12-02 23:48:32 +01:00
parent d97364a439
commit 5b264e876d
No known key found for this signature in database
GPG Key ID: 0FF11B67A5C0863C

View File

@ -4475,12 +4475,15 @@ void Load_SCR(T_IO_Context * context)
// temporary 32k buffer before actually decoding it.
FILE * pal_file, * file;
unsigned long real_file_size, file_size, amsdos_file_size = 0;
word addr;
word load_address = 0x4000; // default for OCP Art studio
word display_start = 0x4000;
byte mode, color_anim_flag, color_anim_delay;
byte pal_data[236]; // 12 palettes of 16+1 colors + 16 excluded inks + 16 protected inks
word width, height = 200;
byte bpp;
enum PIXEL_RATIO ratio;
byte * pixel_data;
byte * cpc_ram;
word x, y;
int i;
byte sig[3];
@ -4488,69 +4491,39 @@ void Load_SCR(T_IO_Context * context)
word win_width, win_height;
int is_win = 0;
int columns = 80;
int cpc_plus = 0;
const byte * cpc_plus_pal = NULL;
File_error = 1;
// requires the PAL file
// requires the PAL file for OCP Art studio files
pal_file = Open_file_read_with_alternate_ext(context, "pal");
if (pal_file == NULL)
return;
file_size = File_length_file(pal_file);
if (file_size == 239+128)
if (pal_file != NULL)
{
if (!CPC_check_AMSDOS(pal_file, NULL, NULL))
file_size = File_length_file(pal_file);
if (CPC_check_AMSDOS(pal_file, NULL, &file_size))
fseek(pal_file, 128, SEEK_SET); // right after AMSDOS header
else
fseek(pal_file, 0, SEEK_SET);
if (!Read_byte(pal_file, &mode) || !Read_byte(pal_file, &color_anim_flag)
|| !Read_byte(pal_file, &color_anim_delay) || !Read_bytes(pal_file, pal_data, 236))
{
GFX2_Log(GFX2_WARNING, "Load_SCR() failed to load .PAL file\n");
fclose(pal_file);
return;
}
fseek(pal_file, 128, SEEK_SET); // right after AMSDOS header
}
if (!Read_byte(pal_file, &mode) || !Read_byte(pal_file, &color_anim_flag)
|| !Read_byte(pal_file, &color_anim_delay) || !Read_bytes(pal_file, pal_data, 236))
{
GFX2_Log(GFX2_WARNING, "Load_SCR() failed to load .PAL file\n");
fclose(pal_file);
return;
GFX2_Log(GFX2_DEBUG, "Load_SCR() mode=%d color animation flag=%02X delay=%u\n",
mode, color_anim_flag, color_anim_delay);
}
fclose(pal_file);
GFX2_Log(GFX2_DEBUG, "Load_SCR() mode=%d color animation flag=%02X delay=%u\n",
mode, color_anim_flag, color_anim_delay);
switch (mode)
{
case 0:
width = 160;
bpp = 4;
ratio = PIXEL_WIDE;
break;
case 1:
width = 320;
bpp = 2;
ratio = PIXEL_SIMPLE;
break;
case 2:
width = 640;
bpp = 1;
ratio = PIXEL_TALL;
break;
default:
return; // unsupported
}
if (Config.Clear_palette)
memset(context->Palette,0,sizeof(T_Palette));
// Setup the palette (amstrad hardware palette)
CPC_set_HW_palette(context->Palette + 0x40);
// Set the palette for this picture
for (i = 0; i < 16; i++)
context->Palette[i] = context->Palette[pal_data[12*i]];
file = Open_file_read(context);
if (file == NULL)
return;
file_size = File_length_file(file);
real_file_size = file_size;
if (CPC_check_AMSDOS(file, NULL, &amsdos_file_size))
if (CPC_check_AMSDOS(file, &load_address, &amsdos_file_size))
{
display_start = load_address;
if (file_size < (amsdos_file_size + 128))
{
GFX2_Log(GFX2_ERROR, "Load_SCR() mismatch in file size. AMSDOS file size %lu, should be %lu\n", amsdos_file_size, file_size - 128);
@ -4565,12 +4538,6 @@ void Load_SCR(T_IO_Context * context)
else
fseek(file, 0, SEEK_SET);
if (file_size > 16384) // we don't support bigger files yet
{
fclose(file);
return;
}
if (!Read_bytes(file, sig, 3) || !Read_word_le(file, &block_length))
{
fclose(file);
@ -4578,13 +4545,13 @@ void Load_SCR(T_IO_Context * context)
}
fseek(file, -5, SEEK_CUR);
pixel_data = GFX2_malloc(16384);
memset(pixel_data, 0, 16384);
cpc_ram = GFX2_malloc(64*1024);
memset(cpc_ram, 0, 64*1024);
if (0 != memcmp(sig, "MJH", 3) || block_length > 16384)
{
// raw data
Read_bytes(file, pixel_data, file_size);
Read_bytes(file, cpc_ram + load_address, file_size);
i = file_size;
}
else
@ -4613,14 +4580,14 @@ void Load_SCR(T_IO_Context * context)
file_size -= 2;
do
{
pixel_data[i++] = value;
cpc_ram[load_address + i++] = value;
block_length--;
}
while(--repeat != 0);
}
else
{
pixel_data[i++] = code;
cpc_ram[load_address + i++] = code;
block_length--;
}
}
@ -4633,8 +4600,8 @@ void Load_SCR(T_IO_Context * context)
if (i > 5)
{
win_width = pixel_data[i-4] + (pixel_data[i-3] << 8); // in bits
win_height = pixel_data[i-2];
win_width = cpc_ram[load_address + i - 4] + (cpc_ram[load_address + i - 3] << 8); // in bits
win_height = cpc_ram[load_address + i - 2];
if (((win_width + 7) >> 3) * win_height + 5 == i) // that's a WIN file !
{
width = win_width >> (2 - mode);
@ -4643,36 +4610,177 @@ void Load_SCR(T_IO_Context * context)
columns = (win_width + 7) >> 3;
GFX2_Log(GFX2_DEBUG, ".WIN file detected len=%d (%d,%d) %dcols %02X %02X %02X %02X %02X\n",
i, width, height, columns,
pixel_data[i-5], pixel_data[i-4], pixel_data[i-3],
pixel_data[i-2], pixel_data[i-1]);
cpc_ram[load_address + i - 5], cpc_ram[load_address + i - 4], cpc_ram[load_address + i - 3],
cpc_ram[load_address + i - 2], cpc_ram[load_address + i - 1]);
}
else
{
///@todo guess the picture size, or ask the user
GFX2_Log(GFX2_DEBUG, ".SCR file. Data length %d\n", i);
// i <= 16384 && i >= 16336 => Standard resolution
if (i <= 16384 && i >= 16336)
if (load_address == 0x170)
{
// fichier iMPdraw v2
// http://orgams.wikidot.com/le-format-impdraw-v2
GFX2_Log(GFX2_DEBUG, "Detected \"%s\"\n", cpc_ram + load_address + 6);
mode = cpc_ram[load_address + 0x14] - 0x0e;
cpc_plus = cpc_ram[load_address + 0x3c];
GFX2_Log(GFX2_DEBUG, "Mode %d CPC %d\n", (int)mode, (int)cpc_plus);
for (addr = load_address + 0x1d; cpc_ram[addr] < 16; addr += 2)
{
GFX2_Log(GFX2_DEBUG, " R%d = &H%02x = %d\n", cpc_ram[addr], cpc_ram[addr+1], cpc_ram[addr+1]);
// see http://www.cpcwiki.eu/index.php/CRTC#The_6845_Registers
switch(cpc_ram[addr])
{
case 1:
columns = cpc_ram[addr+1] * 2;
break;
case 6:
height = cpc_ram[addr+1] * 8;
break;
case 12:
display_start = ((cpc_ram[addr+1] & 0x30) << 10) | ((cpc_ram[addr+1] & 0x03) << 9);
GFX2_Log(GFX2_DEBUG, " display_start &H%04X\n", display_start);
}
}
snprintf(context->Comment, COMMENT_SIZE, "%s mode %d %s",
cpc_ram + load_address + 7, mode, cpc_plus ? "CPC+" : "");
if (cpc_plus)
{
// palette at 0x801 (mode at 0x800 ?)
GFX2_LogHexDump(GFX2_DEBUG, "", cpc_ram, 0x800, 0x21);
cpc_plus_pal = cpc_ram + 0x801;
}
else
{
// palette at 0x7f00
GFX2_LogHexDump(GFX2_DEBUG, "", cpc_ram, 0x7f00, 16);
}
}
else if (load_address == 0x200)
{
int j;
// Standard resolution files have the 200 lines stored in block
// of 25 lines of 80 bytes = 2000 bytes every 2048 bytes.
// so there are 48 bytes unused every 2048 bytes...
for (j = 0; j < i; j += 2048)
GFX2_LogHexDump(GFX2_DEBUG, "SCR ", pixel_data, j+2000, 48);
static const byte CPC_Firmware_Colors[] = {
0x54, 0x44, 0x55, 0x5c, 0x58, 0x5d, 0x4c, 0x45, 0x4d,
0x56, 0x46, 0x57, 0x5e, 0x40, 0x5f, 0x4e, 0x47, 0x4f,
0x52, 0x42, 0x53, 0x5a, 0x59, 0x5b, 0x4a, 0x43, 0x4b };
GFX2_LogHexDump(GFX2_DEBUG, "", cpc_ram, 0x800, 0x100);
GFX2_LogHexDump(GFX2_DEBUG, "", cpc_ram, 0x8000, 0x100);
mode = cpc_ram[0x800];
for (j = 0; j < 16; j++)
pal_data[12*j] = CPC_Firmware_Colors[cpc_ram[0x801 + j]];
addr = 0x847;
if (cpc_ram[0x80bb] == 1)
addr = 0x80bb;
for (; cpc_ram[addr] > 0 && cpc_ram[addr] < 16; addr += 2)
{
GFX2_Log(GFX2_DEBUG, " R%d = &H%02x = %d\n", cpc_ram[addr], cpc_ram[addr+1], cpc_ram[addr+1]);
// see http://www.cpcwiki.eu/index.php/CRTC#The_6845_Registers
switch(cpc_ram[addr])
{
case 1:
columns = cpc_ram[addr+1] * 2;
break;
case 6:
height = cpc_ram[addr+1] * 8;
break;
case 12:
display_start = (display_start & 0x00ff) | ((cpc_ram[addr+1] & 0x30) << 10) | ((cpc_ram[addr+1] & 0x03) << 9);
break;
case 13:
display_start = (display_start & 0xff00) | cpc_ram[addr+1];
}
}
}
if (i >= 30000)
{
height = 272; columns = 96;
}
}
}
switch (mode)
{
case 0:
width = columns * 2;
bpp = 4;
ratio = PIXEL_WIDE;
break;
case 1:
width = columns * 4;
bpp = 2;
ratio = PIXEL_SIMPLE;
break;
case 2:
width = columns * 8;
bpp = 1;
ratio = PIXEL_TALL;
break;
default:
return; // unsupported
}
if (Config.Clear_palette)
memset(context->Palette,0,sizeof(T_Palette));
// Setup the palette (amstrad hardware palette)
CPC_set_HW_palette(context->Palette + 0x40);
// Set the palette for this picture
if (cpc_plus_pal)
{
for (i = 0; i < 16; i++)
{
context->Palette[i].G = cpc_plus_pal[i*2 + 1] * 0x11;
context->Palette[i].R = (cpc_plus_pal[i*2] >> 4) * 0x11;
context->Palette[i].B = (cpc_plus_pal[i*2] & 15) * 0x11;
}
}
else
{
for (i = 0; i < 16; i++)
context->Palette[i] = context->Palette[pal_data[12*i]];
}
File_error = 0;
Pre_load(context, width, height, real_file_size, FORMAT_SCR, ratio, bpp);
if (!is_win)
{
// Standard resolution files have the 200 lines stored in block
// of 25 lines of 80 bytes = 2000 bytes every 2048 bytes.
// so there are 48 bytes unused every 2048 bytes...
for (y = 0; y < 8; y++)
{
addr = display_start + 0x800 * y;
if (y > 0 && (display_start & 0x7ff))
GFX2_LogHexDump(GFX2_DEBUG, "SCR1 ", cpc_ram,
addr & 0xf800, display_start & 0x7ff);
addr += (height >> 3) * columns;
if ((height >> 3) * columns + (display_start & 0x7ff) <= 0x800)
GFX2_LogHexDump(GFX2_DEBUG, "SCR2 ", cpc_ram,
addr, 0x800 - ((height >> 3) * columns + (display_start & 0x7ff)));
else
GFX2_LogHexDump(GFX2_DEBUG, "SCR2 ", cpc_ram,
addr + 0x4000, 0x1000 - ((height >> 3) * columns + (display_start & 0x7ff)));
}
//for (j = 0; j < i; j += 2048)
// GFX2_LogHexDump(GFX2_DEBUG, "SCR ", cpc_ram, load_address + j + 2000, 48);
}
GFX2_Log(GFX2_DEBUG, " display_start &H%04X\n", display_start);
for (y = 0; y < height; y++)
{
const byte * line;
if (is_win)
line = pixel_data + y * columns;
addr = display_start + y * columns;
else
line = pixel_data + ((y & 7) << 11) + ((y >> 3) * columns);
{
addr = display_start + ((y >> 3) * columns);
addr = (addr & 0xC7FF) | ((addr & 0x800) << 3);
addr += (y & 7) << 11;
}
//GFX2_Log(GFX2_DEBUG, "line#%d &H%04X\n", y, addr);
line = cpc_ram + addr;
x = 0;
for (i = 0; i < columns; i++)
{
@ -4701,9 +4809,7 @@ void Load_SCR(T_IO_Context * context)
}
}
free(pixel_data);
File_error = 0;
free(cpc_ram);
}
/**