Reorganize Load_IFF()

This commit is contained in:
Thomas Bernard 2017-05-18 12:11:30 +02:00
parent b70d49349a
commit 14cce41ba9

View File

@ -300,6 +300,7 @@ void Test_IFF(T_IO_Context * context, const char *sub_type)
} while (0); } while (0);
fclose(IFF_file); fclose(IFF_file);
IFF_file = NULL;
} }
} }
@ -640,17 +641,27 @@ 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("CMAP")) ) byte real_bit_planes = header.BitPlanes;
if (header.Mask==1)
header.BitPlanes++;
Back_color=header.Transp_col;
Image_HAM=0;
// TODO parse X / Y aspect
while (File_error == 0
&& Read_bytes(IFF_file,section,4)
&& Read_dword_be(IFF_file,&section_size))
{ {
Read_dword_be(IFF_file,&nb_colors); if (memcmp(section, "CMAP", 4) == 0)
nb_colors/=3; {
nb_colors = section_size/3;
if (((dword)1<<header.BitPlanes)!=nb_colors) if (((dword)1<<header.BitPlanes)!=nb_colors)
{ {
if ((nb_colors==32) && (header.BitPlanes==6)) if ((nb_colors==32) && (header.BitPlanes==6))
{ // Ce n'est pas une image HAM mais une image 64 coul. { // This is a Extra Half-Brite (EHB) 64 color image.
Image_HAM=1; // Sauvée en 32 coul. => il faut copier les 32 coul. Image_HAM=1; // 32 colors in the palette.
} // sur les 32 suivantes et assombrir ces dernières. } // The next 32 colors are the same with values divided by 2
else else
{ {
if ((header.BitPlanes==6) || (header.BitPlanes==8)) if ((header.BitPlanes==6) || (header.BitPlanes==8))
@ -660,22 +671,9 @@ void Load_IFF(T_IO_Context * context)
Image_HAM=0; /* trouvé un fichier comme ça, alors... */ Image_HAM=0; /* trouvé un fichier comme ça, alors... */
} }
} }
else
Image_HAM=0;
if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) )
{
byte real_bit_planes = header.BitPlanes;
if (header.Mask==1)
header.BitPlanes++;
// Deluxe paint le fait... alors on le fait...
Back_color=header.Transp_col;
if (Config.Clear_palette) if (Config.Clear_palette)
memset(context->Palette,0,sizeof(T_Palette)); memset(context->Palette,0,sizeof(T_Palette));
// On peut maintenant charger la nouvelle palette
if (Read_bytes(IFF_file,context->Palette,3*nb_colors)) if (Read_bytes(IFF_file,context->Palette,3*nb_colors))
{ {
if (Image_HAM) if (Image_HAM)
@ -685,35 +683,26 @@ void Load_IFF(T_IO_Context * context)
Palette_64_to_256(context->Palette); Palette_64_to_256(context->Palette);
} }
// On lit l'octet de padding du CMAP si la taille est impaire section_size -= 3*nb_colors;
if (nb_colors&1) while(section_size > 0) // Read padding bytes
{
if (Read_byte(IFF_file,&temp_byte)) if (Read_byte(IFF_file,&temp_byte))
File_error=20; File_error=20;
section_size--;
// Keep reading sections until we find the body
while (1)
{
if (! Read_bytes(IFF_file,section,4))
{
File_error=46;
break;
} }
// Found body : stop searching }
if (!memcmp(section,"BODY",4)) else
break; File_error=1;
else if (!memcmp(section,"CRNG",4)) }
else if (memcmp(section,"CRNG",4) == 0)
{ {
// Handle CRNG
// The content of a CRNG is as follows: // The content of a CRNG is as follows:
word padding; word padding;
word rate; word rate;
word flags; word flags;
byte min_col; byte min_col;
byte max_col; byte max_col;
// if ( (Read_word_be(IFF_file,&padding))
if ( (Read_dword_be(IFF_file,&section_size))
&& (Read_word_be(IFF_file,&padding))
&& (Read_word_be(IFF_file,&rate)) && (Read_word_be(IFF_file,&rate))
&& (Read_word_be(IFF_file,&flags)) && (Read_word_be(IFF_file,&flags))
&& (Read_byte(IFF_file,&min_col)) && (Read_byte(IFF_file,&min_col))
@ -734,33 +723,14 @@ void Load_IFF(T_IO_Context * context)
} }
} }
else else
{
File_error=47; File_error=47;
break;
} }
} else if (memcmp(section, "BODY", 4) == 0)
else
{ {
// ignore any number of unknown sections
if (!IFF_Skip_section())
{
File_error=48;
break;
}
}
}
if ( !File_error )
{
Read_dword_be(IFF_file,&section_size);
context->Width = header.Width;
context->Height = header.Height;
Original_screen_X = header.X_screen; Original_screen_X = header.X_screen;
Original_screen_Y = header.Y_screen; Original_screen_Y = header.Y_screen;
Pre_load(context, context->Width,context->Height,file_size,iff_format,PIXEL_SIMPLE,0); Pre_load(context, header.Width, header.Height, file_size, iff_format, PIXEL_SIMPLE, 0);
context->Background_transparent = header.Mask == 2; context->Background_transparent = header.Mask == 2;
context->Transparent_color = context->Background_transparent ? header.Transp_col : 0; context->Transparent_color = context->Background_transparent ? header.Transp_col : 0;
@ -769,18 +739,17 @@ void Load_IFF(T_IO_Context * context)
Main.backups->Pages->Image_mode = IMAGE_MODE_ANIMATION; Main.backups->Pages->Image_mode = IMAGE_MODE_ANIMATION;
Update_screen_targets(); Update_screen_targets();
} }
if (File_error==0)
{
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) // compute row size
real_line_size = (context->Width+15) & ~15; real_line_size = (context->Width+15) & ~15;
plane_line_size = real_line_size >> 3; // 8bits per byte plane_line_size = real_line_size >> 3; // 8bits per byte
line_size = plane_line_size * header.BitPlanes; line_size = plane_line_size * header.BitPlanes;
switch(header.Compression) switch(header.Compression)
{ {
case 0: // non compressé case 0: // uncompressed
IFF_buffer=(byte *)malloc(line_size); IFF_buffer=(byte *)malloc(line_size);
for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++) for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++)
{ {
@ -792,11 +761,8 @@ void Load_IFF(T_IO_Context * context)
free(IFF_buffer); free(IFF_buffer);
IFF_buffer = NULL; IFF_buffer = NULL;
break; break;
case 1: // compressé packbits (Amiga) case 1: // packbits compression (Amiga)
/*Init_lecture();*/
IFF_buffer=(byte *)malloc(line_size); IFF_buffer=(byte *)malloc(line_size);
for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++) for (y_pos=0; ((y_pos<context->Height) && (!File_error)); y_pos++)
{ {
for (x_pos=0; ((x_pos<line_size) && (!File_error)); ) for (x_pos=0; ((x_pos<line_size) && (!File_error)); )
@ -830,13 +796,16 @@ void Load_IFF(T_IO_Context * context)
if (!File_error) if (!File_error)
Draw_IFF_line(context, y_pos,real_line_size,header.BitPlanes); Draw_IFF_line(context, y_pos,real_line_size,header.BitPlanes);
} }
free(IFF_buffer); free(IFF_buffer);
IFF_buffer = NULL; IFF_buffer = NULL;
/*Close_lecture();*/
break; break;
case 2: // compressé vertical RLE (Atari ST) case 2: // vertical RLE compression (Atari ST)
IFF_buffer=(byte *)malloc(line_size*context->Height); IFF_buffer=(byte *)calloc(line_size*context->Height, 1);
if (IFF_buffer == NULL)
{
File_error=1;
Warning("Failed to allocate memory for IFF decoding");
}
plane_line_size = real_line_size >> 3; plane_line_size = real_line_size >> 3;
for (plane = 0; plane < header.BitPlanes && !File_error; plane++) for (plane = 0; plane < header.BitPlanes && !File_error; plane++)
{ {
@ -848,6 +817,7 @@ void Load_IFF(T_IO_Context * context)
y_pos = 0; x_pos = 0; y_pos = 0; x_pos = 0;
if (!IFF_Wait_for("VDAT")) if (!IFF_Wait_for("VDAT"))
{ {
if (plane == 0) // don't cancel loading if at least 1 bitplane has been loaded
File_error = 30; File_error = 30;
break; break;
} }
@ -860,18 +830,23 @@ void Load_IFF(T_IO_Context * context)
File_error = 31; File_error = 31;
break; break;
} }
for (cmd = 0; cmd < cmd_count && x_pos < plane_line_size; cmd++) section_size -= (cmd_count + 2);
for (cmd = 0; cmd < cmd_count && x_pos < plane_line_size && section_size > 0; cmd++)
{ {
if (commands[cmd] <= 0) if (commands[cmd] <= 0)
{ // cmd=0 : load count from data, COPY { // cmd=0 : load count from data, COPY
// cmd < 0 : count = -cmd, COPY // cmd < 0 : count = -cmd, COPY
if (commands[cmd] == 0) if (commands[cmd] == 0)
{
Read_word_be(IFF_file,&count); Read_word_be(IFF_file,&count);
section_size -= 2;
}
else else
count = -commands[cmd]; count = -commands[cmd];
while (count-- > 0 && x_pos < plane_line_size) while (count-- > 0 && x_pos < plane_line_size && section_size > 0)
{ {
Read_bytes(IFF_file,IFF_buffer+x_pos+y_pos*line_size+plane*plane_line_size,2); Read_bytes(IFF_file,IFF_buffer+x_pos+y_pos*line_size+plane*plane_line_size,2);
section_size -= 2;
if(++y_pos >= context->Height) if(++y_pos >= context->Height)
{ {
y_pos = 0; y_pos = 0;
@ -884,14 +859,20 @@ void Load_IFF(T_IO_Context * context)
// cmd >1 : count = cmd, RLE // cmd >1 : count = cmd, RLE
byte data[2]; byte data[2];
if (commands[cmd] == 1) if (commands[cmd] == 1)
{
Read_word_be(IFF_file,&count); Read_word_be(IFF_file,&count);
section_size -= 2;
}
else else
count = (word)commands[cmd]; count = (word)commands[cmd];
if (section_size == 0)
break;
Read_bytes(IFF_file,data,2); Read_bytes(IFF_file,data,2);
section_size -= 2;
while (count-- > 0 && x_pos < plane_line_size) while (count-- > 0 && x_pos < plane_line_size)
{ {
memcpy(IFF_buffer+x_pos+y_pos*line_size+plane*plane_line_size,data,2); memcpy(IFF_buffer+x_pos+y_pos*line_size+plane*plane_line_size,data,2);
if (++y_pos >= context->Height) if(++y_pos >= context->Height)
{ {
y_pos = 0; y_pos = 0;
x_pos += 2; x_pos += 2;
@ -899,6 +880,10 @@ void Load_IFF(T_IO_Context * context)
} }
} }
} }
if(cmd < (cmd_count-1) || section_size > 0)
Warning("Early end in VDAT chunk");
if (section_size > 0)
fseek(IFF_file, section_size, SEEK_CUR); // skip bytes
free(commands); free(commands);
} }
if (!File_error) if (!File_error)
@ -914,7 +899,8 @@ void Load_IFF(T_IO_Context * context)
free(IFF_buffer); free(IFF_buffer);
IFF_buffer = NULL; IFF_buffer = NULL;
break; break;
default: // compression non reconnue default:
Warning("Unknown IFF compression");
File_error = 32; File_error = 32;
} }
} }
@ -972,9 +958,19 @@ void Load_IFF(T_IO_Context * context)
} }
} }
} }
/*Close_lecture();*/
} }
} }
}
else
{
char tmp_msg[60];
// skip section
snprintf(tmp_msg, sizeof(tmp_msg), "Skip unknown section '%.4s' of %u bytes", section, section_size);
Warning(tmp_msg);
fseek(IFF_file, section_size, SEEK_CUR);
}
}
/* /*
while (!File_error && is_anim) while (!File_error && is_anim)
{ {
@ -1001,25 +997,11 @@ void Load_IFF(T_IO_Context * context)
} }
*/ */
} }
}
else
Set_file_error(2);
}
else
{
File_error=1;
}
}
else
Set_file_error(1);
}
else
File_error=1;
}
else else
File_error=1; File_error=1;
fclose(IFF_file); fclose(IFF_file);
IFF_file = NULL;
} }
else else
File_error=1; File_error=1;
@ -1283,6 +1265,7 @@ void Save_IFF(T_IO_Context * context)
} }
} }
fclose(IFF_file); fclose(IFF_file);
IFF_file = NULL;
if (!File_error) if (!File_error)
{ {
@ -1310,6 +1293,7 @@ void Save_IFF(T_IO_Context * context)
Write_dword_be(IFF_file,file_size-8); Write_dword_be(IFF_file,file_size-8);
fclose(IFF_file); fclose(IFF_file);
IFF_file = NULL;
if (File_error) if (File_error)
remove(filename); remove(filename);
@ -1318,6 +1302,7 @@ void Save_IFF(T_IO_Context * context)
{ {
File_error=1; File_error=1;
fclose(IFF_file); fclose(IFF_file);
IFF_file = NULL;
remove(filename); remove(filename);
} }
} }