Load_MOTO(): support the ".MAP" format (GET/SAVEP/LOADP/PUT)

This commit is contained in:
Thomas Bernard 2018-11-12 16:56:27 +01:00
parent 77262deadc
commit 23812b28e9
No known key found for this signature in database
GPG Key ID: 0FF11B67A5C0863C
2 changed files with 315 additions and 79 deletions

View File

@ -90,7 +90,7 @@ const T_Format File_formats[] = {
{FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "",
"gif;png;bmp;2bp;pcx;pkm;iff;lbm;ilbm;sham;ham;ham6;ham8;acbm;pic;anim;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;"
"c64;p64;a64;pi;rp;aas;art;dd;iph;ipt;hpc;ocp;koa;koala;fli;"
"bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin"},
"bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin;map"},
{FORMAT_ALL_PALETTES, "(pal)", NULL, NULL, NULL, 1, 0, 0, "", "kcf;pal;gpl"},
{FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
{FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"},
@ -120,7 +120,7 @@ const T_Format File_formats[] = {
{FORMAT_ICO, " ico", Test_ICO, Load_ICO, Save_ICO, 0, 0, 0, "ico", "ico;ic2;cur"},
{FORMAT_INFO," info",Test_INFO,Load_INFO,NULL, 0, 0, 0, "info", "info"},
{FORMAT_FLI, " flc", Test_FLI, Load_FLI, NULL, 0, 0, 0, "flc", "flc;fli;dat"},
{FORMAT_MOTO," moto",Test_MOTO,Load_MOTO,NULL, 0, 0, 0, "bin", "bin"},
{FORMAT_MOTO," moto",Test_MOTO,Load_MOTO,NULL, 0, 0, 0, "bin", "bin;map"},
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff"},
};

View File

@ -4867,20 +4867,43 @@ void Load_FLI(T_IO_Context * context)
void Test_MOTO(T_IO_Context * context, FILE * file)
{
long file_size;
byte code;
word size, address;
(void)context;
file_size = File_length_file(file);
File_error = 1;
if (file_size <= 10)
return;
switch (file_size)
{
// Files in RAW formats (from TGA2teo)
case 8004: // 2 colors palette
case 8008: // 4 colors palette
case 8032: // 16 colors palette
File_error = 0;
break;
return;
default:
File_error = 1;
break;
}
// Check for Thomson binary format
// last 5 bytes must be
// FF 00 00 xx xx (xx xx = start address when using LOADM,R)
if (fseek(file, -5, SEEK_END) < 0)
return;
if(!Read_byte(file, &code))
return;
if(code != 0xff)
return;
if(!Read_word_be(file, &size))
return;
if(size != 0)
return;
if(!Read_word_be(file, &address))
return;
File_error = 0;
}
/**
@ -4909,18 +4932,17 @@ void Test_MOTO(T_IO_Context * context, FILE * file)
void Load_MOTO(T_IO_Context * context)
{
// FORME / COULEUR
FILE * file_forme;
FILE * file_couleur = NULL;
FILE * file;
byte * vram_forme;
byte * vram_couleur;
long file_size;
int n_colors;
int bx, x, y;
char filename[MAX_PATH_CHARACTERS];
char path[MAX_PATH_CHARACTERS];
int bx, x, y, i;
byte bpp;
char * ext;
byte code;
word length, address;
enum MOTO_mode { F_40col, F_80col, F_bm4, F_bm16 } mode = F_40col;
enum PIXEL_RATIO ratio = PIXEL_SIMPLE;
int width = 320;
int width = 320, height = 200, columns = 40;
static const int gamma[16] = { // Gamma values for MO6/TO8 palette
0 , 100, 127, 147,
163, 179, 191, 203,
@ -4930,10 +4952,206 @@ void Load_MOTO(T_IO_Context * context)
File_error = 1;
file_forme = Open_file_read(context);
if (file_forme == NULL)
file = Open_file_read(context);
if (file == NULL)
return;
file_size = File_length_file(file_forme);
file_size = File_length_file(file);
// check for Thomson binary format
// last 5 bytes must be
// FF 00 00 xx xx (xx xx = start address when using LOADM,R)
if (fseek(file, -5, SEEK_END) < 0)
return;
if (!(Read_byte(file,&code) && Read_word_be(file,&length) && Read_word_be(file,&address)))
return;
if (fseek(file, 0, SEEK_SET) < 0)
return;
if (code == 0xff && length == 0)
{
// http://collection.thomson.free.fr/code/articles/prehisto_bulletin/page.php?XI=0&XJ=13
byte map_mode, col_count, line_count;
byte * vram_current;
int end_marks;
GFX2_Log(GFX2_DEBUG, "Thomson binary file detected. run address=&H%04X\n", address);
if (!(Read_byte(file,&code) && Read_word_be(file,&length) && Read_word_be(file,&address)))
{
fclose(file);
return;
}
GFX2_Log(GFX2_DEBUG, "block &H%02X length=&H%04X address=&H%04X\n", code, length, address);
if (length < 5 || !(Read_byte(file,&map_mode) && Read_byte(file,&col_count) && Read_byte(file,&line_count)))
{
fclose(file);
return;
}
length -= 3;
columns = col_count + 1;
height = 8 * (line_count + 1);
switch(map_mode)
{
default:
case 0: // bitmap4 or 40col
width = 8 * columns;
mode = F_40col; // default to 40col
bpp = 4;
break;
case 0x40: // bitmap16
width = 4 * columns;
mode = F_bm16;
bpp = 4;
ratio = PIXEL_WIDE;
break;
case 0x80: // 80col
width = 16 * columns;
mode = F_80col;
bpp = 1;
ratio = PIXEL_TALL;
break;
}
GFX2_Log(GFX2_DEBUG, "Map mode &H%02X row=%u line=%u (%dx%d)\n", map_mode, col_count, line_count, width, height);
vram_forme = malloc(columns * height);
vram_couleur = malloc(columns * height);
// Check extension (TO-SNAP / PPM / ???)
if (length > 36)
{
long pos_backup;
word data;
pos_backup = ftell(file);
fseek(file, length-2, SEEK_CUR); // go to last word of chunk
Read_word_be(file, &data);
GFX2_Log(GFX2_DEBUG, "%04X\n", data);
switch (data)
{
case 0xA55A: // TO-SNAP
fseek(file, -40, SEEK_CUR); // go to begin of extension
Read_word_be(file, &data); // SCRMOD. 0=>40col, 1=>bm4, $40=>bm16, $80=>80col
GFX2_Log(GFX2_DEBUG, "SCRMOD=&H%04X ", data);
Read_word_be(file, &data); // Border color
GFX2_Log(GFX2_DEBUG, "BORDER=%u ", data);
Read_word_be(file, &data); // Mode BASIC (CONSOLE,,,,X) 0=40col, 1=80col, 2=bm4, 3=bm16, etc.
GFX2_Log(GFX2_DEBUG, "CONSOLE,,,,%u\n", data);
if(data == 2)
{
mode = F_bm4;
bpp = 2;
}
for (i = 0; i < 16; i++)
{
Read_word_be(file, &data); // Palette entry
if (data & 0x8000) data = ~data;
context->Palette[i].B = gamma[(data >> 8) & 0x0F];
context->Palette[i].G = gamma[(data >> 4) & 0x0F];
context->Palette[i].R = gamma[data & 0x0F];
}
break;
case 0x484C: // 'HL' PPM
fseek(file, -36, SEEK_CUR); // go to begin of extension
for (i = 0; i < 16; i++)
{
Read_word_be(file, &data); // Palette entry
if (data & 0x8000) data = ~data;
context->Palette[i].B = gamma[(data >> 8) & 0x0F];
context->Palette[i].G = gamma[(data >> 4) & 0x0F];
context->Palette[i].R = gamma[data & 0x0F];
}
Read_word_be(file, &data); // Mode BASIC (CONSOLE,,,,X) 0=40col, 1=80col, 2=bm4, 3=bm16, etc.
GFX2_Log(GFX2_DEBUG, "CONSOLE,,,,%u\n", data);
if(data == 2)
{
mode = F_bm4;
bpp = 2;
}
break;
}
fseek(file, pos_backup, SEEK_SET); // RESET Position
}
i = 0;
vram_current = vram_forme;
end_marks = 0;
while (length > 1)
{
byte byte1, byte2;
Read_byte(file,&byte1);
Read_byte(file,&byte2);
length-=2;
if(byte1 == 0)
{
if (byte2 == 0)
{
// end of vram stream
GFX2_Log(GFX2_DEBUG, "0000 i=%d length=%ld\n", i, length);
if (end_marks == 1)
break;
i = 0;
vram_current = vram_couleur;
end_marks++;
}
else while(byte2-- > 0 && length > 0) // copy
{
Read_byte(file,vram_current + i);
length--;
i += columns; // to the next line
if (i >= columns * height)
{
if (mode == F_bm4 || mode == F_40col)
i -= (columns * height - 1); // to the 1st line of the next column
else
{
i -= columns * height; // back to the 1st line of the current column
if (vram_current == vram_forme) // other VRAM
vram_current = vram_couleur;
else
{
vram_current = vram_forme;
i++; // next column
}
}
}
}
}
else while(byte1-- > 0) // run length
{
vram_current[i] = byte2;
i += columns; // to the next line
if (i >= columns * height)
{
if (mode == F_bm4 || mode == F_40col)
i -= (columns * height - 1); // to the 1st line of the next column
else
{
i -= columns * height; // back to the 1st line of the current column
if (vram_current == vram_forme) // other VRAM
vram_current = vram_couleur;
else
{
vram_current = vram_forme;
i++; // next column
}
}
}
}
}
}
else
{
char filename[MAX_PATH_CHARACTERS];
char path[MAX_PATH_CHARACTERS];
char * ext;
int n_colors;
vram_forme = malloc(file_size);
if (vram_forme == NULL)
{
fclose(file);
return;
}
if (!Read_bytes(file, vram_forme, file_size))
{
free(vram_forme);
fclose(file);
return;
}
n_colors = (file_size - 8000) / 2;
switch(n_colors)
{
@ -4957,21 +5175,18 @@ void Load_MOTO(T_IO_Context * context)
ext = strrchr(filename, '.');
if (ext == NULL || ext == context->File_name)
{
fclose(file_forme);
free(vram_forme);
return;
}
if ((ext[-1] | 32) == 'c')
{
file_couleur = file_forme;
vram_couleur = vram_forme;
vram_forme = NULL;
ext[-1] = (ext[-1] & 32) | 'P';
Get_full_filename(path, filename, context->File_directory);
file_forme = fopen(path, "rb");
}
else if ((ext[-1] | 32) == 'p')
{
ext[-1] = (ext[-1] & 32) | 'C';
Get_full_filename(path, filename, context->File_directory);
file_couleur = fopen(path, "rb");
if (n_colors == 16)
{
mode = F_bm16;
@ -4979,24 +5194,60 @@ void Load_MOTO(T_IO_Context * context)
ratio = PIXEL_WIDE;
}
}
if (file_couleur == NULL)
else
{
fclose(file_forme);
free(vram_forme);
return;
}
GFX2_Log(GFX2_DEBUG, "MO/TO: %s,%s file_size=%ld n_colors=%d\n", context->File_name, filename, file_size, n_colors);
Pre_load(context, width, 200, file_size, FORMAT_MOTO, ratio, bpp);
File_error = 0;
for (y = 0; y < 200; y++)
Get_full_filename(path, filename, context->File_directory);
file = fopen(path, "rb");
if (vram_forme == NULL)
{
for (bx = 0; bx < 40; bx++)
vram_forme = malloc(file_size);
if (vram_forme == NULL)
{
free(vram_couleur);
fclose(file);
return;
}
Read_bytes(file,vram_forme,file_size);
}
else
{
vram_couleur = malloc(file_size);
if (vram_couleur == NULL)
{
free(vram_forme);
fclose(file);
return;
}
Read_bytes(file,vram_couleur,file_size);
}
fclose(file);
GFX2_Log(GFX2_DEBUG, "MO/TO: %s,%s file_size=%ld n_colors=%d\n", context->File_name, filename, file_size, n_colors);
for (x = 0; x < n_colors; x++)
{
// 1 byte Blue (4 lower bits)
// 1 byte Green (4 upper bits) / Red (4 lower bits)
context->Palette[x].B = gamma[vram_couleur[8000+x*2] & 0x0F];
context->Palette[x].G = gamma[vram_couleur[8000+x*2+1] >> 4];
context->Palette[x].R = gamma[vram_couleur[8000+x*2+1] & 0x0F];
}
}
Pre_load(context, width, height, file_size, FORMAT_MOTO, ratio, bpp);
File_error = 0;
i = 0;
for (y = 0; y < height; y++)
{
for (bx = 0; bx < columns; bx++)
{
byte couleur_forme;
byte couleur_fond;
byte forme, couleurs;
if (!(Read_byte(file_forme,&forme) && Read_byte(file_couleur,&couleurs)))
File_error = 1;
forme = vram_forme[i];
couleurs = vram_couleur[i];
i++;
switch(mode)
{
case F_bm4:
@ -5040,19 +5291,4 @@ void Load_MOTO(T_IO_Context * context)
}
}
}
for (x = 0; x < n_colors; x++)
{
byte value;
// 1 byte Blue (4 lower bits)
// 1 byte Green (4 upper bits) / Red (4 lower bits)
if (!Read_byte(file_forme,&value))
File_error = 1;
context->Palette[x].B = gamma[value & 0x0F];
if (!Read_byte(file_forme,&value))
File_error = 1;
context->Palette[x].G = gamma[value >> 4];
context->Palette[x].R = gamma[value & 0x0F];
}
fclose(file_forme);
fclose(file_couleur);
}