Merge the "CPC Mode 5" branch to trunk.

Note this alsoincludes the "oldies" branch.

This has the following consequences :
[C64]
 * Loading and saving of screen-only, and color-only C64 picture is removed
 * Loading and saving in FLI mode is now possible
 * FLI constraint checker : tries to convert your image to FLI format, and put all the areas where it couldn't find a solution in a separate layer for you to fixup
 * This is currently accessible only with a shortcut. Menu will come next.
[Amstrad CPC]
 * Loading and saving of pictures in "Mode 5" is now possible. This custom format allows overscan mode 1 with rasters on 2 inks and split rasters on a 3rd one.
 * Mode 5 constraint enforcer : will ensure you can only draw pictures that are valid in mode 5. Each ink is seen as a layer.
 * This is accessible from a new button in the FX menu.
[Generic]
 * Added patch as I saw it : platform that don't support reporting "free space" on disk will not display anything (instead of "0 bytesÃ" as before)
 * For other platforms, when the free space is 0, we now have a disk full message.

The merge was not straight forward. I hope I didn't break too much things.


git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1810 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues
2011-06-19 20:15:22 +00:00
24 changed files with 1401 additions and 175 deletions

View File

@@ -6,7 +6,7 @@
Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 2007-2011 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 is free software; you can redistribute it and/or
@@ -40,6 +40,7 @@
#include "sdlscreen.h"
#include "struct.h"
#include "windows.h"
#include "oldies.h"
//////////////////////////////////// PAL ////////////////////////////////////
//
@@ -862,18 +863,18 @@ void Save_CEL(T_IO_Context * context)
short x_pos;
short y_pos;
byte last_byte=0;
dword Utilisation[256]; // Table d'utilisation de couleurs
dword color_usage[256]; // Table d'utilisation de couleurs
// On commence par compter l'utilisation de chaque couleurs
Count_used_colors(Utilisation);
Count_used_colors(color_usage);
File_error=0;
Get_full_filename(filename, context->File_name, context->File_directory);
if ((file=fopen(filename,"wb")))
{
// On regarde si des couleurs >16 sont utilisées dans l'image
for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++);
for (x_pos=16;((x_pos<256) && (!color_usage[x_pos]));x_pos++);
if (x_pos==256)
{
@@ -1180,10 +1181,10 @@ void Save_KCF(T_IO_Context * context)
int pal_index;
int color_index;
int index;
dword Utilisation[256]; // Table d'utilisation de couleurs
dword color_usage[256]; // Table d'utilisation de couleurs
// On commence par compter l'utilisation de chaque couleurs
Count_used_colors(Utilisation);
Count_used_colors(color_usage);
File_error=0;
Get_full_filename(filename, context->File_name, context->File_directory);
@@ -1192,7 +1193,7 @@ void Save_KCF(T_IO_Context * context)
// Sauvegarde de la palette
// On regarde si des couleurs >16 sont utilisées dans l'image
for (index=16;((index<256) && (!Utilisation[index]));index++);
for (index=16;((index<256) && (!color_usage[index]));index++);
if (index==256)
{
@@ -2069,6 +2070,7 @@ void Save_NEO(T_IO_Context * context)
}
//////////////////////////////////// C64 ////////////////////////////////////
void Test_C64(T_IO_Context * context)
{
FILE* file;
@@ -2084,14 +2086,17 @@ void Test_C64(T_IO_Context * context)
file_size = File_length_file(file);
switch (file_size)
{
case 1000: // screen or color
case 1002: // (screen or color) + loadaddr
// case 1000: // screen or color
// case 1002: // (screen or color) + loadaddr
case 8000: // raw bitmap
case 8002: // raw bitmap with loadaddr
case 9000: // bitmap + screen
case 9002: // bitmap + screen + loadaddr
case 9000: // bitmap + ScreenRAM
case 9002: // bitmap + ScreenRAM + loadaddr
case 10001: // multicolor
case 10003: // multicolor + loadaddr
case 17472: // FLI (BlackMail)
case 17474: // FLI (BlackMail) + loadaddr
case 10277: // multicolor CDU-Paint + loadaddr
File_error = 0;
break;
default: // then we don't know for now.
@@ -2105,7 +2110,7 @@ void Test_C64(T_IO_Context * context)
}
}
void Load_C64_hires(T_IO_Context *context, byte *bitmap, byte *colors)
void Load_C64_hires(T_IO_Context *context, byte *bitmap, byte *screen_ram)
{
int cx,cy,x,y,c[4],pixel,color;
@@ -2113,8 +2118,8 @@ void Load_C64_hires(T_IO_Context *context, byte *bitmap, byte *colors)
{
for(cx=0; cx<40; cx++)
{
c[0]=colors[cy*40+cx]&15;
c[1]=colors[cy*40+cx]>>4;
c[0]=screen_ram[cy*40+cx]&15;
c[1]=screen_ram[cy*40+cx]>>4;
for(y=0; y<8; y++)
{
pixel=bitmap[cy*320+cx*8+y];
@@ -2128,7 +2133,7 @@ void Load_C64_hires(T_IO_Context *context, byte *bitmap, byte *colors)
}
}
void Load_C64_multi(T_IO_Context *context, byte *bitmap, byte *colors, byte *nybble, byte background)
void Load_C64_multi(T_IO_Context *context, byte *bitmap, byte *screen_ram, byte *color_ram, byte background)
{
int cx,cy,x,y,c[4],pixel,color;
c[0]=background&15;
@@ -2136,9 +2141,9 @@ void Load_C64_multi(T_IO_Context *context, byte *bitmap, byte *colors, byte *nyb
{
for(cx=0; cx<40; cx++)
{
c[1]=colors[cy*40+cx]>>4;
c[2]=colors[cy*40+cx]&15;
c[3]=nybble[cy*40+cx]&15;
c[1]=screen_ram[cy*40+cx]>>4;
c[2]=screen_ram[cy*40+cx]&15;
c[3]=color_ram[cy*40+cx]&15;
for(y=0; y<8; y++)
{
@@ -2154,16 +2159,113 @@ void Load_C64_multi(T_IO_Context *context, byte *bitmap, byte *colors, byte *nyb
}
}
void Load_C64_fli(T_IO_Context *context, byte *bitmap, byte *screen_ram, byte *color_ram, byte *background)
{
// Thanks to MagerValp for complement of specifications.
//
// background : length: 200 (+ padding 56)
// These are the BG colors for lines 0-199 (top to bottom)
// Low nybble: the color.
// High nybble: garbage. ignore it.
// color_ram : length: 1000 (+ padding 24)
// Color RAM. Contains one color per 4x8 block.
// There are 40x25 such blocks, arranged from top left to bottom
// right, starting in right direction. For each block there is one byte.
// Low nybble: the color.
// High nybble: garbage. ignore it.
// screen_ram : length: 8192
// Screen RAMs. The s is important.
// This is actually 8 blocks of 1000 bytes, each separated by a filler of
// 24 bytes. Each byte contains data for a 4x1 pixel group, and a complete
// block will contain 40x25 of them. 40 is from left to right, and 25 is from
// top to bottom, spacing them 8 lines apart.
// The second block start at y=1, the third block starts at y=2, etc...
// Each byte contains 2 colors that *can* be used by the 4x1 pixel group:
// Low nybble: Color 1
// High nybble: Color 2
//
// bitmap : length: 8000
// This is the final structure that refers to all others. It describes
// 160x200 pixels linearly, from top left to bottom right, starting in
// right direction. For each pixel, two bits say which color is displayed
// (So 4 pixels are described by the same byte)
// 00 Use the BG color of the current line (background[y])
// 01 Use the Color 2 from the current 4x8 block of Screen RAM
// ((screen_ram[y/8][x/4] & 0xF0) >> 8)
// 10 Use the Color 1 from the current 4x8 block of Screen RAM
// (screen_ram[y/8][x/4] & 0x0F)
// 11 Use the color from Color RAM
// (color_ram[y/8][x/4] & 0x0F)
//
int cx,cy,x,y,c[4];
for(y=0; y<200; y++)
{
for(x=0; x<160; x++)
{
Set_pixel(context, x,y,background[y]);
}
}
Set_loading_layer(context, 1);
for(cy=0; cy<25; cy++)
{
for(cx=0; cx<40; cx++)
{
c[3]=color_ram[cy*40+cx]&15;
for(y=0; y<8; y++)
{
for(x=0; x<4; x++)
{
Set_pixel(context, cx*4+(3-x),cy*8+y,c[3]);
}
}
}
}
Set_loading_layer(context, 2);
for(cy=0; cy<25; cy++)
{
for(cx=0; cx<40; cx++)
{
c[3]=color_ram[cy*40+cx]&15;
for(y=0; y<8; y++)
{
int pixel=bitmap[cy*320+cx*8+y];
c[0]=background[cy*8+y]&15;
c[1]=screen_ram[y*1024+cy*40+cx]>>4;
c[2]=screen_ram[y*1024+cy*40+cx]&15;
for(x=0; x<4; x++)
{
int color=c[(pixel&3)];
pixel>>=2;
Set_pixel(context, cx*4+(3-x),cy*8+y,color);
}
}
}
}
Set_loading_layer(context, 3);
for(y=0; y<200; y++)
{
for(x=0; x<160; x++)
{
Set_pixel(context, x,y,16);
}
}
}
void Load_C64(T_IO_Context * context)
{
FILE* file;
char filename[MAX_PATH_CHARACTERS];
long file_size;
int i;
byte background,hasLoadAddr=0;
byte hasLoadAddr=0;
int loadFormat=0;
enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color};
const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"};
enum c64_format {F_hires,F_multi,F_bitmap,F_fli};
const char *c64_format_names[]={"Hires","Multicolor","Bitmap","FLI"};
// Palette from http://www.pepto.de/projects/colorvic/
byte pal[48]={
@@ -2184,118 +2286,194 @@ void Load_C64(T_IO_Context * context)
0x6C, 0x5E, 0xB5,
0x95, 0x95, 0x95};
byte bitmap[8000],colors[1000],nybble[1000];
byte *file_buffer;
byte *bitmap, *screen_ram, *color_ram=NULL, *background=NULL; // Only pointers to existing data
word width=320, height=200;
static byte dummy_screen[1000];
Get_full_filename(filename, context->File_name, context->File_directory);
file = fopen(filename,"rb");
if (file)
{
File_error=0;
file_size = File_length_file(file);
File_error=0;
file_size = File_length_file(file);
switch (file_size)
// Check for known file sizes
switch (file_size)
{
case 8000: // raw bitmap
case 8002: // raw bitmap with loadaddr
case 9000: // bitmap + ScreenRAM
case 9002: // bitmap + ScreenRAM + loadaddr
case 10001: // multicolor
case 10003: // multicolor + loadaddr
case 10277: // multicolor CDU-Paint + loadaddr
case 17472: // FLI (BlackMail)
case 17474: // FLI (BlackMail) + loadaddr
break;
default:
File_error = 1;
fclose(file);
return;
}
// Load entire file in memory
file_buffer=(byte *)malloc(file_size);
if (!file_buffer)
{
File_error = 1;
fclose(file);
return;
}
if (!Read_bytes(file,file_buffer,file_size))
{
File_error = 1;
free(file_buffer);
fclose(file);
return;
}
fclose(file);
memset(dummy_screen,1,1000);
switch (file_size)
{
case 1000: // screen or color
hasLoadAddr=0;
loadFormat=F_screen;
break;
case 1002: // (screen or color) + loadaddr
hasLoadAddr=1;
loadFormat=F_screen;
break;
case 8000: // raw bitmap
hasLoadAddr=0;
loadFormat=F_bitmap;
bitmap=file_buffer+0; // length: 8000
screen_ram=dummy_screen;
break;
case 8002: // raw bitmap with loadaddr
hasLoadAddr=1;
loadFormat=F_bitmap;
bitmap=file_buffer+2; // length: 8000
screen_ram=dummy_screen;
break;
case 9000: // bitmap + screen
case 9000: // bitmap + ScreenRAM
hasLoadAddr=0;
loadFormat=F_hires;
bitmap=file_buffer+0; // length: 8000
screen_ram=file_buffer+8000; // length: 1000
break;
case 9002: // bitmap + screen + loadaddr
case 9002: // bitmap + ScreenRAM + loadaddr
hasLoadAddr=1;
loadFormat=F_hires;
bitmap=file_buffer+2; // length: 8000
screen_ram=file_buffer+8002; // length: 1000
break;
case 10001: // multicolor
hasLoadAddr=0;
loadFormat=F_multi;
context->Ratio = PIXEL_WIDE;
bitmap=file_buffer+0; // length: 8000
screen_ram=file_buffer+8000; // length: 1000
color_ram=file_buffer+9000; // length: 1000
background=file_buffer+10000; // only 1
break;
case 10003: // multicolor + loadaddr
hasLoadAddr=1;
loadFormat=F_multi;
context->Ratio = PIXEL_WIDE;
bitmap=file_buffer+2; // length: 8000
screen_ram=file_buffer+8002; // length: 1000
color_ram=file_buffer+9002; // length: 1000
background=file_buffer+10002; // only 1
break;
default: // then we don't know what it is.
File_error = 1;
case 10277: // multicolor CDU-Paint + loadaddr
hasLoadAddr=1;
loadFormat=F_multi;
context->Ratio = PIXEL_WIDE;
// 273 bytes of display routine
bitmap=file_buffer+275; // length: 8000
screen_ram=file_buffer+8275; // length: 1000
color_ram=file_buffer+9275; // length: 1000
background=file_buffer+10275; // only 1
break;
case 17472: // FLI (BlackMail)
hasLoadAddr=0;
loadFormat=F_fli;
context->Ratio = PIXEL_WIDE;
background=file_buffer+0; // length: 200 (+ padding 56)
color_ram=file_buffer+256; // length: 1000 (+ padding 24)
screen_ram=file_buffer+1280; // length: 8192
bitmap=file_buffer+9472; // length: 8000
break;
case 17474: // FLI (BlackMail) + loadaddr
hasLoadAddr=1;
loadFormat=F_fli;
context->Ratio = PIXEL_WIDE;
background=file_buffer+2; // length: 200 (+ padding 56)
color_ram=file_buffer+258; // length: 1000 (+ padding 24)
screen_ram=file_buffer+1282; // length: 8192
bitmap=file_buffer+9474; // length: 8000
break;
default:
File_error = 1;
free(file_buffer);
return;
}
if (context->Ratio == PIXEL_WIDE)
width=160;
// Write detailed format in comment
strcpy(context->Comment, c64_format_names[loadFormat]);
if (hasLoadAddr)
{
// get load address
word load_addr;
load_addr = file_buffer[0] | (file_buffer[1] << 8);
sprintf(context->Comment+strlen(context->Comment),", load at $%04.4X",load_addr);
}
else
{
sprintf(context->Comment+strlen(context->Comment),", no addr");
}
Pre_load(context, width, height, file_size, FORMAT_C64, context->Ratio,0); // Do this as soon as you can
memcpy(context->Palette,pal,48); // this set the software palette for grafx2
// Transparent color "16" is a dark grey that is distinguishable
// from black, but darker than normal colors.
context->Palette[16].R=20;
context->Palette[16].G=20;
context->Palette[16].B=20;
Palette_loaded(context); // Always call it if you change the palette
if (file_size>9002)
width=160;
if (hasLoadAddr)
{
// get load address
Read_byte(file,&background);
Read_byte(file,&background);
sprintf(filename,"load at $%02x00",background);
}
else
{
sprintf(filename,"no addr");
}
if(file_size>9002)
{
context->Ratio = PIXEL_WIDE;
}
sprintf(context->Comment,"C64 %s, %s",
c64_format_names[loadFormat],filename);
Pre_load(context, width, height, file_size, FORMAT_C64, context->Ratio,0); // Do this as soon as you can
context->Width = width ;
context->Height = height;
context->Transparent_color=16;
Read_bytes(file,bitmap,8000);
if (file_size>8002)
Read_bytes(file,colors,1000);
else
if(loadFormat==F_fli)
{
for(i=0;i<1000;i++)
{
colors[i]=1;
}
Load_C64_fli(context,bitmap,screen_ram,color_ram,background);
}
if(width==160)
else
if(loadFormat==F_multi)
{
Read_bytes(file,nybble,1000);
Read_byte(file,&background);
Load_C64_multi(context,bitmap,colors,nybble,background);
Load_C64_multi(context,bitmap,screen_ram,color_ram,*background);
}
else
{
Load_C64_hires(context,bitmap,colors);
Load_C64_hires(context,bitmap,screen_ram);
}
File_error = 0;
fclose(file);
free(file_buffer);
}
else
File_error = 1;
@@ -2324,17 +2502,17 @@ int Save_C64_window(byte *saveWhat, byte *loadAddr)
};
Open_window(200,120,"c64 settings");
Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN);
Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE);
Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN); // 1
Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE); // 2
Print_in_window(13,18,"Data:",MC_Dark,MC_Light);
what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE,0);
what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE,0); // 3
Window_dropdown_clear_items(what);
for (i=0; i<sizeof(what_label)/sizeof(what_label[0]); i++)
Window_dropdown_add_item(what,i,what_label[i]);
Print_in_window(113,18,"Address:",MC_Dark,MC_Light);
addr=Window_set_dropdown_button(110,28,70,15,70,address_label[*loadAddr/32],1, 0, 1, LEFT_SIDE,0);
addr=Window_set_dropdown_button(110,28,70,15,70,address_label[*loadAddr/32],1, 0, 1, LEFT_SIDE,0); // 4
Window_dropdown_clear_items(addr);
for (i=0; i<sizeof(address_label)/sizeof(address_label[0]); i++)
Window_dropdown_add_item(addr,i,address_label[i]);
@@ -2371,10 +2549,10 @@ int Save_C64_hires(T_IO_Context *context, char *filename, byte saveWhat, byte lo
int cx,cy,x,y,c1,c2=0,i,pixel,bits,pos=0;
word numcolors;
dword cusage[256];
byte colors[1000],bitmap[8000];
byte screen_ram[1000],bitmap[8000];
FILE *file;
for(x=0;x<1000;x++)colors[x]=1; // init colormem to black/white
for(x=0;x<1000;x++)screen_ram[x]=1; // init colormem to black/white
for(cy=0; cy<25; cy++) // Character line, 25 lines
{
@@ -2408,7 +2586,7 @@ int Save_C64_hires(T_IO_Context *context, char *filename, byte saveWhat, byte lo
c1=i;
}
}
colors[cx+cy*40]=(c2<<4)|c1;
screen_ram[cx+cy*40]=(c2<<4)|c1;
for(y=0; y<8; y++)
{
@@ -2450,7 +2628,7 @@ int Save_C64_hires(T_IO_Context *context, char *filename, byte saveWhat, byte lo
if (saveWhat==0 || saveWhat==1)
Write_bytes(file,bitmap,8000);
if (saveWhat==0 || saveWhat==2)
Write_bytes(file,colors,1000);
Write_bytes(file,screen_ram,1000);
fclose(file);
return 0;
@@ -2461,13 +2639,13 @@ int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte lo
/*
BITS COLOR INFORMATION COMES FROM
00 Background color #0 (screen color)
01 Upper 4 bits of screen memory
10 Lower 4 bits of screen memory
11 Color nybble (nybble = 1/2 byte = 4 bits)
01 Upper 4 bits of Screen RAM
10 Lower 4 bits of Screen RAM
11 Color RAM nybble (nybble = 1/2 byte = 4 bits)
*/
int cx,cy,x,y,c[4]={0,0,0,0},color,lut[16],bits,pixel,pos=0;
byte bitmap[8000],screen[1000],nybble[1000];
byte bitmap[8000],screen_ram[1000],color_ram[1000];
word numcolors,count;
dword cusage[256];
byte i,background=0;
@@ -2517,9 +2695,9 @@ int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte lo
}
}
}
// add to screen and nybble
screen[cx+cy*40]=c[1]<<4|c[2];
nybble[cx+cy*40]=c[3];
// add to screen_ram and color_ram
screen_ram[cx+cy*40]=c[1]<<4|c[2];
color_ram[cx+cy*40]=c[3];
//printf("%x%x%x ",c[1],c[2],c[3]);
for(y=0;y<8;y++)
{
@@ -2563,10 +2741,10 @@ int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte lo
Write_bytes(file,bitmap,8000);
if (saveWhat==0 || saveWhat==2)
Write_bytes(file,screen,1000);
Write_bytes(file,screen_ram,1000);
if (saveWhat==0 || saveWhat==3)
Write_bytes(file,nybble,1000);
Write_bytes(file,color_ram,1000);
if (saveWhat==0)
Write_byte(file,background);
@@ -2576,6 +2754,55 @@ int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte lo
return 0;
}
int Save_C64_fli(char *filename, byte saveWhat, byte loadAddr)
{
FILE *file;
byte file_buffer[17474];
memset(file_buffer,0,sizeof(file_buffer));
if (C64_FLI(file_buffer+9474, file_buffer+1282, file_buffer+258, file_buffer+2))
{
File_error=1;
return 1;
}
file = fopen(filename,"wb");
if(!file)
{
Warning_message("File open failed");
File_error = 1;
return 1;
}
if (loadAddr)
{
file_buffer[0]=0;
file_buffer[1]=loadAddr;
Write_bytes(file,file_buffer,2);
}
if (saveWhat==0)
Write_bytes(file,file_buffer+2,256);
if (saveWhat==0 || saveWhat==3)
Write_bytes(file,file_buffer+258,1024);
if (saveWhat==0 || saveWhat==1)
Write_bytes(file,file_buffer+1282,8192);
if (saveWhat==0 || saveWhat==2)
Write_bytes(file,file_buffer+9474,8000);
fclose(file);
//printf("\nbg:%d\n",background);
return 0;
}
void Save_C64(T_IO_Context * context)
{
char filename[MAX_PATH_CHARACTERS];
@@ -2585,12 +2812,14 @@ void Save_C64(T_IO_Context * context)
Get_full_filename(filename, context->File_name, context->File_directory);
/*
if (numcolors>16)
{
Warning_message("Error: Max 16 colors");
File_error = 1;
return;
}
*/
if (((context->Width!=320) && (context->Width!=160)) || context->Height!=200)
{
Warning_message("must be 320x200 or 160x200");
@@ -2608,7 +2837,7 @@ void Save_C64(T_IO_Context * context)
if (context->Width==320)
File_error = Save_C64_hires(context,filename,saveWhat,loadAddr);
else
File_error = Save_C64_multi(context,filename,saveWhat,loadAddr);
File_error = Save_C64_fli(filename,saveWhat,loadAddr);
}
@@ -2699,3 +2928,234 @@ void Save_SCR(T_IO_Context * context)
File_error = 0;
}
// CM5 - Amstrad CPC "Mode 5" picture
// This is a format designed by SyX. There is one .SCR file in the usual amstrad format,
// and a .CM5 file with the palette, which varies over time.
void Test_CM5(T_IO_Context * context)
{
// check cm5 file size == 2049 bytes
FILE *file;
char filename[MAX_PATH_CHARACTERS];
long file_size;
Get_full_filename(filename, context->File_name, context->File_directory);
File_error = 1;
if ((file = fopen(filename, "rb")))
{
file_size = File_length_file(file);
if (file_size == 2049)
File_error = 0;
}
// TODO: check existence of a .SCR file with the same name
}
void Load_CM5(T_IO_Context* context)
{
// Ensure "8bit" constraint mode is switched on
// Set palette to the CPC hardware colors
// Load the palette data to the 4 colorlayers
FILE *file;
char filename[MAX_PATH_CHARACTERS];
byte value = 0;
int mod;
short line = 0;
int tx, ty;
byte buffer[48*6/4];
Get_full_filename(filename, context->File_name, context->File_directory);
if (!(file = fopen(filename, "rb")))
{
File_error = 1;
return;
}
Pre_load(context, 48*6, 256, 2049, FORMAT_CM5, PIXEL_SIMPLE, 0);
context->Width=48*6;
context->Height=256;
// Setup the palette (amstrad hardware palette)
context->Palette[0x54].R = 0; context->Palette[0x54].G = 2; context->Palette[0x54].B = 1;
context->Palette[0x44].R = 0; context->Palette[0x44].G = 2; context->Palette[0x44].B = 0x6B;
context->Palette[0x55].R = 0x0C; context->Palette[0x55].G = 2; context->Palette[0x55].B = 0xF4;
context->Palette[0x5C].R = 0x6C; context->Palette[0x5C].G = 2; context->Palette[0x5C].B = 1;
context->Palette[0x58].R = 0x69; context->Palette[0x58].G = 2; context->Palette[0x58].B = 0x68;
context->Palette[0x5D].R = 0x6C; context->Palette[0x5D].G = 2; context->Palette[0x5D].B = 0xF2;
context->Palette[0x4C].R = 0xF3; context->Palette[0x4C].G = 5; context->Palette[0x4C].B = 6;
context->Palette[0x45].R = 0xF0; context->Palette[0x45].G = 2; context->Palette[0x45].B = 0x68;
context->Palette[0x4D].R = 0xF3; context->Palette[0x4D].G = 2; context->Palette[0x4D].B = 0xF4;
context->Palette[0x56].R = 2; context->Palette[0x56].G = 0x78; context->Palette[0x56].B = 1;
context->Palette[0x46].R = 0; context->Palette[0x46].G = 0x78; context->Palette[0x46].B = 0x68;
context->Palette[0x57].R = 0xC; context->Palette[0x57].G = 0x7B; context->Palette[0x57].B = 0xF4;
context->Palette[0x5E].R = 0x6E; context->Palette[0x5E].G = 0x7B; context->Palette[0x5E].B = 1;
context->Palette[0x40].R = 0x6E; context->Palette[0x40].G = 0x7D; context->Palette[0x40].B = 0x6B;
context->Palette[0x5F].R = 0x6E; context->Palette[0x5F].G = 0x7B; context->Palette[0x5F].B = 0xF6;
context->Palette[0x4E].R = 0xF3; context->Palette[0x4E].G = 0x7D; context->Palette[0x4E].B = 0xD;
context->Palette[0x47].R = 0xF3; context->Palette[0x47].G = 0x7D; context->Palette[0x47].B = 0x6B;
context->Palette[0x4F].R = 0xFA; context->Palette[0x4F].G = 0x80; context->Palette[0x4F].B = 0xF9;
context->Palette[0x52].R = 2; context->Palette[0x52].G = 0xF0; context->Palette[0x52].B = 1;
context->Palette[0x42].R = 0; context->Palette[0x42].G = 0xF3; context->Palette[0x42].B = 0x6B;
context->Palette[0x53].R = 0xF; context->Palette[0x53].G = 0xF3; context->Palette[0x53].B = 0xF2;
context->Palette[0x5A].R = 0x71; context->Palette[0x5A].G = 0xF5; context->Palette[0x5A].B = 4;
context->Palette[0x59].R = 0x71; context->Palette[0x59].G = 0xF3; context->Palette[0x59].B = 0x6B;
context->Palette[0x5B].R = 0x71; context->Palette[0x5B].G = 0xF3; context->Palette[0x5B].B = 0xF4;
context->Palette[0x4A].R = 0xF3; context->Palette[0x4A].G = 0xF3; context->Palette[0x4A].B = 0xD;
context->Palette[0x43].R = 0xF3; context->Palette[0x43].G = 0xF3; context->Palette[0x43].B = 0x6D;
context->Palette[0x4B].R = 255; context->Palette[0x4B].G = 0xF3; context->Palette[0x4B].B = 0xF9;
Palette_loaded(context);
if (Constraint_mode != 1)
Constraint_mode = 1;
if (Read_byte(file, &value)!=1)
File_error = 2;
Set_loading_layer(context, 0);
for(ty=0; ty<context->Height; ty++)
for(tx=0; tx<context->Width; tx++)
{
Set_pixel(context, tx, ty, value);
}
// Fill layer with color we just read
while(Read_byte(file, &value) == 1)
{
switch(mod)
{
case 0:
// This is color for layer 1
Set_loading_layer(context, 1);
for(tx=0; tx<context->Width; tx++)
Set_pixel(context, tx, line, value);
break;
case 1:
// This is color for layer 2
Set_loading_layer(context, 2);
for(tx=0; tx<context->Width; tx++)
Set_pixel(context, tx, line, value);
break;
default:
// This is color for a block in layer 4
Set_loading_layer(context, 3);
for(tx=(mod-2)*48; tx<(mod-1)*48; tx++)
Set_pixel(context, tx, line, value);
break;
}
mod = mod + 1;
if (mod > 7)
{
mod = 0;
line ++;
}
}
fclose(file);
// Load the pixeldata to the 5th layer
filename[strlen(filename) - 3] = 0;
strcat(filename,"gfx");
if (!(file = fopen(filename, "rb")))
{
File_error = 1;
return;
}
Set_loading_layer(context, 4);
for (ty = 0; ty < 256; ty++)
{
Read_bytes(file, buffer, 48*6/4);
for (tx = 0; tx < 48*6; tx+=4)
{
Set_pixel(context, tx+0, ty, 3-(((buffer[tx/4]&0x80) >> 7) |((buffer[tx/4]&0x8)>>2)));
Set_pixel(context, tx+1, ty, 3-(((buffer[tx/4]&0x40) >> 6) |((buffer[tx/4]&0x4)>>1)));
Set_pixel(context, tx+2, ty, 3-(((buffer[tx/4]&0x20) >> 5) |((buffer[tx/4]&0x2)>>0)));
Set_pixel(context, tx+3, ty, 3-(((buffer[tx/4]&0x10) >> 4) |((buffer[tx/4]&0x1)<<1)));
}
}
fclose(file);
}
void Save_CM5(T_IO_Context* context)
{
char filename[MAX_PATH_CHARACTERS];
FILE* file;
int tx, ty;
Get_full_filename(filename, context->File_name, context->File_directory);
// TODO: Check picture has 5 layers
// TODO: Check the constraints on the layers
// Layer 1 : 1 color Only
// Layer 2 and 3 : 1 color/line
// Layer 4 : 1 color / 48x1 block
// TODO: handle filesize
if (!(file = fopen(filename,"wb")))
{
File_error = 1;
return;
}
// Write layer 0
Set_saving_layer(context, 0);
Write_byte(file, Get_pixel(context, 0, 0));
for(ty = 0; ty < 256; ty++)
{
Set_saving_layer(context, 1);
Write_byte(file, Get_pixel(context, 0, ty));
Set_saving_layer(context, 2);
Write_byte(file, Get_pixel(context, 0, ty));
Set_saving_layer(context, 3);
for(tx = 0; tx < 6; tx++)
{
Write_byte(file, Get_pixel(context, tx*48, ty));
}
}
fclose(file);
// Now the pixeldata
filename[strlen(filename) - 3] = 0;
strcat(filename,"gfx");
if (!(file = fopen(filename, "wb")))
{
File_error = 2;
return;
}
Set_saving_layer(context, 4);
for (ty = 0; ty < 256; ty++)
{
for (tx = 0; tx < 48*6; tx+=4)
{
byte code = 0;
byte pixel;
pixel = 3-Get_pixel(context, tx+3, ty);
code |= (pixel&2)>>1 | ((pixel & 1)<<4);
pixel = 3-Get_pixel(context, tx+2, ty);
code |= ((pixel&2)<<0) | ((pixel & 1)<<5);
pixel = 3-Get_pixel(context, tx+1, ty);
code |= ((pixel&2)<<1) | ((pixel & 1)<<6);
pixel = 3-Get_pixel(context, tx, ty);
code |= ((pixel&2)<<2) | ((pixel & 1)<<7);
Write_byte(file, code);
}
}
fclose(file);
File_error = 0;
}