Fix loading some Atari ST IFF files

IFF is a versatile format, and can store data in Atari ST display RAM format.
This allows to load several of our IFF test files, but the result for most
seems corrupt (either that, or the files in our testsuite are ugly).

Thanks to miniupnp for the patch!

Fixes #38.


git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@2168 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues 2016-11-22 20:42:15 +00:00
parent 40201c862d
commit 2fc6b9375c

View File

@ -231,10 +231,10 @@ typedef struct
word X_org; // Inutile word X_org; // Inutile
word Y_org; // Inutile word Y_org; // Inutile
byte BitPlanes; byte BitPlanes;
byte Mask; byte Mask; // 0=none, 1=mask, 2=transp color, 3=Lasso
byte Compression; byte Compression; // 0=none, 1=packbits, 2=vertical RLE
byte Pad1; // Inutile byte Pad1; // Inutile
word Transp_col; word Transp_col; // transparent color for masking mode 2
byte X_aspect; // Inutile byte X_aspect; // Inutile
byte Y_aspect; // Inutile byte Y_aspect; // Inutile
word X_screen; word X_screen;
@ -438,7 +438,7 @@ int IFF_Skip_section(void)
} }
// ------------------------- Attendre une section ------------------------- // ------------------------- Attendre une section -------------------------
byte IFF_Wait_for(byte * expected_section) byte IFF_Wait_for(const char * expected_section)
{ {
// Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur) // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
byte section_read[4]; byte section_read[4];
@ -584,12 +584,14 @@ void Load_IFF(T_IO_Context * context)
short y_pos; short y_pos;
short counter; short counter;
short line_size; // Taille d'une ligne en octets short line_size; // Taille d'une ligne en octets
short plane_line_size; // Size of line in bytes for 1 plane
short real_line_size; // Taille d'une ligne en pixels short real_line_size; // Taille d'une ligne en pixels
byte color; byte color;
long file_size; long file_size;
dword dummy; dword dummy;
byte is_anim=0; byte is_anim=0;
int iff_format; int iff_format;
int plane;
Get_full_filename(filename, context->File_name, context->File_directory); Get_full_filename(filename, context->File_name, context->File_directory);
@ -617,7 +619,7 @@ void Load_IFF(T_IO_Context * context)
else else
iff_format = FORMAT_PBM; iff_format = FORMAT_PBM;
if (!IFF_Wait_for((byte *)"BMHD")) if (!IFF_Wait_for("BMHD"))
File_error=1; File_error=1;
Read_dword_be(IFF_file,&dummy); Read_dword_be(IFF_file,&dummy);
@ -637,7 +639,7 @@ void Load_IFF(T_IO_Context * context)
&& (Read_word_be(IFF_file,&header.Y_screen)) && (Read_word_be(IFF_file,&header.Y_screen))
&& header.Width && header.Height) && header.Width && header.Height)
{ {
if ( (header.BitPlanes) && (IFF_Wait_for((byte *)"CMAP")) ) if ( (header.BitPlanes) && (IFF_Wait_for("CMAP")) )
{ {
Read_dword_be(IFF_file,&nb_colors); Read_dword_be(IFF_file,&nb_colors);
nb_colors/=3; nb_colors/=3;
@ -662,6 +664,8 @@ void Load_IFF(T_IO_Context * context)
if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) ) if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) )
{ {
byte real_bit_planes = header.BitPlanes;
if (header.Mask==1) if (header.Mask==1)
header.BitPlanes++; header.BitPlanes++;
@ -769,73 +773,148 @@ void Load_IFF(T_IO_Context * context)
if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap
{ {
// Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques) // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques)
if (context->Width & 15) real_line_size = (context->Width+15) & ~15;
plane_line_size = real_line_size >> 3; // 8bits per byte
line_size = plane_line_size * header.BitPlanes;
switch(header.Compression)
{ {
real_line_size=( (context->Width+16) >> 4 ) << 4; case 0: // non compressé
line_size=( (context->Width+16) >> 4 )*(header.BitPlanes<<1); IFF_buffer=(byte *)malloc(line_size);
} for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++)
else
{
real_line_size=context->Width;
line_size=(context->Width>>3)*header.BitPlanes;
}
if (!header.Compression)
{ // non compressé
IFF_buffer=(byte *)malloc(line_size);
for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++)
{
if (Read_bytes(IFF_file,IFF_buffer,line_size))
Draw_IFF_line(context, y_pos,real_line_size, header.BitPlanes);
else
File_error=21;
}
free(IFF_buffer);
IFF_buffer = NULL;
}
else
{ // compressé
/*Init_lecture();*/
IFF_buffer=(byte *)malloc(line_size);
for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++)
{
for (x_pos=0; ((x_pos<line_size) && (!File_error)); )
{ {
if(Read_byte(IFF_file, &temp_byte)!=1) if (Read_bytes(IFF_file,IFF_buffer,line_size))
Draw_IFF_line(context, y_pos,real_line_size, header.BitPlanes);
else
File_error=21;
}
free(IFF_buffer);
IFF_buffer = NULL;
break;
case 1: // compressé packbits (Amiga)
/*Init_lecture();*/
IFF_buffer=(byte *)malloc(line_size);
for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++)
{
for (x_pos=0; ((x_pos<line_size) && (!File_error)); )
{ {
File_error=22; if(Read_byte(IFF_file, &temp_byte)!=1)
break;
}
// Si temp_byte > 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant
// Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants
if (temp_byte>127)
{
if(Read_byte(IFF_file, &color)!=1)
{ {
File_error=23; File_error=22;
break; break;
} }
b256=(short)(256-temp_byte); // Si temp_byte > 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant
for (counter=0; counter<=b256; counter++) // Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants
if (x_pos<line_size) if (temp_byte>127)
IFF_buffer[x_pos++]=color; {
else if(Read_byte(IFF_file, &color)!=1)
File_error=24; {
File_error=23;
break;
}
b256=(short)(256-temp_byte);
for (counter=0; counter<=b256; counter++)
if (x_pos<line_size)
IFF_buffer[x_pos++]=color;
else
File_error=24;
}
else
for (counter=0; counter<=(short)(temp_byte); counter++)
if (x_pos>=line_size || Read_byte(IFF_file, &(IFF_buffer[x_pos++]))!=1)
File_error=25;
} }
else if (!File_error)
for (counter=0; counter<=(short)(temp_byte); counter++) Draw_IFF_line(context, y_pos,real_line_size,header.BitPlanes);
if (x_pos>=line_size || Read_byte(IFF_file, &(IFF_buffer[x_pos++]))!=1) }
File_error=25;
free(IFF_buffer);
IFF_buffer = NULL;
/*Close_lecture();*/
break;
case 2: // compressé vertical RLE (Atari ST)
IFF_buffer=(byte *)malloc(line_size*context->Height);
plane_line_size = real_line_size >> 3;
for (plane = 0; plane < header.BitPlanes && !File_error; plane++)
{
word cmd_count;
word cmd;
signed char * commands;
word count;
y_pos = 0; x_pos = 0;
if (!IFF_Wait_for("VDAT"))
{
File_error = 30;
break;
}
Read_dword_be(IFF_file,&section_size);
Read_word_be(IFF_file,&cmd_count);
cmd_count -= 2;
commands = (signed char *)malloc(cmd_count);
if (!Read_bytes(IFF_file,commands,cmd_count))
{
File_error = 31;
break;
}
for (cmd = 0; cmd < cmd_count && x_pos < plane_line_size; cmd++)
{
if (commands[cmd] <= 0)
{ // cmd=0 : load count from data, COPY
// cmd < 0 : count = -cmd, COPY
if (commands[cmd] == 0)
Read_word_be(IFF_file,&count);
else
count = -commands[cmd];
while (count-- > 0 && x_pos < plane_line_size)
{
Read_bytes(IFF_file,IFF_buffer+x_pos+y_pos*line_size+plane*plane_line_size,2);
if(++y_pos >= context->Height)
{
y_pos = 0;
x_pos += 2;
}
}
}
else if (commands[cmd] >= 1)
{ // cmd=1 : load count from data, RLE
// cmd >1 : count = cmd, RLE
byte data[2];
if (commands[cmd] == 1)
Read_word_be(IFF_file,&count);
else
count = (word)commands[cmd];
Read_bytes(IFF_file,data,2);
while (count-- > 0 && x_pos < plane_line_size)
{
memcpy(IFF_buffer+x_pos+y_pos*line_size+plane*plane_line_size,data,2);
if (++y_pos >= context->Height)
{
y_pos = 0;
x_pos += 2;
}
}
}
}
free(commands);
} }
if (!File_error) if (!File_error)
Draw_IFF_line(context, y_pos,real_line_size,header.BitPlanes); {
} byte * save_IFF_buffer = IFF_buffer;
for (y_pos = 0; y_pos < context->Height; y_pos++)
free(IFF_buffer); {
IFF_buffer = NULL; Draw_IFF_line(context,y_pos,real_line_size,real_bit_planes);
/*Close_lecture();*/ IFF_buffer += line_size;
}
IFF_buffer = save_IFF_buffer;
}
free(IFF_buffer);
IFF_buffer = NULL;
break;
default: // compression non reconnue
File_error = 32;
} }
} }
else // "PBM ": Planar(?) BitMap else // "PBM ": Planar(?) BitMap
@ -909,7 +988,7 @@ void Load_IFF(T_IO_Context * context)
// ILBM, hopefully // ILBM, hopefully
Read_bytes(IFF_file,format,4); Read_bytes(IFF_file,format,4);
if (!IFF_Wait_for((byte *)"DLTA")) if (!IFF_Wait_for("DLTA"))
{ {
File_error=1; File_error=1;
break; break;
@ -1142,19 +1221,13 @@ void Save_IFF(T_IO_Context * context)
if (context->Format == FORMAT_LBM) if (context->Format == FORMAT_LBM)
{ {
short line_size; // Size of line in bytes short line_size; // Size of line in bytes
short plane_line_size; // Size of line in bytes for 1 plane
short real_line_size; // Size of line in pixels short real_line_size; // Size of line in pixels
// Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques) // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques)
if (context->Width & 15) real_line_size = (context->Width+15) & ~15;
{ plane_line_size = real_line_size >> 3; // 8bits per byte
real_line_size=( (context->Width+16) >> 4 ) << 4; line_size = plane_line_size * header.BitPlanes;
line_size=( (context->Width+16) >> 4 )*(header.BitPlanes<<1);
}
else
{
real_line_size=context->Width;
line_size=(context->Width>>3)*header.BitPlanes;
}
IFF_buffer=(byte *)malloc(line_size); IFF_buffer=(byte *)malloc(line_size);
// Start encoding // Start encoding