diff --git a/src/const.h b/src/const.h index b7ffbd59..806b04f1 100644 --- a/src/const.h +++ b/src/const.h @@ -110,6 +110,7 @@ enum FILE_FORMATS FORMAT_PCX, FORMAT_PKM, FORMAT_LBM, + FORMAT_PBM, FORMAT_IMG, FORMAT_SCx, FORMAT_PI1, diff --git a/src/fileformats.c b/src/fileformats.c index ac81906e..d50f5529 100644 --- a/src/fileformats.c +++ b/src/fileformats.c @@ -176,6 +176,8 @@ void Save_IMG(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + memcpy(IMG_header.Filler1,signature,6); IMG_header.Width=context->Width; @@ -197,13 +199,10 @@ void Save_IMG(T_IO_Context * context) ) { - Init_write_buffer(); - for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) for (x_pos=0; x_posWidth; x_pos++) Write_one_byte(file,Get_pixel(context, x_pos,y_pos)); - End_write(file); fclose(file); if (File_error) @@ -225,7 +224,7 @@ void Save_IMG(T_IO_Context * context) } -//////////////////////////////////// LBM //////////////////////////////////// +//////////////////////////////////// IFF //////////////////////////////////// typedef struct { word Width; @@ -241,14 +240,14 @@ typedef struct byte Y_aspect; // Inutile word X_screen; word Y_screen; -} T_LBM_Header; +} T_IFF_Header; -byte * LBM_buffer; -FILE *LBM_file; +byte * IFF_buffer; +FILE *IFF_file; -// -- Tester si un fichier est au format LBM -------------------------------- +// -- Tester si un fichier est au format IFF -------------------------------- -void Test_LBM(T_IO_Context * context) +void Test_IFF(T_IO_Context * context, const char *sub_type) { char filename[MAX_PATH_CHARACTERS]; char format[4]; @@ -259,51 +258,60 @@ void Test_LBM(T_IO_Context * context) File_error=1; - if ((LBM_file=fopen(filename, "rb"))) + if ((IFF_file=fopen(filename, "rb"))) { do // Dummy loop, so that all breaks jump to end. { - if (! Read_bytes(LBM_file,section,4)) + if (! Read_bytes(IFF_file,section,4)) break; if (memcmp(section,"FORM",4)) break; - if (! Read_dword_be(LBM_file, &dummy)) + if (! Read_dword_be(IFF_file, &dummy)) break; // On aurait pu vérifier que ce long est égal à la taille // du fichier - 8, mais ça aurait interdit de charger des // fichiers tronqués (et déjà que c'est chiant de perdre // une partie du fichier il faut quand même pouvoir en // garder un peu... Sinon, moi je pleure :'( !!! ) - if (! Read_bytes(LBM_file,format,4)) + if (! Read_bytes(IFF_file,format,4)) break; if (!memcmp(format,"ANIM",4)) { - // An ANIM header: need to check that it encloses an ILBM - if (! Read_bytes(LBM_file,section,4)) + // An ANIM header: need to check that it encloses an image + if (! Read_bytes(IFF_file,section,4)) break; if (memcmp(section,"FORM",4)) break; - if (! Read_dword_be(LBM_file, &dummy)) + if (! Read_dword_be(IFF_file, &dummy)) break; - if (! Read_bytes(LBM_file,format,4)) + if (! Read_bytes(IFF_file,format,4)) break; } - if ( (memcmp(format,"ILBM",4)) && (memcmp(format,"PBM ",4)) ) + if ( memcmp(format,sub_type,4)) break; - // If we reach this part, file is indeed ILBM or ANIM + // If we reach this part, file is indeed ILBM/PBM or ANIM File_error=0; } while (0); - fclose(LBM_file); + fclose(IFF_file); } } +void Test_PBM(T_IO_Context * context) +{ + Test_IFF(context, "PBM "); +} +void Test_LBM(T_IO_Context * context) +{ + Test_IFF(context, "ILBM"); +} -// -- Lire un fichier au format LBM ----------------------------------------- + +// -- Lire un fichier au format IFF ----------------------------------------- byte Image_HAM; @@ -414,35 +422,35 @@ void Test_LBM(T_IO_Context * context) // Inspired by Allegro: storing a 4-character identifier as a 32bit litteral #define ID4(a,b,c,d) ((((a)&255)<<24) | (((b)&255)<<16) | (((c)&255)<<8) | (((d)&255))) -/// Skips the current section in an ILBM file. +/// Skips the current section in an IFF file. /// This function should be called while the file pointer is right /// after the 4-character code that identifies the section. -int LBM_Skip_section(void) +int IFF_Skip_section(void) { dword size; - if (!Read_dword_be(LBM_file,&size)) + if (!Read_dword_be(IFF_file,&size)) return 0; if (size&1) size++; - if (fseek(LBM_file,size,SEEK_CUR)) + if (fseek(IFF_file,size,SEEK_CUR)) return 0; return 1; } // ------------------------- Attendre une section ------------------------- -byte LBM_Wait_for(byte * expected_section) +byte IFF_Wait_for(byte * expected_section) { // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur) byte section_read[4]; - if (! Read_bytes(LBM_file,section_read,4)) + if (! Read_bytes(IFF_file,section_read,4)) return 0; while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée { - if (!LBM_Skip_section()) + if (!IFF_Skip_section()) return 0; - if (! Read_bytes(LBM_file,section_read,4)) + if (! Read_bytes(IFF_file,section_read,4)) return 0; } return 1; @@ -451,30 +459,43 @@ byte LBM_Wait_for(byte * expected_section) // Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour // en faire du chunky -byte Color_ILBM_line(word x_pos, word real_line_size, byte HBPm1) +/// +/// Decodes the color of one pixel from the ILBM line buffer. +/// @param x_pos Position of the pixel in graphic line +/// @param real_line_size Width of one bitplane in memory, in bytes +/// @param bitplanes Number of bitplanes +byte Get_IFF_color(word x_pos, word real_line_size, byte bitplanes) { - // Renvoie la couleur du pixel (ILBM) en x_pos. - // CL sera le rang auquel on extrait les bits de la couleur - byte cl = 7 - (x_pos & 7); - int ax,bh,dx; - byte bl=0; + byte shift = 7 - (x_pos & 7); + int address,masked_bit,plane; + byte color=0; - for(dx=HBPm1;dx>=0;dx--) + for(plane=bitplanes-1;plane>=0;plane--) { - //CIL_Loop - ax = (real_line_size * dx + x_pos) >> 3; - bh = (LBM_buffer[ax] >> cl) & 1; + address = (real_line_size * plane + x_pos) >> 3; + masked_bit = (IFF_buffer[address] >> shift) & 1; - bl = (bl << 1) + bh; + color = (color << 1) + masked_bit; } - return bl; + return color; } -byte HBPm1; // header.BitPlanes-1 +void Set_IFF_color(word x_pos, byte color, word real_line_size, byte bitplanes) +{ + byte shift = 7 - (x_pos & 7); + int address, plane; + + for(plane=0;plane> 3; + IFF_buffer[address] |= (color&1) << shift; + color = color >> 1; + } +} // ----------------------- Afficher une ligne ILBM ------------------------ - void Draw_ILBM_line(T_IO_Context *context, short y_pos, short real_line_size) + void Draw_IFF_line(T_IO_Context *context, short y_pos, short real_line_size, byte bitplanes) { byte color; byte red,green,blue; @@ -485,7 +506,7 @@ byte HBPm1; // header.BitPlanes-1 { for (x_pos=0; x_posWidth; x_pos++) { - Set_pixel(context, x_pos,y_pos,Color_ILBM_line(x_pos,real_line_size, HBPm1)); + Set_pixel(context, x_pos,y_pos,Get_IFF_color(x_pos,real_line_size, bitplanes)); } } else @@ -497,7 +518,7 @@ byte HBPm1; // header.BitPlanes-1 if (Image_HAM==6) for (x_pos=0; x_posWidth; x_pos++) // HAM6 { - temp=Color_ILBM_line(x_pos,real_line_size, HBPm1); + temp=Get_IFF_color(x_pos,real_line_size, bitplanes); switch (temp & 0xF0) { case 0x10: // blue @@ -523,7 +544,7 @@ byte HBPm1; // header.BitPlanes-1 else for (x_pos=0; x_posWidth; x_pos++) // HAM8 { - temp=Color_ILBM_line(x_pos,real_line_size, HBPm1); + temp=Get_IFF_color(x_pos,real_line_size, bitplanes); switch (temp & 0x03) { case 0x01: // blue @@ -550,10 +571,10 @@ byte HBPm1; // header.BitPlanes-1 } -void Load_LBM(T_IO_Context * context) +void Load_IFF(T_IO_Context * context) { char filename[MAX_PATH_CHARACTERS]; - T_LBM_Header header; + T_IFF_Header header; char format[4]; char section[4]; byte temp_byte; @@ -569,52 +590,57 @@ void Load_LBM(T_IO_Context * context) long file_size; dword dummy; byte is_anim=0; + int iff_format; Get_full_filename(filename, context->File_name, context->File_directory); File_error=0; - if ((LBM_file=fopen(filename, "rb"))) + if ((IFF_file=fopen(filename, "rb"))) { - file_size=File_length_file(LBM_file); + file_size=File_length_file(IFF_file); // FORM + size(4) - Read_bytes(LBM_file,section,4); - Read_dword_be(LBM_file,&dummy); + Read_bytes(IFF_file,section,4); + Read_dword_be(IFF_file,&dummy); - Read_bytes(LBM_file,format,4); + Read_bytes(IFF_file,format,4); if (!memcmp(format,"ANIM",4)) { is_anim=1; // Skip a bit, brother - Read_bytes(LBM_file,section,4); - Read_dword_be(LBM_file,&dummy); - Read_bytes(LBM_file,format,4); + Read_bytes(IFF_file,section,4); + Read_dword_be(IFF_file,&dummy); + Read_bytes(IFF_file,format,4); } + if (!memcmp(format,"ILBM",4)) + iff_format = FORMAT_LBM; + else + iff_format = FORMAT_PBM; - if (!LBM_Wait_for((byte *)"BMHD")) + if (!IFF_Wait_for((byte *)"BMHD")) File_error=1; - Read_dword_be(LBM_file,&dummy); + Read_dword_be(IFF_file,&dummy); // Maintenant on lit le header pour pouvoir commencer le chargement de l'image - if ( (Read_word_be(LBM_file,&header.Width)) - && (Read_word_be(LBM_file,&header.Height)) - && (Read_word_be(LBM_file,&header.X_org)) - && (Read_word_be(LBM_file,&header.Y_org)) - && (Read_byte(LBM_file,&header.BitPlanes)) - && (Read_byte(LBM_file,&header.Mask)) - && (Read_byte(LBM_file,&header.Compression)) - && (Read_byte(LBM_file,&header.Pad1)) - && (Read_word_be(LBM_file,&header.Transp_col)) - && (Read_byte(LBM_file,&header.X_aspect)) - && (Read_byte(LBM_file,&header.Y_aspect)) - && (Read_word_be(LBM_file,&header.X_screen)) - && (Read_word_be(LBM_file,&header.Y_screen)) + if ( (Read_word_be(IFF_file,&header.Width)) + && (Read_word_be(IFF_file,&header.Height)) + && (Read_word_be(IFF_file,&header.X_org)) + && (Read_word_be(IFF_file,&header.Y_org)) + && (Read_byte(IFF_file,&header.BitPlanes)) + && (Read_byte(IFF_file,&header.Mask)) + && (Read_byte(IFF_file,&header.Compression)) + && (Read_byte(IFF_file,&header.Pad1)) + && (Read_word_be(IFF_file,&header.Transp_col)) + && (Read_byte(IFF_file,&header.X_aspect)) + && (Read_byte(IFF_file,&header.Y_aspect)) + && (Read_word_be(IFF_file,&header.X_screen)) + && (Read_word_be(IFF_file,&header.Y_screen)) && header.Width && header.Height) { - if ( (header.BitPlanes) && (LBM_Wait_for((byte *)"CMAP")) ) + if ( (header.BitPlanes) && (IFF_Wait_for((byte *)"CMAP")) ) { - Read_dword_be(LBM_file,&nb_colors); + Read_dword_be(IFF_file,&nb_colors); nb_colors/=3; if (((dword)1<=2) && (nb_colors<=256) ) { - HBPm1=header.BitPlanes-1; if (header.Mask==1) header.BitPlanes++; @@ -647,7 +672,7 @@ void Load_LBM(T_IO_Context * context) if (Config.Clear_palette) memset(context->Palette,0,sizeof(T_Palette)); // On peut maintenant charger la nouvelle palette - if (Read_bytes(LBM_file,context->Palette,3*nb_colors)) + if (Read_bytes(IFF_file,context->Palette,3*nb_colors)) { if (Image_HAM) { @@ -659,13 +684,13 @@ void Load_LBM(T_IO_Context * context) // On lit l'octet de padding du CMAP si la taille est impaire if (nb_colors&1) - if (Read_byte(LBM_file,&temp_byte)) + if (Read_byte(IFF_file,&temp_byte)) File_error=20; // Keep reading sections until we find the body while (1) { - if (! Read_bytes(LBM_file,section,4)) + if (! Read_bytes(IFF_file,section,4)) { File_error=46; break; @@ -684,12 +709,12 @@ void Load_LBM(T_IO_Context * context) byte min_col; byte max_col; // - if ( (Read_dword_be(LBM_file,§ion_size)) - && (Read_word_be(LBM_file,&padding)) - && (Read_word_be(LBM_file,&rate)) - && (Read_word_be(LBM_file,&flags)) - && (Read_byte(LBM_file,&min_col)) - && (Read_byte(LBM_file,&max_col))) + if ( (Read_dword_be(IFF_file,§ion_size)) + && (Read_word_be(IFF_file,&padding)) + && (Read_word_be(IFF_file,&rate)) + && (Read_word_be(IFF_file,&flags)) + && (Read_byte(IFF_file,&min_col)) + && (Read_byte(IFF_file,&max_col))) { if (section_size == 8 && min_col != max_col) { @@ -714,7 +739,7 @@ void Load_LBM(T_IO_Context * context) else { // ignore any number of unknown sections - if (!LBM_Skip_section()) + if (!IFF_Skip_section()) { File_error=48; break; @@ -725,14 +750,17 @@ void Load_LBM(T_IO_Context * context) if ( !File_error ) { - Read_dword_be(LBM_file,§ion_size); + Read_dword_be(IFF_file,§ion_size); context->Width = header.Width; context->Height = header.Height; Original_screen_X = header.X_screen; Original_screen_Y = header.Y_screen; - Pre_load(context, context->Width,context->Height,file_size,FORMAT_LBM,PIXEL_SIMPLE,0); + Pre_load(context, context->Width,context->Height,file_size,iff_format,PIXEL_SIMPLE,0); + context->Background_transparent = header.Mask == 2; + context->Transparent_color = context->Background_transparent ? header.Transp_col : 0; + if (context->Type == CONTEXT_MAIN_IMAGE) { Main_backups->Pages->Image_mode = IMAGE_MODE_ANIMATION; @@ -756,28 +784,28 @@ void Load_LBM(T_IO_Context * context) if (!header.Compression) { // non compressé - LBM_buffer=(byte *)malloc(line_size); + IFF_buffer=(byte *)malloc(line_size); for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) { - if (Read_bytes(LBM_file,LBM_buffer,line_size)) - Draw_ILBM_line(context, y_pos,real_line_size); + 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(LBM_buffer); - LBM_buffer = NULL; + free(IFF_buffer); + IFF_buffer = NULL; } else { // compressé /*Init_lecture();*/ - LBM_buffer=(byte *)malloc(line_size); + IFF_buffer=(byte *)malloc(line_size); for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) { for (x_pos=0; ((x_pos127) { - if(Read_byte(LBM_file, &color)!=1) + if(Read_byte(IFF_file, &color)!=1) { File_error=23; break; @@ -794,21 +822,21 @@ void Load_LBM(T_IO_Context * context) b256=(short)(256-temp_byte); for (counter=0; counter<=b256; counter++) if (x_pos=line_size || Read_byte(LBM_file, &(LBM_buffer[x_pos++]))!=1) + if (x_pos>=line_size || Read_byte(IFF_file, &(IFF_buffer[x_pos++]))!=1) File_error=25; } if (!File_error) - Draw_ILBM_line(context, y_pos,real_line_size); + Draw_IFF_line(context, y_pos,real_line_size,header.BitPlanes); } - free(LBM_buffer); - LBM_buffer = NULL; + free(IFF_buffer); + IFF_buffer = NULL; /*Close_lecture();*/ } } @@ -818,17 +846,17 @@ void Load_LBM(T_IO_Context * context) if (!header.Compression) { // non compressé - LBM_buffer=(byte *)malloc(real_line_size); + IFF_buffer=(byte *)malloc(real_line_size); for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) { - if (Read_bytes(LBM_file,LBM_buffer,real_line_size)) + if (Read_bytes(IFF_file,IFF_buffer,real_line_size)) for (x_pos=0; x_posWidth; x_pos++) - Set_pixel(context, x_pos,y_pos,LBM_buffer[x_pos]); + Set_pixel(context, x_pos,y_pos,IFF_buffer[x_pos]); else File_error=26; } - free(LBM_buffer); - LBM_buffer = NULL; + free(IFF_buffer); + IFF_buffer = NULL; } else { // compressé @@ -837,14 +865,14 @@ void Load_LBM(T_IO_Context * context) { for (x_pos=0; ((x_pos127) { - if(Read_byte(LBM_file, &color)!=1) + if(Read_byte(IFF_file, &color)!=1) { File_error=28; break; @@ -857,7 +885,7 @@ void Load_LBM(T_IO_Context * context) for (counter=0; counter<=temp_byte; counter++) { byte byte_read=0; - if(Read_byte(LBM_file, &byte_read)!=1) + if(Read_byte(IFF_file, &byte_read)!=1) { File_error=29; break; @@ -877,21 +905,21 @@ void Load_LBM(T_IO_Context * context) // Just loaded the first image successfully : now keep reading // FORM + size(4) - if (!Read_bytes(LBM_file,section,4)) + if (!Read_bytes(IFF_file,section,4)) break; - Read_dword_be(LBM_file,&dummy); + Read_dword_be(IFF_file,&dummy); // ILBM, hopefully - Read_bytes(LBM_file,format,4); - if (!LBM_Wait_for((byte *)"DLTA")) + Read_bytes(IFF_file,format,4); + if (!IFF_Wait_for((byte *)"DLTA")) { File_error=1; break; } Set_loading_layer(context, context->Current_layer+1); - Read_dword_be(LBM_file,&delta_size); - fseek(LBM_file, delta_size + (delta_size & 1), SEEK_CUR); + Read_dword_be(IFF_file,&delta_size); + fseek(IFF_file, delta_size + (delta_size & 1), SEEK_CUR); } */ } @@ -913,40 +941,40 @@ void Load_LBM(T_IO_Context * context) else File_error=1; - fclose(LBM_file); + fclose(IFF_file); } else File_error=1; } -// -- Sauver un fichier au format LBM --------------------------------------- +// -- Sauver un fichier au format IFF --------------------------------------- - byte LBM_color_list[129]; - word LBM_list_size; - byte LBM_repetition_mode; + byte IFF_color_list[129]; + word IFF_list_size; + byte IFF_repetition_mode; // ------------- Ecrire les couleurs que l'on vient de traiter ------------ void Transfer_colors(void) { byte index; - if (LBM_list_size>0) + if (IFF_list_size>0) { - if (LBM_repetition_mode) + if (IFF_repetition_mode) { - Write_one_byte(LBM_file,257-LBM_list_size); - Write_one_byte(LBM_file,LBM_color_list[0]); + Write_one_byte(IFF_file,257-IFF_list_size); + Write_one_byte(IFF_file,IFF_color_list[0]); } else { - Write_one_byte(LBM_file,LBM_list_size-1); - for (index=0; index et on a 3 couleurs qui se suivent { - LBM_list_size-=2; + IFF_list_size-=2; Transfer_colors(); - LBM_color_list[0]=color; - LBM_color_list[1]=color; - LBM_color_list[2]=color; - LBM_list_size=3; - LBM_repetition_mode=1; + IFF_color_list[0]=color; + IFF_color_list[1]=color; + IFF_color_list[2]=color; + IFF_list_size=3; + IFF_repetition_mode=1; } } else // La couleur n'est pas la même que la précédente { - if (!LBM_repetition_mode) // On conserve le mode... + if (!IFF_repetition_mode) // On conserve le mode... { - LBM_color_list[LBM_list_size++]=color; - if (LBM_list_size==128) + IFF_color_list[IFF_list_size++]=color; + if (IFF_list_size==128) Transfer_colors(); } else // On change de mode... { Transfer_colors(); - LBM_color_list[LBM_list_size]=color; - LBM_list_size++; + IFF_color_list[IFF_list_size]=color; + IFF_list_size++; } } } } -void Save_LBM(T_IO_Context * context) +void Save_IFF(T_IO_Context * context) { char filename[MAX_PATH_CHARACTERS]; - T_LBM_Header header; + T_IFF_Header header; word x_pos; word y_pos; byte temp_byte; - word real_width; int file_size; int i; + int palette_entries; + byte bit_depth; + + if (context->Format == FORMAT_LBM) + { + // Check how many bits are used by pixel colors + for (y_pos=0; y_posHeight; y_pos++) + for (x_pos=0; x_posWidth; x_pos++) + temp_byte |= Get_pixel(context, x_pos,y_pos); + bit_depth=0; + do + { + bit_depth++; + temp_byte>>=1; + } while (temp_byte); + } + else // FORMAT_PBM + { + bit_depth=8; + } + palette_entries = 1<File_name, context->File_directory); // Ouverture du fichier - if ((LBM_file=fopen(filename,"wb"))) + if ((IFF_file=fopen(filename,"wb"))) { - Write_bytes(LBM_file,"FORM",4); - Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin + setvbuf(IFF_file, NULL, _IOFBF, 64*1024); + + Write_bytes(IFF_file,"FORM",4); + Write_dword_be(IFF_file,0); // On mettra la taille à jour à la fin - Write_bytes(LBM_file,"PBM BMHD",8); - Write_dword_be(LBM_file,20); - - // On corrige la largeur de l'image pour qu'elle soit multiple de 2 - real_width=context->Width+(context->Width&1); + if (context->Format == FORMAT_LBM) + Write_bytes(IFF_file,"ILBM",4); + else + Write_bytes(IFF_file,"PBM ",4); + + Write_bytes(IFF_file,"BMHD",4); + Write_dword_be(IFF_file,20); header.Width=context->Width; header.Height=context->Height; header.X_org=0; header.Y_org=0; - header.BitPlanes=8; - header.Mask=0; + header.BitPlanes=bit_depth; + header.Mask=context->Background_transparent ? 2 : 0; header.Compression=1; header.Pad1=0; - header.Transp_col=Back_color; - header.X_aspect=1; - header.Y_aspect=1; - header.X_screen = Screen_width; - header.Y_screen = Screen_height; + header.Transp_col=context->Background_transparent ? context->Transparent_color : 0; + header.X_aspect=context->Ratio == PIXEL_WIDE ? 2 : 1; + header.Y_aspect=context->Ratio == PIXEL_TALL ? 2 : 1; + header.X_screen = context->Width;// Screen_width?; + header.Y_screen = context->Height;// Screen_height?; - Write_word_be(LBM_file,header.Width); - Write_word_be(LBM_file,header.Height); - Write_word_be(LBM_file,header.X_org); - Write_word_be(LBM_file,header.Y_org); - Write_bytes(LBM_file,&header.BitPlanes,1); - Write_bytes(LBM_file,&header.Mask,1); - Write_bytes(LBM_file,&header.Compression,1); - Write_bytes(LBM_file,&header.Pad1,1); - Write_word_be(LBM_file,header.Transp_col); - Write_bytes(LBM_file,&header.X_aspect,1); - Write_bytes(LBM_file,&header.Y_aspect,1); - Write_word_be(LBM_file,header.X_screen); - Write_word_be(LBM_file,header.Y_screen); + Write_word_be(IFF_file,header.Width); + Write_word_be(IFF_file,header.Height); + Write_word_be(IFF_file,header.X_org); + Write_word_be(IFF_file,header.Y_org); + Write_bytes(IFF_file,&header.BitPlanes,1); + Write_bytes(IFF_file,&header.Mask,1); + Write_bytes(IFF_file,&header.Compression,1); + Write_bytes(IFF_file,&header.Pad1,1); + Write_word_be(IFF_file,header.Transp_col); + Write_bytes(IFF_file,&header.X_aspect,1); + Write_bytes(IFF_file,&header.Y_aspect,1); + Write_word_be(IFF_file,header.X_screen); + Write_word_be(IFF_file,header.Y_screen); - Write_bytes(LBM_file,"CMAP",4); - Write_dword_be(LBM_file,sizeof(T_Palette)); + Write_bytes(IFF_file,"CMAP",4); + Write_dword_be(IFF_file,palette_entries*3); - Write_bytes(LBM_file,context->Palette,sizeof(T_Palette)); + Write_bytes(IFF_file,context->Palette,palette_entries*3); for (i=0; iColor_cycles; i++) { @@ -1075,61 +1128,116 @@ void Save_LBM(T_IO_Context * context) flags|= context->Cycle_range[i].Speed?1:0; // Cycling or not flags|= context->Cycle_range[i].Inverse?2:0; // Inverted - Write_bytes(LBM_file,"CRNG",4); - Write_dword_be(LBM_file,8); // Section size - Write_word_be(LBM_file,0); // Padding - Write_word_be(LBM_file,context->Cycle_range[i].Speed*78); // Rate - Write_word_be(LBM_file,flags); // Flags - Write_byte(LBM_file,context->Cycle_range[i].Start); // Min color - Write_byte(LBM_file,context->Cycle_range[i].End); // Max color + Write_bytes(IFF_file,"CRNG",4); + Write_dword_be(IFF_file,8); // Section size + Write_word_be(IFF_file,0); // Padding + Write_word_be(IFF_file,context->Cycle_range[i].Speed*78); // Rate + Write_word_be(IFF_file,flags); // Flags + Write_byte(IFF_file,context->Cycle_range[i].Start); // Min color + Write_byte(IFF_file,context->Cycle_range[i].End); // Max color // No padding, size is multiple of 2 } - Write_bytes(LBM_file,"BODY",4); - Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin + Write_bytes(IFF_file,"BODY",4); + Write_dword_be(IFF_file,0); // On mettra la taille à jour à la fin - Init_write_buffer(); - - LBM_list_size=0; - - for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) + if (context->Format == FORMAT_LBM) { - for (x_pos=0; ((x_posWidth & 15) + { + real_line_size=( (context->Width+16) >> 4 ) << 4; + 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); + + // Start encoding + IFF_list_size=0; + for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) + { + // Dispatch the pixel into planes + memset(IFF_buffer,0,line_size); + for (x_pos=0; x_posWidth; x_pos++) + Set_IFF_color(x_pos, Get_pixel(context, x_pos,y_pos), real_line_size, header.BitPlanes); + + if (context->Width&1) // odd width fix + Set_IFF_color(x_pos, 0, real_line_size, header.BitPlanes); + + // encode the resulting sequence of bytes + if (header.Compression) + { + int plane_width=line_size/header.BitPlanes; + int plane; + + for (plane=0; planeHeight) && (!File_error)); y_pos++) + { + for (x_pos=0; ((x_posWidth) && (!File_error)); x_pos++) + New_color(Get_pixel(context, x_pos,y_pos)); + + if (context->Width&1) // odd width fix + New_color(0); + + if (!File_error) + Transfer_colors(); + } + } + fclose(IFF_file); if (!File_error) { file_size=File_length(filename); - LBM_file=fopen(filename,"rb+"); - fseek(LBM_file,820+context->Color_cycles*16,SEEK_SET); - Write_dword_be(LBM_file,file_size-824-context->Color_cycles*16); + IFF_file=fopen(filename,"rb+"); + fseek(IFF_file,52+palette_entries*3+context->Color_cycles*16,SEEK_SET); + Write_dword_be(IFF_file,file_size-56-palette_entries*3-context->Color_cycles*16); if (!File_error) { - fseek(LBM_file,4,SEEK_SET); + fseek(IFF_file,4,SEEK_SET); // Si la taille de la section de l'image (taille fichier-8) est // impaire, on rajoute un 0 (Padding) à la fin. if ((file_size) & 1) { - Write_dword_be(LBM_file,file_size-7); - fseek(LBM_file,0,SEEK_END); + Write_dword_be(IFF_file,file_size-7); + fseek(IFF_file,0,SEEK_END); temp_byte=0; - if (! Write_bytes(LBM_file,&temp_byte,1)) + if (! Write_bytes(IFF_file,&temp_byte,1)) File_error=1; } else - Write_dword_be(LBM_file,file_size-8); + Write_dword_be(IFF_file,file_size-8); - fclose(LBM_file); + fclose(IFF_file); if (File_error) remove(filename); @@ -1137,7 +1245,7 @@ void Save_LBM(T_IO_Context * context) else { File_error=1; - fclose(LBM_file); + fclose(IFF_file); remove(filename); } } @@ -1645,7 +1753,8 @@ void Save_BMP(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { - + setvbuf(file, NULL, _IOFBF, 64*1024); + // Image width must be a multiple of 4 bytes line_size = context->Width; if (line_size & 3) @@ -1703,8 +1812,6 @@ void Save_BMP(T_IO_Context * context) if (Write_bytes(file,local_palette,1024)) { - Init_write_buffer(); - // ... Et Bill, il a dit: "OK les gars! Mais seulement si vous rangez // les pixels dans l'ordre inverse, mais que sur les Y quand-même // parce que faut pas pousser." @@ -1712,7 +1819,6 @@ void Save_BMP(T_IO_Context * context) for (x_pos=0; x_posWidth; x_pos++) { - color=(LBM_buffer[x_pos/reduction]>>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask; + color=(IFF_buffer[x_pos/reduction]>>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask; Set_pixel(context, x_pos,y_pos,color); } } @@ -3118,11 +3224,10 @@ void Load_PCX(T_IO_Context * context) { line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; real_line_size=(short)PCX_header.Bytes_per_plane_line<<3; - // On se sert de données LBM car le dessin de ligne en moins de 256 + // On se sert de données ILBM car le dessin de ligne en moins de 256 // couleurs se fait comme avec la structure ILBM. Image_HAM=0; - HBPm1=PCX_header.Plane-1; - LBM_buffer=(byte *)malloc(line_size); + IFF_buffer=(byte *)malloc(line_size); // Chargement de l'image if (PCX_header.Compression) // Image compressée @@ -3181,7 +3286,7 @@ void Load_PCX(T_IO_Context * context) { for (index=0; indexHeight) && (!File_error);y_pos++) { - if ((width_read=Read_bytes(file,LBM_buffer,line_size))) + if ((width_read=Read_bytes(file,IFF_buffer,line_size))) { if (PCX_header.Plane==1) for (x_pos=0; x_posWidth;x_pos++) - Set_pixel(context, x_pos,y_pos,LBM_buffer[x_pos]); + Set_pixel(context, x_pos,y_pos,IFF_buffer[x_pos]); else { if (PCX_header.Depth==1) - Draw_ILBM_line(context, y_pos,real_line_size); + Draw_IFF_line(context, y_pos,real_line_size,PCX_header.Plane); else Draw_PCX_line(context, y_pos,PCX_header.Depth); } @@ -3224,8 +3329,8 @@ void Load_PCX(T_IO_Context * context) } } - free(LBM_buffer); - LBM_buffer = NULL; + free(IFF_buffer); + IFF_buffer = NULL; } } } @@ -3339,7 +3444,8 @@ void Save_PCX(T_IO_Context * context) if ((file=fopen(filename,"wb"))) { - + setvbuf(file, NULL, _IOFBF, 64*1024); + PCX_header.Manufacturer=10; PCX_header.Version=5; PCX_header.Compression=1; @@ -3380,8 +3486,6 @@ void Save_PCX(T_IO_Context * context) { line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; - Init_write_buffer(); - for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) { pixel_read=Get_pixel(context, 0,y_pos); @@ -3411,8 +3515,6 @@ void Save_PCX(T_IO_Context * context) if (!File_error) Write_one_byte(file,12); - End_write(file); - // Ecriture de la palette if (!File_error) { @@ -3526,13 +3628,13 @@ void Load_SCx(T_IO_Context * context) if (!SCx_header.Planes) { // 256 couleurs (raw) - LBM_buffer=(byte *)malloc(context->Width); + IFF_buffer=(byte *)malloc(context->Width); for (y_pos=0;(y_posHeight) && (!File_error);y_pos++) { - if (Read_bytes(file,LBM_buffer,context->Width)) + if (Read_bytes(file,IFF_buffer,context->Width)) for (x_pos=0; x_posWidth;x_pos++) - Set_pixel(context, x_pos,y_pos,LBM_buffer[x_pos]); + Set_pixel(context, x_pos,y_pos,IFF_buffer[x_pos]); else File_error=2; } @@ -3541,20 +3643,19 @@ void Load_SCx(T_IO_Context * context) { // moins de 256 couleurs (planar) size=((context->Width+7)>>3)*SCx_header.Planes; real_size=(size/SCx_header.Planes)<<3; - LBM_buffer=(byte *)malloc(size); - HBPm1=SCx_header.Planes-1; + IFF_buffer=(byte *)malloc(size); Image_HAM=0; for (y_pos=0;(y_posHeight) && (!File_error);y_pos++) { - if (Read_bytes(file,LBM_buffer,size)) - Draw_ILBM_line(context, y_pos,real_size); + if (Read_bytes(file,IFF_buffer,size)) + Draw_IFF_line(context, y_pos,real_size,SCx_header.Planes); else File_error=2; } } - free(LBM_buffer); - LBM_buffer = NULL; + free(IFF_buffer); + IFF_buffer = NULL; } else File_error=1; @@ -3609,6 +3710,8 @@ void Save_SCx(T_IO_Context * context) if ((file=fopen(filename,"wb"))) { T_Palette palette_64; + + setvbuf(file, NULL, _IOFBF, 64*1024); memcpy(palette_64,context->Palette,sizeof(T_Palette)); Palette_256_to_64(palette_64); @@ -3626,13 +3729,10 @@ void Save_SCx(T_IO_Context * context) && Write_bytes(file,&palette_64,sizeof(T_Palette)) ) { - Init_write_buffer(); - for (y_pos=0; ((y_posHeight) && (!File_error)); y_pos++) for (x_pos=0; x_posWidth; x_pos++) Write_one_byte(file,Get_pixel(context, x_pos,y_pos)); - End_write(file); fclose(file); if (File_error) @@ -3669,7 +3769,7 @@ void Save_XPM(T_IO_Context* context) File_error = 1; return; } - + setvbuf(file, NULL, _IOFBF, 64*1024); fprintf(file, "/* XPM */\nstatic char* pixmap[] = {\n"); fprintf(file, "\"%d %d 256 2\",\n", context->Width, context->Height); @@ -3733,7 +3833,7 @@ int PNG_read_unknown_chunk(png_structp ptr, png_unknown_chunkp chunk) if (!strcmp((const char *)chunk->name, "crNg")) { - // Color animation. Similar to a LBM CRNG chunk. + // Color animation. Similar to a CRNG chunk in an IFF file. unsigned int i; byte *chunk_ptr = chunk->data; @@ -4126,6 +4226,8 @@ void Save_PNG(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + /* initialisation */ if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) && (info_ptr = png_create_info_struct(png_ptr))) diff --git a/src/helpfile.h b/src/helpfile.h index 53a68773..4e11a4fb 100644 --- a/src/helpfile.h +++ b/src/helpfile.h @@ -512,7 +512,7 @@ static const T_Help_table helptable_credits[] = HELP_TEXT (" CEL,KCF : K.O.S. (KISekae Set system)") HELP_TEXT (" GIF : Compuserve") HELP_TEXT (" IMG : Bivas (W. Wiedmann?)") - HELP_TEXT (" LBM : Electronic Arts") + HELP_TEXT (" IFF : Electronic Arts") HELP_TEXT (" PAL : ermmh... nobody (?)") HELP_TEXT (" PCX : Z-Soft") HELP_TEXT (" PI1,PC1 : Degas Elite") @@ -1204,7 +1204,7 @@ static const T_Help_table helptable_grad_rect[] = HELP_TEXT ("") HELP_TEXT ("These options allow you to use animation of") HELP_TEXT ("colors: Grafx2 will shift palette entries") - HELP_TEXT ("at real-time. Note that only the LBM file") + HELP_TEXT ("at real-time. Note that only the IFF file") HELP_TEXT ("format can record these settings, and very") HELP_TEXT ("few image viewers will play it back.") HELP_TEXT ("") diff --git a/src/init.c b/src/init.c index 4ec36fc1..2f73d373 100644 --- a/src/init.c +++ b/src/init.c @@ -2190,7 +2190,7 @@ int Load_CFG(int reload_all) break; case CHUNK_GRADIENTS: // Infos sur les dégradés // The gradients chunk is deprecated since the data - // is now loaded/saved in GIF and LBM formats. + // is now loaded/saved in GIF and IFF formats. // The chunk will be completely ignored. /*if (reload_all) { @@ -2518,7 +2518,7 @@ int Save_CFG(void) // Sauvegarde des informations des dégradés // The gradients chunk is deprecated since the data - // is now loaded/saved in GIF and LBM formats. + // is now loaded/saved in GIF and IFF formats. /* Chunk.Number=CHUNK_GRADIENTS; Chunk.Size=14*16+1; diff --git a/src/loadsave.c b/src/loadsave.c index 818a8c07..0d16f776 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -57,10 +57,11 @@ void Test_PKM(T_IO_Context *); void Load_PKM(T_IO_Context *); void Save_PKM(T_IO_Context *); -// -- LBM ------------------------------------------------------------------- +// -- IFF ------------------------------------------------------------------- void Test_LBM(T_IO_Context *); -void Load_LBM(T_IO_Context *); -void Save_LBM(T_IO_Context *); +void Test_PBM(T_IO_Context *); +void Load_IFF(T_IO_Context *); +void Save_IFF(T_IO_Context *); // -- GIF ------------------------------------------------------------------- void Test_GIF(T_IO_Context *); @@ -142,12 +143,12 @@ void Save_PNG(T_IO_Context *); #endif // -- SDL_Image ------------------------------------------------------------- -// (TGA, BMP, PNM, XPM, XCF, PCX, GIF, JPG, TIF, LBM, PNG, ICO) +// (TGA, BMP, PNM, XPM, XCF, PCX, GIF, JPG, TIF, IFF, PNG, ICO) void Load_SDL_Image(T_IO_Context *); // ENUM Name TestFunc LoadFunc SaveFunc PalOnly Comment Layers Ext Exts T_Format File_formats[] = { - {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;cm5"}, + {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;iff;lbm;ilbm;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;koala;fli;bml;cdu;prg;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;cm5"}, {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"}, {FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 0, 1, 1, "gif", "gif"}, #ifndef __no_pnglib__ @@ -156,7 +157,8 @@ T_Format File_formats[] = { {FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 0, 0, 0, "bmp", "bmp"}, {FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 0, 0, 0, "pcx", "pcx"}, {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, 0, "pkm", "pkm"}, - {FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 0, 0, 0, "lbm", "lbm;iff;ilbm"}, + {FORMAT_LBM, " lbm", Test_LBM, Load_IFF, Save_IFF, 0, 0, 0, "iff", "iff;lbm;ilbm"}, + {FORMAT_PBM, " pbm", Test_PBM, Load_IFF, Save_IFF, 0, 0, 0, "iff", "iff;pbm"}, {FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 0, 0, 0, "img", "img"}, {FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 0, 0, 0, "sc?", "sci;scq;scf;scn;sco"}, {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, 0, "pi1", "pi1"}, @@ -556,36 +558,12 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size, // Gestion des lectures et écritures // ///////////////////////////////////////////////////////////////////////////// -byte * Write_buffer; -word Write_buffer_index; - -void Init_write_buffer(void) -{ - Write_buffer=(byte *)malloc(64000); - Write_buffer_index=0; -} - void Write_one_byte(FILE *file, byte b) { - Write_buffer[Write_buffer_index++]=b; - if (Write_buffer_index>=64000) - { - if (! Write_bytes(file,Write_buffer,64000)) + if (! Write_byte(file,b)) File_error=1; - Write_buffer_index=0; - } } -void End_write(FILE *file) -{ - if (Write_buffer_index) - if (! Write_bytes(file,Write_buffer,Write_buffer_index)) - File_error=1; - free(Write_buffer); - Write_buffer = NULL; -} - - ///////////////////////////////////////////////////////////////////////////// // -------- Modifier la valeur du code d'erreur d'accès à un fichier -------- diff --git a/src/loadsave.h b/src/loadsave.h index f4a7e46f..9e9c06b3 100644 --- a/src/loadsave.h +++ b/src/loadsave.h @@ -259,8 +259,6 @@ void Set_file_error(int value); /* void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio); */ -void Init_write_buffer(void); void Write_one_byte(FILE *file, byte b); -void End_write(FILE *file); #endif diff --git a/src/miscfileformats.c b/src/miscfileformats.c index 9d267a36..c8d1c487 100644 --- a/src/miscfileformats.c +++ b/src/miscfileformats.c @@ -192,6 +192,9 @@ void Save_PAL(T_IO_Context * context) if ((file=fopen(filename,"w"))) { int i; + + setvbuf(file, NULL, _IOFBF, 64*1024); + if (fputs("JASC-PAL\n0100\n256\n", file)==EOF) File_error=1; for (i = 0; i < 256 && File_error==0; i++) @@ -555,6 +558,8 @@ void Save_PKM(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + // Ecriture du header if (Write_bytes(file,&header.Ident,3) && Write_byte(file,header.Method) && @@ -565,7 +570,6 @@ void Save_PKM(T_IO_Context * context) Write_bytes(file,&header.Palette,sizeof(T_Palette)) && Write_word_le(file,header.Jump)) { - Init_write_buffer(); // Ecriture du commentaire // (Compteur_de_pixels est utilisé ici comme simple index de comptage) @@ -655,8 +659,6 @@ void Save_PKM(T_IO_Context * context) } } } - - End_write(file); } else File_error=1; @@ -909,6 +911,8 @@ void Save_CEL(T_IO_Context * context) Get_full_filename(filename, context->File_name, context->File_directory); if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + // On regarde si des couleurs >16 sont utilisées dans l'image for (x_pos=16;((x_pos<256) && (!color_usage[x_pos]));x_pos++); @@ -924,7 +928,6 @@ void Save_CEL(T_IO_Context * context) ) { // Sauvegarde de l'image - Init_write_buffer(); for (y_pos=0;((y_posHeight) && (!File_error));y_pos++) { for (x_pos=0;((x_posWidth) && (!File_error));x_pos++) @@ -939,7 +942,6 @@ void Save_CEL(T_IO_Context * context) if ((x_pos & 1)==1) Write_one_byte(file,last_byte); } - End_write(file); } else File_error=1; @@ -990,11 +992,9 @@ void Save_CEL(T_IO_Context * context) ) { // Sauvegarde de l'image - Init_write_buffer(); for (y_pos=0;((y_posFile_name, context->File_directory); if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); // Sauvegarde de la palette // On regarde si des couleurs >16 sont utilisées dans l'image @@ -1545,6 +1546,8 @@ void Save_PI1(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + // allocation d'un buffer mémoire buffer=(byte *)malloc(32066); // Codage de la résolution @@ -1882,6 +1885,8 @@ void Save_PC1(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + // Allocation des buffers mémoire bufferdecomp=(byte *)malloc(32000); buffercomp =(byte *)malloc(64066); @@ -2055,6 +2060,8 @@ void Save_NEO(T_IO_Context * context) // Ouverture du fichier if ((file=fopen(filename,"wb"))) { + setvbuf(file, NULL, _IOFBF, 64*1024); + // allocation d'un buffer mémoire buffer=(byte *)malloc(32128); // Codage de la résolution @@ -2656,6 +2663,8 @@ int Save_C64_hires(T_IO_Context *context, char *filename, byte saveWhat, byte lo return 1; } + setvbuf(file, NULL, _IOFBF, 64*1024); + if (loadAddr) { Write_byte(file,0); @@ -2766,7 +2775,9 @@ int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte lo File_error = 1; return 1; } - + + setvbuf(file, NULL, _IOFBF, 64*1024); + if (loadAddr) { Write_byte(file,0); @@ -2812,7 +2823,9 @@ int Save_C64_fli(char *filename, byte saveWhat, byte loadAddr) File_error = 1; return 1; } - + + setvbuf(file, NULL, _IOFBF, 64*1024); + if (loadAddr) { file_buffer[0]=0; @@ -2962,7 +2975,7 @@ void Save_SCR(T_IO_Context * context) fclose(file); free (output); - output = NULL; + output = NULL; File_error = 0; } @@ -3172,7 +3185,8 @@ void Save_CM5(T_IO_Context* context) File_error = 1; return; } - + setvbuf(file, NULL, _IOFBF, 64*1024); + // Write layer 0 Set_saving_layer(context, 0); Write_byte(file, Get_pixel(context, 0, 0)); @@ -3199,7 +3213,8 @@ void Save_CM5(T_IO_Context* context) File_error = 2; return; } - + setvbuf(file, NULL, _IOFBF, 64*1024); + Set_saving_layer(context, 4); for (ty = 0; ty < 256; ty++)