diff --git a/Makefile b/Makefile
index f3e7bc5d..cf0e13f3 100644
--- a/Makefile
+++ b/Makefile
@@ -279,7 +279,7 @@ endif
.PHONY : all debug release clean depend zip version force install uninstall
# This is the list of the objects we want to build. Dependancies are built by "make depend" automatically.
-OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ)
+OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o
SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png
diff --git a/fileformats.c b/fileformats.c
new file mode 100644
index 00000000..5e8052da
--- /dev/null
+++ b/fileformats.c
@@ -0,0 +1,3496 @@
+/* Grafx2 - The Ultimate 256-color bitmap paint program
+
+ Copyright 2009 Petter Lindquist
+ Copyright 2008 Yves Rizoud
+ Copyright 2008 Franck Charlet
+ Copyright 2007 Adrien Destugues
+ Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
+
+ Grafx2 is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2
+ of the License.
+
+ Grafx2 is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Grafx2; if not, see
+*/
+
+///@file fileformats.c
+/// Saving and loading different picture formats.
+
+#ifndef __no_pnglib__
+#include
+#endif
+
+#include "errors.h"
+#include "global.h"
+#include "loadsave.h"
+#include "misc.h"
+#include "struct.h"
+
+//////////////////////////////////// IMG ////////////////////////////////////
+
+// -- Tester si un fichier est au format IMG --------------------------------
+void Test_IMG(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ T_IMG_Header IMG_header;
+ byte signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0};
+
+
+ Get_full_filename(filename,0);
+
+ File_error=1;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ // Lecture et vérification de la signature
+ if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header)))
+ {
+ if ( (!memcmp(IMG_header.Filler1,signature,6))
+ && IMG_header.Width && IMG_header.Height)
+ File_error=0;
+ }
+ // Fermeture du fichier
+ fclose(file);
+ }
+}
+
+
+// -- Lire un fichier au format IMG -----------------------------------------
+void Load_IMG(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ byte * buffer;
+ FILE *file;
+ word x_pos,y_pos;
+ long width_read;
+ long file_size;
+ T_IMG_Header IMG_header;
+
+ Get_full_filename(filename,0);
+ File_error=0;
+
+ if ((file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(file);
+
+ if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header)))
+ {
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ IMG_header.Width = SDL_Swap16(IMG_header.Width);
+ IMG_header.Height = SDL_Swap16(IMG_header.Height);
+#endif
+
+ buffer=(byte *)malloc(IMG_header.Width);
+
+ Init_preview(IMG_header.Width,IMG_header.Height,file_size,FORMAT_IMG,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ memcpy(Main_palette,IMG_header.Palette,sizeof(T_Palette));
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ Main_image_width=IMG_header.Width;
+ Main_image_height=IMG_header.Height;
+ width_read=IMG_header.Width;
+
+ for (y_pos=0;(y_pos=0)?temp:0;
+ }
+ if ((i-7)&2)
+ {
+ temp=Main_palette[j].G-16;
+ Main_palette[color].G=(temp>=0)?temp:0;
+ }
+ if ((i-7)&4)
+ {
+ temp=Main_palette[j].B-16;
+ Main_palette[color].B=(temp>=0)?temp:0;
+ }
+ }
+ }
+ }
+ // Ici, il reste les 16 dernières couleurs à modifier
+ for (i=240,j=0; j<16; i++,j++)
+ {
+ temp=Main_palette[j].R+8;
+ Main_palette[i].R=(temp<63)?temp:63;
+ temp=Main_palette[j].G+8;
+ Main_palette[i].G=(temp<63)?temp:63;
+ temp=Main_palette[j].B+8;
+ Main_palette[i].B=(temp<63)?temp:63;
+ }
+ }
+ else if (Image_HAM==8)
+ {
+ for (i=1; i<=3; i++)
+ {
+ // On recopie la palette de base
+ memcpy(Main_palette+(i<<6),Main_palette,192);
+ // On modifie les teintes de cette palette
+ for (j=0; j<64; j++)
+ {
+ color=(i<<6)+j;
+ switch (i)
+ {
+ case 1 :
+ temp=Main_palette[j].R+16;
+ Main_palette[color].R=(temp<63)?temp:63;
+ break;
+ case 2 :
+ temp=Main_palette[j].G+16;
+ Main_palette[color].G=(temp<63)?temp:63;
+ break;
+ default:
+ temp=Main_palette[j].B+16;
+ Main_palette[color].B=(temp<63)?temp:63;
+ }
+ }
+ }
+ }
+ else // Image 64 couleurs sauvée en 32.
+ {
+ for (i=0; i<32; i++)
+ {
+ j=i+32;
+ Main_palette[j].R=Main_palette[i].R>>1;
+ Main_palette[j].G=Main_palette[i].G>>1;
+ Main_palette[j].B=Main_palette[i].B>>1;
+ }
+ }
+ }
+
+ // ------------------------- Attendre une section -------------------------
+ byte Wait_for(byte * expected_section)
+ {
+ // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
+ dword Taille_section;
+ byte section_read[4];
+
+ if (! Read_bytes(LBM_file,section_read,4))
+ return 0;
+ while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée
+ {
+ if (!Read_dword_be(LBM_file,&Taille_section))
+ return 0;
+ if (Taille_section&1)
+ Taille_section++;
+ if (fseek(LBM_file,Taille_section,SEEK_CUR))
+ return 0;
+ if (! Read_bytes(LBM_file,section_read,4))
+ return 0;
+ }
+ return 1;
+ }
+
+// 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)
+{
+ // 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;
+
+ for(dx=HBPm1;dx>=0;dx--)
+ {
+ //CIL_Loop
+ ax = (real_line_size * dx + x_pos) >> 3;
+ bh = (LBM_buffer[ax] >> cl) & 1;
+
+ bl = (bl << 1) + bh;
+ }
+
+ return bl;
+}
+
+byte HBPm1; // header.BitPlanes-1
+
+ // ----------------------- Afficher une ligne ILBM ------------------------
+ void Draw_ILBM_line(short y_pos, short real_line_size)
+ {
+ byte color;
+ byte red,green,blue;
+ byte temp;
+ short x_pos;
+
+ if (Image_HAM<=1) // ILBM
+ {
+ for (x_pos=0; x_pos>2;
+ color=Best_color(red,green,blue);
+ break;
+ case 0x02: // red
+ red=temp>>2;
+ color=Best_color(red,green,blue);
+ break;
+ case 0x03: // green
+ green=temp>>2;
+ color=Best_color(red,green,blue);
+ break;
+ default: // Nouvelle couleur
+ color=temp;
+ red=Main_palette[color].R;
+ green =Main_palette[color].G;
+ blue =Main_palette[color].B;
+ }
+ Pixel_load_function(x_pos,y_pos,color);
+ }
+ }
+ }
+
+
+void Load_LBM(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ T_LBM_Header header;
+ char format[4];
+ char section[4];
+ byte temp_byte;
+ short b256;
+ dword nb_colors;
+ dword image_size;
+ short x_pos;
+ short y_pos;
+ short counter;
+ short line_size; // Taille d'une ligne en octets
+ short real_line_size; // Taille d'une ligne en pixels
+ byte color;
+ long file_size;
+ dword dummy;
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+
+ if ((LBM_file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(LBM_file);
+
+ // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été)
+ Read_bytes(LBM_file,section,4);
+ Read_dword_be(LBM_file,&dummy);
+ Read_bytes(LBM_file,format,4);
+ if (!Wait_for((byte *)"BMHD"))
+ File_error=1;
+ Read_dword_be(LBM_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))
+ && header.Width && header.Height)
+ {
+ if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) )
+ {
+ Read_dword_be(LBM_file,&nb_colors);
+ nb_colors/=3;
+
+ if (((dword)1< il faut copier les 32 coul.
+ } // sur les 32 suivantes et assombrir ces dernières.
+ else
+ {
+ if ((header.BitPlanes==6) || (header.BitPlanes==8))
+ Image_HAM=header.BitPlanes;
+ else
+ /* File_error=1;*/ /* C'est censé être incorrect mais j'ai */
+ Image_HAM=0; /* trouvé un fichier comme ça, alors... */
+ }
+ }
+ else
+ Image_HAM=0;
+
+ if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) )
+ {
+ HBPm1=header.BitPlanes-1;
+ if (header.Mask==1)
+ header.BitPlanes++;
+
+ // Deluxe paint le fait... alors on le fait...
+ Back_color=header.Transp_col;
+
+ // On commence par passer la palette en 256 comme ça, si la nouvelle
+ // palette a moins de 256 coul, la précédente ne souffrira pas d'un
+ // assombrissement préjudiciable.
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+ else
+ Palette_64_to_256(Main_palette);
+ // On peut maintenant charger la nouvelle palette
+ if (Read_bytes(LBM_file,Main_palette,3*nb_colors))
+ {
+ Palette_256_to_64(Main_palette);
+ if (Image_HAM)
+ Adapt_palette_HAM();
+ Palette_64_to_256(Main_palette);
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ // On lit l'octet de padding du CMAP si la taille est impaire
+ if (nb_colors&1)
+ if (Read_byte(LBM_file,&temp_byte))
+ File_error=2;
+
+ if ( (Wait_for((byte *)"BODY")) && (!File_error) )
+ {
+ Read_dword_be(LBM_file,&image_size);
+ //swab((char *)&header.Width ,(char *)&Main_image_width,2);
+ //swab((char *)&header.Height,(char *)&Main_image_height,2);
+ Main_image_width = header.Width;
+ Main_image_height = header.Height;
+
+ //swab((char *)&header.X_screen,(char *)&Original_screen_X,2);
+ //swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2);
+ Original_screen_X = header.X_screen;
+ Original_screen_Y = header.Y_screen;
+
+ Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_LBM,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap
+ {
+ // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques)
+ if (Main_image_width & 15)
+ {
+ real_line_size=( (Main_image_width+16) >> 4 ) << 4;
+ line_size=( (Main_image_width+16) >> 4 )*(header.BitPlanes<<1);
+ }
+ else
+ {
+ real_line_size=Main_image_width;
+ line_size=(Main_image_width>>3)*header.BitPlanes;
+ }
+
+ if (!header.Compression)
+ { // non compressé
+ LBM_buffer=(byte *)malloc(line_size);
+ for (y_pos=0; ((y_pos 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(LBM_file, &color)!=1)
+ {
+ File_error=2;
+ break;
+ }
+ 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)
+ File_error=2;
+ }
+ if (!File_error)
+ Draw_ILBM_line(y_pos,real_line_size);
+ }
+
+ free(LBM_buffer);
+ /*Close_lecture();*/
+ }
+ }
+ else // "PBM ": Planar(?) BitMap
+ {
+ real_line_size=Main_image_width+(Main_image_width&1);
+
+ if (!header.Compression)
+ { // non compressé
+ LBM_buffer=(byte *)malloc(real_line_size);
+ for (y_pos=0; ((y_pos127)
+ {
+ if(Read_byte(LBM_file, &color)!=1)
+ {
+ File_error=2;
+ break;
+ }
+ b256=256-temp_byte;
+ for (counter=0; counter<=b256; counter++)
+ Pixel_load_function(x_pos++,y_pos,color);
+ }
+ else
+ for (counter=0; counter<=temp_byte; counter++)
+ {
+ byte byte_read=0;
+ if(Read_byte(LBM_file, &byte_read)!=1)
+ {
+ File_error=2;
+ break;
+ }
+ Pixel_load_function(x_pos++,y_pos,byte_read);
+ }
+ }
+ }
+ /*Close_lecture();*/
+ }
+ }
+ }
+ }
+ else
+ Set_file_error(2);
+ }
+ else
+ {
+ File_error=1;
+ }
+ }
+ else
+ Set_file_error(1);
+ }
+ else
+ File_error=1;
+ }
+ else
+ File_error=1;
+
+ fclose(LBM_file);
+ }
+ else
+ File_error=1;
+}
+
+
+// -- Sauver un fichier au format LBM ---------------------------------------
+
+ byte LBM_color_list[129];
+ word LBM_list_size;
+ byte LBM_repetition_mode;
+
+ // ------------- Ecrire les couleurs que l'on vient de traiter ------------
+ void Transfer_colors(void)
+ {
+ byte index;
+
+ if (LBM_list_size>0)
+ {
+ if (LBM_repetition_mode)
+ {
+ Write_one_byte(LBM_file,257-LBM_list_size);
+ Write_one_byte(LBM_file,LBM_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;
+ 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;
+ }
+ }
+ else // La couleur n'est pas la même que la précédente
+ {
+ if (!LBM_repetition_mode) // On conserve le mode...
+ {
+ LBM_color_list[LBM_list_size++]=color;
+ if (LBM_list_size==128)
+ Transfer_colors();
+ }
+ else // On change de mode...
+ {
+ Transfer_colors();
+ LBM_color_list[LBM_list_size]=color;
+ LBM_list_size++;
+ }
+ }
+ }
+ }
+
+
+void Save_LBM(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ T_LBM_Header header;
+ word x_pos;
+ word y_pos;
+ byte temp_byte;
+ word real_width;
+ int file_size;
+
+ File_error=0;
+ Get_full_filename(filename,0);
+
+ // Ouverture du fichier
+ if ((LBM_file=fopen(filename,"wb")))
+ {
+ Write_bytes(LBM_file,"FORM",4);
+ Write_dword_be(LBM_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=Main_image_width+(Main_image_width&1);
+
+ //swab((byte *)&real_width,(byte *)&header.Width,2);
+ header.Width=Main_image_width;
+ header.Height=Main_image_height;
+ header.X_org=0;
+ header.Y_org=0;
+ header.BitPlanes=8;
+ header.Mask=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;
+
+ 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_bytes(LBM_file,"CMAP",4);
+ Write_dword_be(LBM_file,sizeof(T_Palette));
+
+ Write_bytes(LBM_file,Main_palette,sizeof(T_Palette));
+
+ Write_bytes(LBM_file,"BODY",4);
+ Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin
+
+ Init_write_buffer();
+
+ LBM_list_size=0;
+
+ for (y_pos=0; ((y_pos on efface le fichier
+ remove(filename);
+ }
+ else
+ File_error=1;
+}
+
+
+
+//////////////////////////////////// BMP ////////////////////////////////////
+#pragma pack(1)
+typedef struct
+{
+ word Signature; // ='BM' = 0x4D42
+ dword Size_1; // =Taille du fichier
+ word Reserved_1; // =0
+ word Reserved_2; // =0
+ dword Offset; // Nb octets avant les données bitmap
+
+ dword Size_2; // =40
+ dword Width;
+ dword Height;
+ word Planes; // =1
+ word Nb_bits; // =1,4,8 ou 24
+ dword Compression;
+ dword Size_3;
+ dword XPM;
+ dword YPM;
+ dword Nb_Clr;
+ dword Clr_Imprt;
+} T_BMP_Header;
+#pragma pack()
+
+// -- Tester si un fichier est au format BMP --------------------------------
+void Test_BMP(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+ T_BMP_Header header;
+
+ File_error=1;
+ Get_full_filename(filename,0);
+
+ if ((file=fopen(filename, "rb")))
+ {
+ if (Read_bytes(file,&(header.Signature),2) // "BM"
+ && Read_dword_le(file,&(header.Size_1))
+ && Read_word_le(file,&(header.Reserved_1))
+ && Read_word_le(file,&(header.Reserved_2))
+ && Read_dword_le(file,&(header.Offset))
+ && Read_dword_le(file,&(header.Size_2))
+ && Read_dword_le(file,&(header.Width))
+ && Read_dword_le(file,&(header.Height))
+ && Read_word_le(file,&(header.Planes))
+ && Read_word_le(file,&(header.Nb_bits))
+ && Read_dword_le(file,&(header.Compression))
+ && Read_dword_le(file,&(header.Size_3))
+ && Read_dword_le(file,&(header.XPM))
+ && Read_dword_le(file,&(header.YPM))
+ && Read_dword_le(file,&(header.Nb_Clr))
+ && Read_dword_le(file,&(header.Clr_Imprt))
+ )
+ {
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ header.Signature = SDL_Swap16(header.Signature);
+#endif
+
+ if ( (header.Signature==0x4D42) && (header.Size_2==40)
+ && header.Width && header.Height )
+ File_error=0;
+ }
+ fclose(file);
+ }
+}
+
+// Find the 8 important bits in a dword
+byte Bitmap_mask(dword pixel, dword mask)
+{
+ byte result;
+ int i;
+ int bits_found;
+
+ switch(mask)
+ {
+ // Shortcuts to quickly handle the common 24/32bit cases
+ case 0x000000FF:
+ return (pixel & 0x000000FF);
+ case 0x0000FF00:
+ return (pixel & 0x0000FF00)>>8;
+ case 0x00FF0000:
+ return (pixel & 0x00FF0000)>>16;
+ case 0xFF000000:
+ return (pixel & 0xFF000000)>>24;
+ }
+ // Uncommon : do it bit by bit.
+ bits_found=0;
+ result=0;
+ // Process the mask from low to high bit
+ for (i=0;i<32;i++)
+ {
+ // Found a bit in the mask
+ if (mask & (1<=8)
+ return result;
+ }
+ }
+ // Less than 8 bits in the mask: scale the result to 8 bits
+ return result << (8-bits_found);
+}
+
+// -- Charger un fichier au format BMP --------------------------------------
+void Load_BMP(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+ T_BMP_Header header;
+ byte * buffer;
+ word index;
+ byte local_palette[256][4]; // R,G,B,0
+ word nb_colors = 0;
+ short x_pos;
+ short y_pos;
+ word line_size;
+ byte a,b,c=0;
+ long file_size;
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+
+ if ((file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(file);
+
+ if (Read_word_le(file,&(header.Signature))
+ && Read_dword_le(file,&(header.Size_1))
+ && Read_word_le(file,&(header.Reserved_1))
+ && Read_word_le(file,&(header.Reserved_2))
+ && Read_dword_le(file,&(header.Offset))
+ && Read_dword_le(file,&(header.Size_2))
+ && Read_dword_le(file,&(header.Width))
+ && Read_dword_le(file,&(header.Height))
+ && Read_word_le(file,&(header.Planes))
+ && Read_word_le(file,&(header.Nb_bits))
+ && Read_dword_le(file,&(header.Compression))
+ && Read_dword_le(file,&(header.Size_3))
+ && Read_dword_le(file,&(header.XPM))
+ && Read_dword_le(file,&(header.YPM))
+ && Read_dword_le(file,&(header.Nb_Clr))
+ && Read_dword_le(file,&(header.Clr_Imprt))
+ )
+ {
+ switch (header.Nb_bits)
+ {
+ case 1 :
+ case 4 :
+ case 8 :
+ if (header.Nb_Clr)
+ nb_colors=header.Nb_Clr;
+ else
+ nb_colors=1<>3;
+
+ buffer=(byte *)malloc(line_size);
+ for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--)
+ {
+ if (Read_bytes(file,buffer,line_size))
+ for (x_pos=0; x_pos>1] & 0xF);
+ else
+ Pixel_load_function(x_pos,y_pos,buffer[x_pos>>1] >> 4 );
+ break;
+ case 1 :
+ if ( buffer[x_pos>>3] & (0x80>>(x_pos&7)) )
+ Pixel_load_function(x_pos,y_pos,1);
+ else
+ Pixel_load_function(x_pos,y_pos,0);
+ }
+ else
+ File_error=2;
+ }
+ free(buffer);
+ break;
+
+ case 1 : // Compression RLE 8 bits
+ x_pos=0;
+ y_pos=Main_image_height-1;
+
+ /*Init_lecture();*/
+ if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1)
+ File_error=2;
+ while (!File_error)
+ {
+ if (a) // Encoded mode
+ for (index=1; index<=a; index++)
+ Pixel_load_function(x_pos++,y_pos,b);
+ else // Absolute mode
+ switch (b)
+ {
+ case 0 : // End of line
+ x_pos=0;
+ y_pos--;
+ break;
+ case 1 : // End of bitmap
+ break;
+ case 2 : // Delta
+ if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1)
+ File_error=2;
+ x_pos+=a;
+ y_pos-=b;
+ break;
+ default: // Nouvelle série
+ while (b)
+ {
+ if(Read_byte(file, &a)!=1)
+ File_error=2;
+ //Read_one_byte(file, &c);
+ Pixel_load_function(x_pos++,y_pos,a);
+ //if (--c)
+ //{
+ // Pixel_load_function(x_pos++,y_pos,c);
+ // b--;
+ //}
+ b--;
+ }
+ if (ftell(file) & 1) fseek(file, 1, SEEK_CUR);
+ }
+ if (a==0 && b==1)
+ break;
+ if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1)
+ {
+ File_error=2;
+ }
+ }
+ /*Close_lecture();*/
+ break;
+
+ case 2 : // Compression RLE 4 bits
+ x_pos=0;
+ y_pos=Main_image_height-1;
+
+ /*Init_lecture();*/
+ if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1)
+ File_error =2;
+ while ( (!File_error) && ((a)||(b!=1)) )
+ {
+ if (a) // Encoded mode (A fois les 1/2 pixels de B)
+ for (index=1; index<=a; index++)
+ {
+ if (index & 1)
+ Pixel_load_function(x_pos,y_pos,b>>4);
+ else
+ Pixel_load_function(x_pos,y_pos,b&0xF);
+ x_pos++;
+ }
+ else // Absolute mode
+ switch (b)
+ {
+ case 0 : //End of line
+ x_pos=0;
+ y_pos--;
+ break;
+ case 1 : // End of bitmap
+ break;
+ case 2 : // Delta
+ if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1)
+ File_error=2;
+ x_pos+=a;
+ y_pos-=b;
+ break;
+ default: // Nouvelle série (B 1/2 pixels bruts)
+ for (index=1; ((index<=b) && (!File_error)); index++,x_pos++)
+ {
+ if (index&1)
+ {
+ if(Read_byte(file, &c)!=1) File_error=2;
+ Pixel_load_function(x_pos,y_pos,c>>4);
+ }
+ else
+ Pixel_load_function(x_pos,y_pos,c&0xF);
+ }
+ // On lit l'octet rendant le nombre d'octets pair, si
+ // nécessaire. Encore un truc de crétin "made in MS".
+ if ( ((b&3)==1) || ((b&3)==2) )
+ {
+ byte dummy;
+ if(Read_byte(file, &dummy)!=1) File_error=2;
+ }
+ }
+ if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) File_error=2;
+ }
+ /*Close_lecture();*/
+ }
+ fclose(file);
+ }
+ else
+ {
+ fclose(file);
+ File_error=1;
+ }
+ }
+ }
+ else
+ {
+ // Image 16/24/32 bits
+ dword red_mask;
+ dword green_mask;
+ dword blue_mask;
+ if (header.Nb_bits == 16)
+ {
+ red_mask = 0x00007C00;
+ green_mask = 0x000003E0;
+ blue_mask = 0x0000001F;
+ }
+ else
+ {
+ red_mask = 0x00FF0000;
+ green_mask = 0x0000FF00;
+ blue_mask = 0x000000FF;
+ }
+ File_error=0;
+
+ Main_image_width=header.Width;
+ Main_image_height=header.Height;
+ Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP);
+ if (File_error==0)
+ {
+ switch (header.Compression)
+ {
+ case 3: // BI_BITFIELDS
+ if (!Read_dword_le(file,&red_mask) ||
+ !Read_dword_le(file,&green_mask) ||
+ !Read_dword_le(file,&blue_mask))
+ File_error=2;
+ break;
+ default:
+ break;
+ }
+ if (fseek(file, header.Offset, SEEK_SET))
+ File_error=2;
+ }
+ if (File_error==0)
+ {
+ switch (header.Nb_bits)
+ {
+ // 24bit bitmap
+ default:
+ case 24:
+ line_size=Main_image_width*3;
+ x_pos=(line_size % 4); // x_pos sert de variable temporaire
+ if (x_pos>0)
+ line_size+=(4-x_pos);
+
+ buffer=(byte *)malloc(line_size);
+ for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--)
+ {
+ if (Read_bytes(file,buffer,line_size))
+ for (x_pos=0,index=0; x_pos=0) && (!File_error)); y_pos--)
+ {
+ if (Read_bytes(file,buffer,line_size))
+ for (x_pos=0; x_pos=0) && (!File_error)); y_pos--)
+ {
+ if (Read_bytes(file,buffer,line_size))
+ for (x_pos=0; x_pos> 3)+1) << 3;
+ else
+ line_size=Main_image_width;
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ header.Signature = 0x424D;
+#else
+ header.Signature = 0x4D42;
+#endif
+ header.Size_1 =(line_size*Main_image_height)+1078;
+ header.Reserved_1 =0;
+ header.Reserved_2 =0;
+ header.Offset =1078;
+ header.Size_2 =40;
+ header.Width =Main_image_width;
+ header.Height =Main_image_height;
+ header.Planes =1;
+ header.Nb_bits =8;
+ header.Compression=0;
+ header.Size_3 =0;
+ header.XPM =0;
+ header.YPM =0;
+ header.Nb_Clr =0;
+ header.Clr_Imprt =0;
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ header.Size_1 = SDL_Swap32( header.Size_1 );
+ header.Offset = SDL_Swap32( header.Offset );
+ header.Size_2 = SDL_Swap32( header.Size_2 );
+ header.Width = SDL_Swap32( header.Width );
+ header.Height = SDL_Swap32( header.Height );
+ header.Planes = SDL_Swap16( header.Planes );
+ header.Nb_bits = SDL_Swap16( header.Nb_bits );
+ // If you ever set any more fields to non-zero, please swap here!
+#endif
+
+ if (Write_bytes(file,&header,sizeof(T_BMP_Header)))
+ {
+ // Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre
+ // inverse, et pour faire chier, on va les mettre sur une échelle de
+ // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et
+ // puis comme c'est pas assez débile, on va aussi y rajouter un octet
+ // toujours à 0 pour forcer les gens à s'acheter des gros disques
+ // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira
+ // Windows 95." ...
+ for (index=0; index<256; index++)
+ {
+ local_palette[index][0]=Main_palette[index].B;
+ local_palette[index][1]=Main_palette[index].G;
+ local_palette[index][2]=Main_palette[index].R;
+ local_palette[index][3]=0;
+ }
+
+ 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."
+ for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--)
+ for (x_pos=0; x_pos>=current_nb_bits;
+ nb_bits_processed +=current_nb_bits;
+ nb_bits_to_process-=current_nb_bits;
+ GIF_remainder_bits -=current_nb_bits;
+ }
+
+ return GIF_current_code;
+ }
+
+ // -- Affiche un nouveau pixel --
+
+ void GIF_new_pixel(byte color)
+ {
+ Pixel_load_function(GIF_pos_X,GIF_pos_Y,color);
+
+ GIF_pos_X++;
+
+ if (GIF_pos_X>=Main_image_width)
+ {
+ GIF_pos_X=0;
+
+ if (!GIF_interlaced)
+ GIF_pos_Y++;
+ else
+ {
+ switch (GIF_pass)
+ {
+ case 0 : GIF_pos_Y+=8;
+ break;
+ case 1 : GIF_pos_Y+=8;
+ break;
+ case 2 : GIF_pos_Y+=4;
+ break;
+ default: GIF_pos_Y+=2;
+ }
+
+ if (GIF_pos_Y>=Main_image_height)
+ {
+ switch(++GIF_pass)
+ {
+ case 1 : GIF_pos_Y=4;
+ break;
+ case 2 : GIF_pos_Y=2;
+ break;
+ case 3 : GIF_pos_Y=1;
+ break;
+ case 4 : GIF_finished_interlaced_image=1;
+ }
+ }
+ }
+ }
+ }
+
+
+void Load_GIF(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ char signature[6];
+
+ word * alphabet_stack; // Pile de décodage d'une chaîne
+ word * alphabet_prefix; // Table des préfixes des codes
+ word * alphabet_suffix; // Table des suffixes des codes
+ word alphabet_free; // Position libre dans l'alphabet
+ word alphabet_max; // Nombre d'entrées possibles dans l'alphabet
+ word alphabet_stack_pos; // Position dans la pile de décodage d'un chaîne
+
+ T_GIF_LSDB LSDB;
+ T_GIF_IDB IDB;
+
+ word nb_colors; // Nombre de couleurs dans l'image
+ word color_index; // index de traitement d'une couleur
+ byte size_to_read; // Nombre de données à lire (divers)
+ byte block_indentifier; // Code indicateur du type de bloc en cours
+ word initial_nb_bits; // Nb de bits au début du traitement LZW
+ word special_case=0; // Mémoire pour le cas spécial
+ word old_code=0; // Code précédent
+ word byte_read; // Sauvegarde du code en cours de lecture
+ word value_clr; // Valeur <=> Clear tables
+ word value_eof; // Valeur <=> End d'image
+ long file_size;
+ int number_LID; // Nombre d'images trouvées dans le fichier
+
+ /////////////////////////////////////////////////// FIN DES DECLARATIONS //
+
+
+ GIF_pos_X=0;
+ GIF_pos_Y=0;
+ GIF_last_byte=0;
+ GIF_remainder_bits=0;
+ GIF_remainder_byte=0;
+ number_LID=0;
+
+ Get_full_filename(filename,0);
+
+ if ((GIF_file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(GIF_file);
+ if ( (Read_bytes(GIF_file,signature,6)) &&
+ ( (memcmp(signature,"GIF87a",6)==0) ||
+ (memcmp(signature,"GIF89a",6)==0) ) )
+ {
+
+ // Allocation de mémoire pour les tables & piles de traitement:
+ alphabet_stack =(word *)malloc(4096*sizeof(word));
+ alphabet_prefix=(word *)malloc(4096*sizeof(word));
+ alphabet_suffix=(word *)malloc(4096*sizeof(word));
+
+ if (Read_word_le(GIF_file,&(LSDB.Width))
+ && Read_word_le(GIF_file,&(LSDB.Height))
+ && Read_byte(GIF_file,&(LSDB.Resol))
+ && Read_byte(GIF_file,&(LSDB.Backcol))
+ && Read_byte(GIF_file,&(LSDB.Aspect))
+ )
+ {
+ // Lecture du Logical Screen Descriptor Block réussie:
+
+ Original_screen_X=LSDB.Width;
+ Original_screen_Y=LSDB.Height;
+
+ // Palette globale dispo = (LSDB.Resol and $80)
+ // Profondeur de couleur =((LSDB.Resol and $70) shr 4)+1
+ // Nombre de bits/pixel = (LSDB.Resol and $07)+1
+ // Ordre de Classement = (LSDB.Aspect and $80)
+
+ alphabet_stack_pos=0;
+ GIF_last_byte =0;
+ GIF_remainder_bits =0;
+ GIF_remainder_byte =0;
+
+ nb_colors=(1 << ((LSDB.Resol & 0x07)+1));
+ initial_nb_bits=(LSDB.Resol & 0x07)+2;
+
+ if (LSDB.Resol & 0x80)
+ {
+ // Palette globale dispo:
+
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+
+ // On peut maintenant charger la nouvelle palette:
+ if (!(LSDB.Aspect & 0x80))
+ // Palette dans l'ordre:
+ for(color_index=0;color_indexnb_char_to_keep)
+ fseek(GIF_file,size_to_read-nb_char_to_keep,SEEK_CUR);
+ }
+ break;
+ case 0xF9: // Graphics Control Extension
+ // Prévu pour la transparence
+
+ default:
+ // On saute le bloc:
+ fseek(GIF_file,size_to_read,SEEK_CUR);
+ break;
+ }
+ // Lecture de la taille du bloc suivant:
+ Read_byte(GIF_file,&size_to_read);
+ }
+ }
+ break;
+ case 0x2C: // Local Image Descriptor
+ {
+ // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort.
+ if (number_LID!=0)
+ {
+ File_error=2;
+ break;
+ }
+ number_LID++;
+
+ // lecture de 10 derniers octets
+ if ( Read_word_le(GIF_file,&(IDB.Pos_X))
+ && Read_word_le(GIF_file,&(IDB.Pos_Y))
+ && Read_word_le(GIF_file,&(IDB.Image_width))
+ && Read_word_le(GIF_file,&(IDB.Image_height))
+ && Read_byte(GIF_file,&(IDB.Indicator))
+ && Read_byte(GIF_file,&(IDB.Nb_bits_pixel))
+ && IDB.Image_width && IDB.Image_height)
+ {
+ Main_image_width=IDB.Image_width;
+ Main_image_height=IDB.Image_height;
+
+ Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE);
+
+ // Palette locale dispo = (IDB.Indicator and $80)
+ // Image entrelacée = (IDB.Indicator and $40)
+ // Ordre de classement = (IDB.Indicator and $20)
+ // Nombre de bits/pixel = (IDB.Indicator and $07)+1 (si palette locale dispo)
+
+ if (IDB.Indicator & 0x80)
+ {
+ // Palette locale dispo
+
+ nb_colors=(1 << ((IDB.Indicator & 0x07)+1));
+ initial_nb_bits=(IDB.Indicator & 0x07)+2;
+
+ if (!(IDB.Indicator & 0x40))
+ // Palette dans l'ordre:
+ for(color_index=0;color_indexvalue_clr)
+ {
+ alphabet_stack[alphabet_stack_pos++]=alphabet_suffix[GIF_current_code];
+ GIF_current_code=alphabet_prefix[GIF_current_code];
+ }
+
+ special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code;
+
+ do
+ GIF_new_pixel(alphabet_stack[--alphabet_stack_pos]);
+ while (alphabet_stack_pos!=0);
+
+ alphabet_prefix[alphabet_free ]=old_code;
+ alphabet_suffix[alphabet_free++]=GIF_current_code;
+ old_code=byte_read;
+
+ if (alphabet_free>alphabet_max)
+ {
+ if (GIF_nb_bits<12)
+ alphabet_max =((1 << (++GIF_nb_bits))-1);
+ }
+ }
+ else // Code Clear rencontré
+ {
+ GIF_nb_bits =initial_nb_bits;
+ alphabet_max =((1 << GIF_nb_bits)-1);
+ alphabet_free =nb_colors+2;
+ special_case =GIF_get_next_code();
+ old_code =GIF_current_code;
+ GIF_new_pixel(GIF_current_code);
+ }
+ }
+ else
+ File_error=2;
+ } // Code End-Of-Information ou erreur de fichier rencontré
+
+ /*Close_lecture();*/
+
+ if (File_error>=0)
+ if ( /* (GIF_pos_X!=0) || */
+ ( ( (!GIF_interlaced) && (GIF_pos_Y!=Main_image_height) ) ||
+ ( (GIF_interlaced) && (!GIF_finished_interlaced_image) )
+ ) )
+ File_error=2;
+ } // Le fichier contenait un IDB
+ else
+ File_error=2;
+ }
+ default:
+ break;
+ }
+ // Lecture du code de fonction suivant:
+ Read_byte(GIF_file,&block_indentifier);
+ }
+ } // Le fichier contenait un LSDB
+ else
+ File_error=1;
+
+ // Libération de la mémoire utilisée par les tables & piles de traitement:
+ free(alphabet_suffix);
+ free(alphabet_prefix);
+ free(alphabet_stack);
+ } // Le fichier contenait au moins la signature GIF87a ou GIF89a
+ else
+ File_error=1;
+
+ fclose(GIF_file);
+
+ } // Le fichier était ouvrable
+ else
+ File_error=1;
+}
+
+
+// -- Sauver un fichier au format GIF ---------------------------------------
+
+ int GIF_stop; // "On peut arrêter la sauvegarde du fichier"
+ byte GIF_buffer[256]; // buffer d'écriture de bloc de données compilées
+
+ // -- Vider le buffer GIF dans le buffer KM --
+
+ void GIF_empty_buffer(void)
+ {
+ word index;
+
+ if (GIF_remainder_byte)
+ {
+ GIF_buffer[0]=GIF_remainder_byte;
+
+ for (index=0;index<=GIF_remainder_byte;index++)
+ Write_one_byte(GIF_file,GIF_buffer[index]);
+
+ GIF_remainder_byte=0;
+ }
+ }
+
+ // -- Ecrit un code à GIF_nb_bits --
+
+ void GIF_set_code(word Code)
+ {
+ word nb_bits_to_process=GIF_nb_bits;
+ word nb_bits_processed =0;
+ word current_nb_bits;
+
+ while (nb_bits_to_process)
+ {
+ current_nb_bits=(nb_bits_to_process<=(8-GIF_remainder_bits))?nb_bits_to_process:(8-GIF_remainder_bits);
+
+ GIF_last_byte|=(Code & ((1<>=current_nb_bits;
+ GIF_remainder_bits +=current_nb_bits;
+ nb_bits_processed +=current_nb_bits;
+ nb_bits_to_process-=current_nb_bits;
+
+ if (GIF_remainder_bits==8) // Il ne reste plus de bits à coder sur l'octet courant
+ {
+ // Ecrire l'octet à balancer:
+ GIF_buffer[++GIF_remainder_byte]=GIF_last_byte;
+
+ // Si on a atteint la fin du bloc de Raster Data
+ if (GIF_remainder_byte==255)
+ // On doit vider le buffer qui est maintenant plein
+ GIF_empty_buffer();
+
+ GIF_last_byte=0;
+ GIF_remainder_bits=0;
+ }
+ }
+ }
+
+
+ // -- Lire le pixel suivant --
+
+ byte GIF_next_pixel(void)
+ {
+ byte temp;
+
+ temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y);
+
+ if (++GIF_pos_X>=Main_image_width)
+ {
+ GIF_pos_X=0;
+ if (++GIF_pos_Y>=Main_image_height)
+ GIF_stop=1;
+ }
+
+ return temp;
+ }
+
+
+
+void Save_GIF(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+
+ word * alphabet_prefix; // Table des préfixes des codes
+ word * alphabet_suffix; // Table des suffixes des codes
+ word * alphabet_daughter; // Table des chaînes filles (plus longues)
+ word * alphabet_sister; // Table des chaînes soeurs (même longueur)
+ word alphabet_free; // Position libre dans l'alphabet
+ word alphabet_max; // Nombre d'entrées possibles dans l'alphabet
+ word start; // Code précédent (sert au linkage des chaînes)
+ int descend; // Booléen "On vient de descendre"
+
+ T_GIF_LSDB LSDB;
+ T_GIF_IDB IDB;
+
+
+ byte block_indentifier; // Code indicateur du type de bloc en cours
+ word current_string; // Code de la chaîne en cours de traitement
+ byte current_char; // Caractère à coder
+ word index; // index de recherche de chaîne
+
+
+ /////////////////////////////////////////////////// FIN DES DECLARATIONS //
+
+
+ GIF_pos_X=0;
+ GIF_pos_Y=0;
+ GIF_last_byte=0;
+ GIF_remainder_bits=0;
+ GIF_remainder_byte=0;
+
+ Get_full_filename(filename,0);
+
+ if ((GIF_file=fopen(filename,"wb")))
+ {
+ // On écrit la signature du fichier
+ if (Write_bytes(GIF_file,"GIF89a",6))
+ {
+ // La signature du fichier a été correctement écrite.
+
+ // Allocation de mémoire pour les tables
+ alphabet_prefix=(word *)malloc(4096*sizeof(word));
+ alphabet_suffix=(word *)malloc(4096*sizeof(word));
+ alphabet_daughter =(word *)malloc(4096*sizeof(word));
+ alphabet_sister =(word *)malloc(4096*sizeof(word));
+
+ // On initialise le LSDB du fichier
+ if (Config.Screen_size_in_GIF)
+ {
+ LSDB.Width=Screen_width;
+ LSDB.Height=Screen_height;
+ }
+ else
+ {
+ LSDB.Width=Main_image_width;
+ LSDB.Height=Main_image_height;
+ }
+ LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette
+ LSDB.Backcol=0;
+ LSDB.Aspect =0; // Palette normale
+
+ // On sauve le LSDB dans le fichier
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ LSDB.Width = SDL_Swap16(LSDB.Width);
+ LSDB.Height = SDL_Swap16(LSDB.Height);
+#endif
+
+ if (Write_bytes(GIF_file,&LSDB,sizeof(T_GIF_LSDB)))
+ {
+ // Le LSDB a été correctement écrit.
+
+ // On sauve la palette
+ if (Write_bytes(GIF_file,Main_palette,768))
+ {
+ // La palette a été correctement écrite.
+
+ // Le jour où on se servira des blocks d'extensions pour placer
+ // des commentaires, on le fera ici.
+
+ // Ecriture de la transparence
+ //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8);
+
+ // Ecriture du commentaire
+ if (Main_comment[0])
+ {
+ Write_bytes(GIF_file,"\x21\xFE",2);
+ Write_byte(GIF_file,strlen(Main_comment));
+ Write_bytes(GIF_file,Main_comment,strlen(Main_comment)+1);
+ }
+
+
+
+ // On va écrire un block indicateur d'IDB et l'IDB du fichier
+
+ block_indentifier=0x2C;
+ IDB.Pos_X=0;
+ IDB.Pos_Y=0;
+ IDB.Image_width=Main_image_width;
+ IDB.Image_height=Main_image_height;
+ IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale.
+ IDB.Nb_bits_pixel=8; // Image 256 couleurs;
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ IDB.Image_width = SDL_Swap16(IDB.Image_width);
+ IDB.Image_height = SDL_Swap16(IDB.Image_height);
+#endif
+
+ if ( Write_bytes(GIF_file,&block_indentifier,1) &&
+ Write_bytes(GIF_file,&IDB,sizeof(T_GIF_IDB)) )
+ {
+ // Le block indicateur d'IDB et l'IDB ont étés correctements
+ // écrits.
+
+ Init_write_buffer();
+
+ index=4096;
+ File_error=0;
+ GIF_stop=0;
+
+ // Réintialisation de la table:
+ alphabet_free=258;
+ GIF_nb_bits =9;
+ alphabet_max =511;
+ GIF_set_code(256);
+ for (start=0;start<4096;start++)
+ {
+ alphabet_daughter[start]=4096;
+ alphabet_sister[start]=4096;
+ }
+
+ ////////////////////////////////////////////// COMPRESSION LZW //
+
+ start=current_string=GIF_next_pixel();
+ descend=1;
+
+ do
+ {
+ current_char=GIF_next_pixel();
+
+ // On regarde si dans la table on aurait pas une chaîne
+ // équivalente à current_string+Caractere
+
+ while ( (index0xFFF)
+ {
+ // Réintialisation de la table:
+ GIF_set_code(256);
+ alphabet_free=258;
+ GIF_nb_bits =9;
+ alphabet_max =511;
+ for (start=0;start<4096;start++)
+ {
+ alphabet_daughter[start]=4096;
+ alphabet_sister[start]=4096;
+ }
+ }
+ else if (alphabet_free>alphabet_max+1)
+ {
+ // On augmente le nb de bits
+
+ GIF_nb_bits++;
+ alphabet_max=(1< 16c , 1 => 256c , ...
+ word Bytes_per_plane_line;// Doit toujours être pair
+ word Palette_info; // 1 => color , 2 => Gris (ignoré à partir de la version 4)
+ word Screen_X; // |_ Dimensions de
+ word Screen_Y; // | l'écran d'origine
+ byte Filler[54]; // Ca... J'adore!
+ } T_PCX_Header;
+#pragma pack()
+
+T_PCX_Header PCX_header;
+
+// -- Tester si un fichier est au format PCX --------------------------------
+
+void Test_PCX(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+
+ File_error=0;
+ Get_full_filename(filename,0);
+
+ if ((file=fopen(filename, "rb")))
+ {
+ if (Read_byte(file,&(PCX_header.Manufacturer)) &&
+ Read_byte(file,&(PCX_header.Version)) &&
+ Read_byte(file,&(PCX_header.Compression)) &&
+ Read_byte(file,&(PCX_header.Depth)) &&
+ Read_word_le(file,&(PCX_header.X_min)) &&
+ Read_word_le(file,&(PCX_header.Y_min)) &&
+ Read_word_le(file,&(PCX_header.X_max)) &&
+ Read_word_le(file,&(PCX_header.Y_max)) &&
+ Read_word_le(file,&(PCX_header.X_dpi)) &&
+ Read_word_le(file,&(PCX_header.Y_dpi)) &&
+ Read_bytes(file,&(PCX_header.Palette_16c),48) &&
+ Read_byte(file,&(PCX_header.Reserved)) &&
+ Read_byte(file,&(PCX_header.Plane)) &&
+ Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) &&
+ Read_word_le(file,&(PCX_header.Palette_info)) &&
+ Read_word_le(file,&(PCX_header.Screen_X)) &&
+ Read_word_le(file,&(PCX_header.Screen_Y)) &&
+ Read_bytes(file,&(PCX_header.Filler),54) )
+ {
+
+ // Vu que ce header a une signature de merde et peu significative, il
+ // va falloir que je teste différentes petites valeurs dont je connais
+ // l'intervalle. Grrr!
+ if ( (PCX_header.Manufacturer!=10)
+ || (PCX_header.Compression>1)
+ || ( (PCX_header.Depth!=1) && (PCX_header.Depth!=2) && (PCX_header.Depth!=4) && (PCX_header.Depth!=8) )
+ || ( (PCX_header.Plane!=1) && (PCX_header.Plane!=2) && (PCX_header.Plane!=4) && (PCX_header.Plane!=8) && (PCX_header.Plane!=3) )
+ || (PCX_header.X_max>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask;
+ Pixel_load_function(x_pos,y_pos,color);
+ }
+ }
+
+void Load_PCX(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+
+ short line_size;
+ short real_line_size; // width de l'image corrigée
+ short width_read;
+ short x_pos;
+ short y_pos;
+ byte byte1;
+ byte byte2;
+ byte index;
+ dword nb_colors;
+ long file_size;
+ byte palette_CGA[9]={ 84,252,252, 252, 84,252, 252,252,252};
+
+ long position;
+ long image_size;
+ byte * buffer;
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+
+ if ((file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(file);
+ /*
+ if (Read_bytes(file,&PCX_header,sizeof(T_PCX_Header)))
+ {*/
+
+ if (Read_byte(file,&(PCX_header.Manufacturer)) &&
+ Read_byte(file,&(PCX_header.Version)) &&
+ Read_byte(file,&(PCX_header.Compression)) &&
+ Read_byte(file,&(PCX_header.Depth)) &&
+ Read_word_le(file,&(PCX_header.X_min)) &&
+ Read_word_le(file,&(PCX_header.Y_min)) &&
+ Read_word_le(file,&(PCX_header.X_max)) &&
+ Read_word_le(file,&(PCX_header.Y_max)) &&
+ Read_word_le(file,&(PCX_header.X_dpi)) &&
+ Read_word_le(file,&(PCX_header.Y_dpi)) &&
+ Read_bytes(file,&(PCX_header.Palette_16c),48) &&
+ Read_byte(file,&(PCX_header.Reserved)) &&
+ Read_byte(file,&(PCX_header.Plane)) &&
+ Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) &&
+ Read_word_le(file,&(PCX_header.Palette_info)) &&
+ Read_word_le(file,&(PCX_header.Screen_X)) &&
+ Read_word_le(file,&(PCX_header.Screen_Y)) &&
+ Read_bytes(file,&(PCX_header.Filler),54) )
+ {
+
+ Main_image_width=PCX_header.X_max-PCX_header.X_min+1;
+ Main_image_height=PCX_header.Y_max-PCX_header.Y_min+1;
+
+ Original_screen_X=PCX_header.Screen_X;
+ Original_screen_Y=PCX_header.Screen_Y;
+
+ if (PCX_header.Plane!=3)
+ {
+ Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ // On prépare la palette à accueillir les valeurs du fichier PCX
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+ nb_colors=(dword)(1<4)
+ memcpy(Main_palette,PCX_header.Palette_16c,48);
+ else
+ {
+ Main_palette[1].R=0;
+ Main_palette[1].G=0;
+ Main_palette[1].B=0;
+ byte1=PCX_header.Palette_16c[3]>>5;
+ if (nb_colors==4)
+ { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :))
+ memcpy(Main_palette+1,palette_CGA,9);
+ if (!(byte1&2))
+ {
+ Main_palette[1].B=84;
+ Main_palette[2].B=84;
+ Main_palette[3].B=84;
+ }
+ } // Palette monochrome (on va dire que c'est du N&B)
+ else
+ {
+ Main_palette[1].R=252;
+ Main_palette[1].G=252;
+ Main_palette[1].B=252;
+ }
+ }
+
+ // On se positionne à la fin du fichier - 769 octets pour voir s'il y
+ // a une palette.
+ if ( (PCX_header.Depth==8) && (PCX_header.Version>=5) && (file_size>(256*3)) )
+ {
+ fseek(file,file_size-((256*3)+1),SEEK_SET);
+ // On regarde s'il y a une palette après les données de l'image
+ if (Read_byte(file,&byte1))
+ if (byte1==12) // Lire la palette si c'est une image en 256 couleurs
+ {
+ int index;
+ // On lit la palette 256c que ces crétins ont foutue à la fin du fichier
+ for(index=0;index<256;index++)
+ if ( ! Read_byte(file,&Main_palette[index].R)
+ || ! Read_byte(file,&Main_palette[index].G)
+ || ! Read_byte(file,&Main_palette[index].B) )
+ {
+ File_error=2;
+ DEBUG("ERROR READING PCX PALETTE !",index);
+ break;
+ }
+ }
+ }
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ // Maintenant qu'on a lu la palette que ces crétins sont allés foutre
+ // à la fin, on retourne juste après le header pour lire l'image.
+ fseek(file,128,SEEK_SET);
+ if (!File_error)
+ {
+ 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
+ // couleurs se fait comme avec la structure ILBM.
+ Image_HAM=0;
+ HBPm1=PCX_header.Plane-1;
+ LBM_buffer=(byte *)malloc(line_size);
+
+ // Chargement de l'image
+ if (PCX_header.Compression) // Image compressée
+ {
+ /*Init_lecture();*/
+
+ image_size=(long)PCX_header.Bytes_per_plane_line*Main_image_height;
+
+ if (PCX_header.Depth==8) // 256 couleurs (1 plan)
+ {
+ for (position=0; ((position=line_size)
+ {
+ for (x_pos=0; x_pos=line_size)
+ {
+ for (x_pos=0; x_pos1) || (last_pixel>=0xC0) )
+ Write_one_byte(file,counter|0xC0);
+ Write_one_byte(file,last_pixel);
+
+ }
+ }
+
+ // Ecriture de l'octet (12) indiquant que la palette arrive
+ if (!File_error)
+ Write_one_byte(file,12);
+
+ End_write(file);
+
+ // Ecriture de la palette
+ if (!File_error)
+ {
+ if (! Write_bytes(file,Main_palette,sizeof(T_Palette)))
+ File_error=1;
+ }
+ }
+ else
+ File_error=1;
+
+ fclose(file);
+
+ if (File_error)
+ remove(filename);
+
+ }
+ else
+ File_error=1;
+}
+
+
+//////////////////////////////////// SCx ////////////////////////////////////
+#pragma pack(1)
+typedef struct
+{
+ byte Filler1[4];
+ word Width;
+ word Height;
+ byte Filler2;
+ byte Planes;
+} T_SCx_Header;
+#pragma pack()
+
+// -- Tester si un fichier est au format SCx --------------------------------
+void Test_SCx(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ //byte Signature[3];
+ T_SCx_Header SCx_header;
+
+
+ Get_full_filename(filename,0);
+
+ File_error=1;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ // Lecture et vérification de la signature
+ if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header))))
+ {
+ if ( (!memcmp(SCx_header.Filler1,"RIX",3))
+ && SCx_header.Width && SCx_header.Height)
+ File_error=0;
+ }
+ // Fermeture du fichier
+ fclose(file);
+ }
+}
+
+
+// -- Lire un fichier au format SCx -----------------------------------------
+void Load_SCx(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ FILE *file;
+ word x_pos,y_pos;
+ long size,real_size;
+ long file_size;
+ T_SCx_Header SCx_header;
+ T_Palette SCx_Palette;
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+
+ if ((file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(file);
+
+ if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header))))
+ {
+ Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ if (!SCx_header.Planes)
+ size=sizeof(T_Palette);
+ else
+ size=sizeof(T_Components)*(1<>3)*SCx_header.Planes;
+ real_size=(size/SCx_header.Planes)<<3;
+ LBM_buffer=(byte *)malloc(size);
+ HBPm1=SCx_header.Planes-1;
+ Image_HAM=0;
+
+ for (y_pos=0;(y_poscolor_type;
+ bit_depth = info_ptr->bit_depth;
+
+ // If it's any supported file
+ // (Note: As of writing this, this test covers every possible
+ // image format of libpng)
+ if (color_type == PNG_COLOR_TYPE_PALETTE
+ || color_type == PNG_COLOR_TYPE_GRAY
+ || color_type == PNG_COLOR_TYPE_GRAY_ALPHA
+ || color_type == PNG_COLOR_TYPE_RGB
+ || color_type == PNG_COLOR_TYPE_RGB_ALPHA
+ )
+ {
+ int num_text;
+ png_text *text_ptr;
+
+ int unit_type;
+ png_uint_32 res_x;
+ png_uint_32 res_y;
+
+ // Comment (tEXt)
+ Main_comment[0]='\0'; // Clear the previous comment
+ if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL)))
+ {
+ while (num_text--)
+ {
+ if (!strcmp(text_ptr[num_text].key,"Title"))
+ {
+ int size;
+ size = Min(text_ptr[num_text].text_length, COMMENT_SIZE);
+ strncpy(Main_comment, text_ptr[num_text].text, size);
+ Main_comment[size]='\0';
+ break; // Skip all others tEXt chunks
+ }
+ }
+ }
+ // Pixel Ratio (pHYs)
+ if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type))
+ {
+ // Ignore unit, and use the X/Y ratio as a hint for
+ // WIDE or TALL pixels
+ if (res_x>0 && res_y>0)
+ {
+ if (res_y/res_x>1)
+ {
+ Ratio_of_loaded_image=PIXEL_WIDE;
+ }
+ else if (res_x/res_y>1)
+ {
+ Ratio_of_loaded_image=PIXEL_TALL;
+ }
+ }
+ }
+ if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG);
+ else
+ Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image);
+
+ if (File_error==0)
+ {
+ int x,y;
+ png_colorp palette;
+ int num_palette;
+
+ // 16-bit images
+ if (bit_depth == 16)
+ {
+ // Reduce to 8-bit
+ png_set_strip_16(png_ptr);
+ }
+ else if (bit_depth < 8)
+ {
+ // Inform libpng we want one byte per pixel,
+ // even though the file was less than 8bpp
+ png_set_packing(png_ptr);
+ }
+
+ // Images with alpha channel
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ // Tell libpng to ignore it
+ png_set_strip_alpha(png_ptr);
+ }
+
+ // Greyscale images :
+ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ // Map low bpp greyscales to full 8bit (0-255 range)
+ if (bit_depth < 8)
+ png_set_gray_1_2_4_to_8(png_ptr);
+
+ // Create greyscale palette
+ for (x=0;x<256;x++)
+ {
+ Main_palette[x].R=x;
+ Main_palette[x].G=x;
+ Main_palette[x].B=x;
+ }
+ }
+ else if (color_type == PNG_COLOR_TYPE_PALETTE) // Palette images
+ {
+
+ if (bit_depth < 8)
+ {
+ // Clear unused colors
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+ }
+ // Load the palette
+ png_get_PLTE(png_ptr, info_ptr, &palette,
+ &num_palette);
+ for (x=0;xwidth;
+ Main_image_height=info_ptr->height;
+
+ png_set_interlace_handling(png_ptr);
+ png_read_update_info(png_ptr, info_ptr);
+
+ // Allocate row pointers
+ Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height);
+ row_pointers_allocated = 0;
+
+ /* read file */
+ if (!setjmp(png_jmpbuf(png_ptr)))
+ {
+ if (color_type == PNG_COLOR_TYPE_GRAY
+ || color_type == PNG_COLOR_TYPE_GRAY_ALPHA
+ || color_type == PNG_COLOR_TYPE_PALETTE
+ )
+ {
+ // 8bpp
+
+ for (y=0; yrowbytes);
+ row_pointers_allocated = 1;
+
+ png_read_image(png_ptr, Row_pointers);
+
+ for (y=0; yrowbytes);
+ row_pointers_allocated = 1;
+
+ png_read_image(png_ptr, Row_pointers);
+
+ for (y=0; y
#include
#include
-#ifndef __no_pnglib__
-#include
-#endif
#include
#include
@@ -132,26 +129,27 @@ void Load_SDL_Image(void);
void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio);
+// ENUM Name TestFunc LoadFunc SaveFunc Backup Comment Ext Exts
T_Format File_formats[NB_KNOWN_FORMATS] = {
- {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
- {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, "", "*"},
+ {FORMAT_ALL_IMAGES,"(all)",NULL, NULL, NULL, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
+ {FORMAT_ALL_FILES,"(*.*)",NULL, NULL, NULL, 0, 0, "", "*"},
{FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 1, 1, "gif", "gif"},
#ifndef __no_pnglib__
{FORMAT_PNG, " png", Test_PNG, Load_PNG, Save_PNG, 1, 1, "png", "png"},
#endif
{FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 1, 0, "bmp", "bmp"},
{FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 1, 0, "pcx", "pcx"},
- {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 1, 1, "pkm", "pkm"},
+ {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, "pkm", "pkm"}, // Not a backup since it does not save the full palette
{FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0, "lbm", "lbm;iff"},
{FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 1, 0, "img", "img"},
{FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 1, 0, "sc?", "sci;scq;scf;scn;sco"},
- {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 1, 0, "pi1", "pi1"},
- {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 1, 0, "pc1", "pc1"},
+ {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, "pi1", "pi1"},
+ {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 0, 0, "pc1", "pc1"},
{FORMAT_CEL, " cel", Test_CEL, Load_CEL, Save_CEL, 1, 0, "cel", "cel"},
- {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 1, 0, "neo", "neo"},
+ {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 0, 0, "neo", "neo"},
{FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0, "kcf", "kcf"},
{FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 0, 0, "pal", "pal"},
- {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 1, 1, "c64", "c64;koa"},
+ {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, "c64", "c64;koa"},
{FORMAT_MISC,"misc.", NULL, NULL, NULL, 1, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
};
@@ -182,8 +180,6 @@ short Preview_factor_Y;
short Preview_pos_X;
short Preview_pos_Y;
-byte HBPm1; // header.BitPlanes-1
-
// Chargement des pixels dans la preview
void Pixel_load_in_preview(word x_pos,word y_pos,byte color)
@@ -271,12 +267,7 @@ void Remap_fileselector(void)
}
}
-
-
-// Données pour la gestion du chargement en 24b
-#define FORMAT_24B 0x100
-typedef void (* Func_24b_display) (short,short,byte,byte,byte);
-int Image_24b;
+int Image_24b;
T_Components * Buffer_image_24b;
Func_24b_display Pixel_load_24b;
@@ -784,6098 +775,6 @@ void Save_image(byte image)
}
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// PAL ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-// -- Tester si un fichier est au format PAL --------------------------------
-void Test_PAL(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- long file_size; // Taille du fichier
-
- Get_full_filename(filename,0);
-
- File_error=1;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- // Lecture de la taille du fichier
- file_size=File_length_file(file);
- fclose(file);
- // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets
- if (file_size==sizeof(T_Palette))
- File_error=0;
- }
-}
-
-
-// -- Lire un fichier au format PAL -----------------------------------------
-void Load_PAL(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- //long file_size; // Taille du fichier
-
-
- Get_full_filename(filename,0);
- File_error=0;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- T_Palette palette_64;
- // Init_preview(?); // Pas possible... pas d'image...
-
- // Lecture du fichier dans Main_palette
- if (Read_bytes(file,palette_64,sizeof(T_Palette)))
- {
- Palette_64_to_256(palette_64);
- memcpy(Main_palette,palette_64,sizeof(T_Palette));
- Set_palette(Main_palette);
- Remap_fileselector();
-
- // On dessine une preview de la palette (si chargement=preview)
- Draw_palette_preview();
- }
- else
- File_error=2;
-
- // Fermeture du fichier
- fclose(file);
- }
- else
- // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
- File_error=1;
-}
-
-
-// -- Sauver un fichier au format PAL ---------------------------------------
-void Save_PAL(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- //long file_size; // Taille du fichier
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- // Ouverture du fichier
- if ((file=fopen(filename,"wb")))
- {
- T_Palette palette_64;
- memcpy(palette_64,Main_palette,sizeof(T_Palette));
- Palette_256_to_64(palette_64);
- // Enregistrement de Main_palette dans le fichier
- if (! Write_bytes(file,palette_64,sizeof(T_Palette)))
- {
- File_error=1;
- fclose(file);
- remove(filename);
- }
- else // Ecriture correcte => Fermeture normale du fichier
- fclose(file);
- }
- else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
- {
- File_error=1;
- fclose(file);
- remove(filename);
- // On se fout du résultat de l'opération car si ça
- // renvoie 0 c'est que le fichier avait été partiel-
- // -lement écrit, sinon pas du tout. Or dans tous les
- // cas ça revient au même pour nous: Sauvegarde ratée!
- }
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// IMG ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-#pragma pack(1)
-typedef struct
-{
- byte Filler1[6];
- word Width;
- word Height;
- byte Filler2[118];
- T_Palette Palette;
-} T_IMG_Header;
-#pragma pack()
-
-// -- Tester si un fichier est au format IMG --------------------------------
-void Test_IMG(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- T_IMG_Header IMG_header;
- byte signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0};
-
-
- Get_full_filename(filename,0);
-
- File_error=1;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- // Lecture et vérification de la signature
- if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header)))
- {
- if ( (!memcmp(IMG_header.Filler1,signature,6))
- && IMG_header.Width && IMG_header.Height)
- File_error=0;
- }
- // Fermeture du fichier
- fclose(file);
- }
-}
-
-
-// -- Lire un fichier au format IMG -----------------------------------------
-void Load_IMG(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- byte * buffer;
- FILE *file;
- word x_pos,y_pos;
- long width_read;
- long file_size;
- T_IMG_Header IMG_header;
-
- Get_full_filename(filename,0);
- File_error=0;
-
- if ((file=fopen(filename, "rb")))
- {
- file_size=File_length_file(file);
-
- if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header)))
- {
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- IMG_header.Width = SDL_Swap16(IMG_header.Width);
- IMG_header.Height = SDL_Swap16(IMG_header.Height);
-#endif
-
- buffer=(byte *)malloc(IMG_header.Width);
-
- Init_preview(IMG_header.Width,IMG_header.Height,file_size,FORMAT_IMG,PIXEL_SIMPLE);
- if (File_error==0)
- {
- memcpy(Main_palette,IMG_header.Palette,sizeof(T_Palette));
- Set_palette(Main_palette);
- Remap_fileselector();
-
- Main_image_width=IMG_header.Width;
- Main_image_height=IMG_header.Height;
- width_read=IMG_header.Width;
-
- for (y_pos=0;(y_posCOMMENT_SIZE)
- {
- color=temp_byte; // On se sert de color comme
- temp_byte=COMMENT_SIZE; // variable temporaire
- color-=COMMENT_SIZE;
- }
- else
- color=0;
-
- if (Read_bytes(file,Main_comment,temp_byte))
- {
- index+=temp_byte;
- Main_comment[temp_byte]='\0';
- if (color)
- if (fseek(file,color,SEEK_CUR))
- File_error=2;
- }
- else
- File_error=2;
- }
- else
- File_error=2;
- break;
-
- case 1 : // Dimensions de l'écran d'origine
- if (Read_byte(file,&temp_byte))
- {
- if (temp_byte==4)
- {
- index+=4;
- if ( ! Read_word_le(file,(word *) &Original_screen_X)
- || !Read_word_le(file,(word *) &Original_screen_Y) )
- File_error=2;
- }
- else
- File_error=2;
- }
- else
- File_error=2;
- break;
-
- case 2 : // color de transparence
- if (Read_byte(file,&temp_byte))
- {
- if (temp_byte==1)
- {
- index++;
- if (! Read_byte(file,&Back_color))
- File_error=2;
- }
- else
- File_error=2;
- }
- else
- File_error=2;
- break;
-
- default:
- if (Read_byte(file,&temp_byte))
- {
- index+=temp_byte;
- if (fseek(file,temp_byte,SEEK_CUR))
- File_error=2;
- }
- else
- File_error=2;
- }
- }
- else
- File_error=2;
- }
- if ( (!File_error) && (index!=header.Jump) )
- File_error=2;
- }
-
- /*Init_lecture();*/
-
- if (!File_error)
- {
- Init_preview(header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE);
- if (File_error==0)
- {
-
- Main_image_width=header.Width;
- Main_image_height=header.Height;
- image_size=(dword)(Main_image_width*Main_image_height);
- // Palette lue en 64
- memcpy(Main_palette,header.Palette,sizeof(T_Palette));
- Palette_64_to_256(Main_palette);
- Set_palette(Main_palette);
- Remap_fileselector();
-
- Compteur_de_donnees_packees=0;
- Compteur_de_pixels=0;
- Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump;
-
- // Boucle de décompression:
- while ( (Compteur_de_pixels>8);
- Write_one_byte(file,Screen_height&0xFF);
- Write_one_byte(file,Screen_height>>8);
- // Ecriture de la back-color
- Write_one_byte(file,2);
- Write_one_byte(file,1);
- Write_one_byte(file,Back_color);
-
- // Routine de compression PKM de l'image
- image_size=(dword)(Main_image_width*Main_image_height);
- Compteur_de_pixels=0;
- pixel_value=Read_pixel_function(0,0);
-
- while ( (Compteur_de_pixels=image_size) break;
- pixel_value=Read_pixel_function(Compteur_de_pixels % Main_image_width,Compteur_de_pixels / Main_image_width);
- }
-
- if ( (last_color!=header.recog1) && (last_color!=header.recog2) )
- {
- if (repetitions==1)
- Write_one_byte(file,last_color);
- else
- if (repetitions==2)
- {
- Write_one_byte(file,last_color);
- Write_one_byte(file,last_color);
- }
- else
- if ( (repetitions>2) && (repetitions<256) )
- { // RECON1/couleur/nombre
- Write_one_byte(file,header.recog1);
- Write_one_byte(file,last_color);
- Write_one_byte(file,repetitions&0xFF);
- }
- else
- if (repetitions>=256)
- { // RECON2/couleur/hi(nombre)/lo(nombre)
- Write_one_byte(file,header.recog2);
- Write_one_byte(file,last_color);
- Write_one_byte(file,repetitions>>8);
- Write_one_byte(file,repetitions&0xFF);
- }
- }
- else
- {
- if (repetitions<256)
- {
- Write_one_byte(file,header.recog1);
- Write_one_byte(file,last_color);
- Write_one_byte(file,repetitions&0xFF);
- }
- else
- {
- Write_one_byte(file,header.recog2);
- Write_one_byte(file,last_color);
- Write_one_byte(file,repetitions>>8);
- Write_one_byte(file,repetitions&0xFF);
- }
- }
- }
-
- End_write(file);
- }
- else
- File_error=1;
- fclose(file);
- }
- else
- {
- File_error=1;
- fclose(file);
- }
- // S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser
- // ce fichier pourri traîner... Ca fait pas propre.
- if (File_error)
- remove(filename);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// LBM ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-#pragma pack(1)
-typedef struct
-{
- word Width;
- word Height;
- word X_org; // Inutile
- word Y_org; // Inutile
- byte BitPlanes;
- byte Mask;
- byte Compression;
- byte Pad1; // Inutile
- word Transp_col;
- byte X_aspect; // Inutile
- byte Y_aspect; // Inutile
- word X_screen;
- word Y_screen;
-} T_LBM_Header;
-#pragma pack()
-
-byte * LBM_buffer;
-FILE *LBM_file;
-
-// -- Tester si un fichier est au format LBM --------------------------------
-
-void Test_LBM(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- char format[4];
- char section[4];
- dword dummy;
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- if ((LBM_file=fopen(filename, "rb")))
- {
- if (! Read_bytes(LBM_file,section,4))
- File_error=1;
- else
- if (memcmp(section,"FORM",4))
- File_error=1;
- else
- {
- Read_dword_be(LBM_file, &dummy);
- // 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))
- File_error=1;
- else
- if ( (memcmp(format,"ILBM",4)) && (memcmp(format,"PBM ",4)) )
- File_error=1;
- }
- fclose(LBM_file);
- }
- else
- File_error=1;
-}
-
-
-// -- Lire un fichier au format LBM -----------------------------------------
-
- byte Image_HAM;
-
- // ---------------- Adapter la palette pour les images HAM ----------------
- void Adapt_palette_HAM(void)
- {
- short i,j,temp;
- byte color;
-
- if (Image_HAM==6)
- {
- for (i=1; i<=14; i++)
- {
- // On recopie a palette de base
- memcpy(Main_palette+(i<<4),Main_palette,48);
- // On modifie les teintes de cette palette
- for (j=0; j<16; j++)
- {
- color=(i<<4)+j;
- if (i<=7)
- {
- if (i&1)
- {
- temp=Main_palette[j].R+16;
- Main_palette[color].R=(temp<63)?temp:63;
- }
- if (i&2)
- {
- temp=Main_palette[j].G+16;
- Main_palette[color].G=(temp<63)?temp:63;
- }
- if (i&4)
- {
- temp=Main_palette[j].B+16;
- Main_palette[color].B=(temp<63)?temp:63;
- }
- }
- else
- {
- if ((i-7)&1)
- {
- temp=Main_palette[j].R-16;
- Main_palette[color].R=(temp>=0)?temp:0;
- }
- if ((i-7)&2)
- {
- temp=Main_palette[j].G-16;
- Main_palette[color].G=(temp>=0)?temp:0;
- }
- if ((i-7)&4)
- {
- temp=Main_palette[j].B-16;
- Main_palette[color].B=(temp>=0)?temp:0;
- }
- }
- }
- }
- // Ici, il reste les 16 dernières couleurs à modifier
- for (i=240,j=0; j<16; i++,j++)
- {
- temp=Main_palette[j].R+8;
- Main_palette[i].R=(temp<63)?temp:63;
- temp=Main_palette[j].G+8;
- Main_palette[i].G=(temp<63)?temp:63;
- temp=Main_palette[j].B+8;
- Main_palette[i].B=(temp<63)?temp:63;
- }
- }
- else if (Image_HAM==8)
- {
- for (i=1; i<=3; i++)
- {
- // On recopie la palette de base
- memcpy(Main_palette+(i<<6),Main_palette,192);
- // On modifie les teintes de cette palette
- for (j=0; j<64; j++)
- {
- color=(i<<6)+j;
- switch (i)
- {
- case 1 :
- temp=Main_palette[j].R+16;
- Main_palette[color].R=(temp<63)?temp:63;
- break;
- case 2 :
- temp=Main_palette[j].G+16;
- Main_palette[color].G=(temp<63)?temp:63;
- break;
- default:
- temp=Main_palette[j].B+16;
- Main_palette[color].B=(temp<63)?temp:63;
- }
- }
- }
- }
- else // Image 64 couleurs sauvée en 32.
- {
- for (i=0; i<32; i++)
- {
- j=i+32;
- Main_palette[j].R=Main_palette[i].R>>1;
- Main_palette[j].G=Main_palette[i].G>>1;
- Main_palette[j].B=Main_palette[i].B>>1;
- }
- }
- }
-
- // ------------------------- Attendre une section -------------------------
- byte Wait_for(byte * expected_section)
- {
- // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
- dword Taille_section;
- byte section_read[4];
-
- if (! Read_bytes(LBM_file,section_read,4))
- return 0;
- while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée
- {
- if (!Read_dword_be(LBM_file,&Taille_section))
- return 0;
- if (Taille_section&1)
- Taille_section++;
- if (fseek(LBM_file,Taille_section,SEEK_CUR))
- return 0;
- if (! Read_bytes(LBM_file,section_read,4))
- return 0;
- }
- return 1;
- }
-
-// 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)
-{
- // 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;
-
- for(dx=HBPm1;dx>=0;dx--)
- {
- //CIL_Loop
- ax = (real_line_size * dx + x_pos) >> 3;
- bh = (LBM_buffer[ax] >> cl) & 1;
-
- bl = (bl << 1) + bh;
- }
-
- return bl;
-}
-
- // ----------------------- Afficher une ligne ILBM ------------------------
- void Draw_ILBM_line(short y_pos, short real_line_size)
- {
- byte color;
- byte red,green,blue;
- byte temp;
- short x_pos;
-
- if (Image_HAM<=1) // ILBM
- {
- for (x_pos=0; x_pos>2;
- color=Best_color(red,green,blue);
- break;
- case 0x02: // red
- red=temp>>2;
- color=Best_color(red,green,blue);
- break;
- case 0x03: // green
- green=temp>>2;
- color=Best_color(red,green,blue);
- break;
- default: // Nouvelle couleur
- color=temp;
- red=Main_palette[color].R;
- green =Main_palette[color].G;
- blue =Main_palette[color].B;
- }
- Pixel_load_function(x_pos,y_pos,color);
- }
- }
- }
-
-
-void Load_LBM(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- T_LBM_Header header;
- char format[4];
- char section[4];
- byte temp_byte;
- short b256;
- dword nb_colors;
- dword image_size;
- short x_pos;
- short y_pos;
- short counter;
- short line_size; // Taille d'une ligne en octets
- short real_line_size; // Taille d'une ligne en pixels
- byte color;
- long file_size;
- dword dummy;
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- if ((LBM_file=fopen(filename, "rb")))
- {
- file_size=File_length_file(LBM_file);
-
- // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été)
- Read_bytes(LBM_file,section,4);
- Read_dword_be(LBM_file,&dummy);
- Read_bytes(LBM_file,format,4);
- if (!Wait_for((byte *)"BMHD"))
- File_error=1;
- Read_dword_be(LBM_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))
- && header.Width && header.Height)
- {
- if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) )
- {
- Read_dword_be(LBM_file,&nb_colors);
- nb_colors/=3;
-
- if (((dword)1< il faut copier les 32 coul.
- } // sur les 32 suivantes et assombrir ces dernières.
- else
- {
- if ((header.BitPlanes==6) || (header.BitPlanes==8))
- Image_HAM=header.BitPlanes;
- else
- /* File_error=1;*/ /* C'est censé être incorrect mais j'ai */
- Image_HAM=0; /* trouvé un fichier comme ça, alors... */
- }
- }
- else
- Image_HAM=0;
-
- if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) )
- {
- HBPm1=header.BitPlanes-1;
- if (header.Mask==1)
- header.BitPlanes++;
-
- // Deluxe paint le fait... alors on le fait...
- Back_color=header.Transp_col;
-
- // On commence par passer la palette en 256 comme ça, si la nouvelle
- // palette a moins de 256 coul, la précédente ne souffrira pas d'un
- // assombrissement préjudiciable.
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
- else
- Palette_64_to_256(Main_palette);
- // On peut maintenant charger la nouvelle palette
- if (Read_bytes(LBM_file,Main_palette,3*nb_colors))
- {
- Palette_256_to_64(Main_palette);
- if (Image_HAM)
- Adapt_palette_HAM();
- Palette_64_to_256(Main_palette);
- Set_palette(Main_palette);
- Remap_fileselector();
-
- // On lit l'octet de padding du CMAP si la taille est impaire
- if (nb_colors&1)
- if (Read_byte(LBM_file,&temp_byte))
- File_error=2;
-
- if ( (Wait_for((byte *)"BODY")) && (!File_error) )
- {
- Read_dword_be(LBM_file,&image_size);
- //swab((char *)&header.Width ,(char *)&Main_image_width,2);
- //swab((char *)&header.Height,(char *)&Main_image_height,2);
- Main_image_width = header.Width;
- Main_image_height = header.Height;
-
- //swab((char *)&header.X_screen,(char *)&Original_screen_X,2);
- //swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2);
- Original_screen_X = header.X_screen;
- Original_screen_Y = header.Y_screen;
-
- Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_LBM,PIXEL_SIMPLE);
- if (File_error==0)
- {
- if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap
- {
- // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques)
- if (Main_image_width & 15)
- {
- real_line_size=( (Main_image_width+16) >> 4 ) << 4;
- line_size=( (Main_image_width+16) >> 4 )*(header.BitPlanes<<1);
- }
- else
- {
- real_line_size=Main_image_width;
- line_size=(Main_image_width>>3)*header.BitPlanes;
- }
-
- if (!header.Compression)
- { // non compressé
- LBM_buffer=(byte *)malloc(line_size);
- for (y_pos=0; ((y_pos 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(LBM_file, &color)!=1)
- {
- File_error=2;
- break;
- }
- 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)
- File_error=2;
- }
- if (!File_error)
- Draw_ILBM_line(y_pos,real_line_size);
- }
-
- free(LBM_buffer);
- /*Close_lecture();*/
- }
- }
- else // "PBM ": Planar(?) BitMap
- {
- real_line_size=Main_image_width+(Main_image_width&1);
-
- if (!header.Compression)
- { // non compressé
- LBM_buffer=(byte *)malloc(real_line_size);
- for (y_pos=0; ((y_pos127)
- {
- if(Read_byte(LBM_file, &color)!=1)
- {
- File_error=2;
- break;
- }
- b256=256-temp_byte;
- for (counter=0; counter<=b256; counter++)
- Pixel_load_function(x_pos++,y_pos,color);
- }
- else
- for (counter=0; counter<=temp_byte; counter++)
- {
- byte byte_read=0;
- if(Read_byte(LBM_file, &byte_read)!=1)
- {
- File_error=2;
- break;
- }
- Pixel_load_function(x_pos++,y_pos,byte_read);
- }
- }
- }
- /*Close_lecture();*/
- }
- }
- }
- }
- else
- Set_file_error(2);
- }
- else
- {
- File_error=1;
- }
- }
- else
- Set_file_error(1);
- }
- else
- File_error=1;
- }
- else
- File_error=1;
-
- fclose(LBM_file);
- }
- else
- File_error=1;
-}
-
-
-// -- Sauver un fichier au format LBM ---------------------------------------
-
- byte LBM_color_list[129];
- word LBM_list_size;
- byte LBM_repetition_mode;
-
- // ------------- Ecrire les couleurs que l'on vient de traiter ------------
- void Transfer_colors(void)
- {
- byte index;
-
- if (LBM_list_size>0)
- {
- if (LBM_repetition_mode)
- {
- Write_one_byte(LBM_file,257-LBM_list_size);
- Write_one_byte(LBM_file,LBM_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;
- 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;
- }
- }
- else // La couleur n'est pas la même que la précédente
- {
- if (!LBM_repetition_mode) // On conserve le mode...
- {
- LBM_color_list[LBM_list_size++]=color;
- if (LBM_list_size==128)
- Transfer_colors();
- }
- else // On change de mode...
- {
- Transfer_colors();
- LBM_color_list[LBM_list_size]=color;
- LBM_list_size++;
- }
- }
- }
- }
-
-
-void Save_LBM(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- T_LBM_Header header;
- word x_pos;
- word y_pos;
- byte temp_byte;
- word real_width;
- int file_size;
-
- File_error=0;
- Get_full_filename(filename,0);
-
- // Ouverture du fichier
- if ((LBM_file=fopen(filename,"wb")))
- {
- Write_bytes(LBM_file,"FORM",4);
- Write_dword_be(LBM_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=Main_image_width+(Main_image_width&1);
-
- //swab((byte *)&real_width,(byte *)&header.Width,2);
- header.Width=Main_image_width;
- header.Height=Main_image_height;
- header.X_org=0;
- header.Y_org=0;
- header.BitPlanes=8;
- header.Mask=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;
-
- 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_bytes(LBM_file,"CMAP",4);
- Write_dword_be(LBM_file,sizeof(T_Palette));
-
- Write_bytes(LBM_file,Main_palette,sizeof(T_Palette));
-
- Write_bytes(LBM_file,"BODY",4);
- Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin
-
- Init_write_buffer();
-
- LBM_list_size=0;
-
- for (y_pos=0; ((y_pos on efface le fichier
- remove(filename);
- }
- else
- File_error=1;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// BMP ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-#pragma pack(1)
-typedef struct
-{
- word Signature; // ='BM' = 0x4D42
- dword Size_1; // =Taille du fichier
- word Reserved_1; // =0
- word Reserved_2; // =0
- dword Offset; // Nb octets avant les données bitmap
-
- dword Size_2; // =40
- dword Width;
- dword Height;
- word Planes; // =1
- word Nb_bits; // =1,4,8 ou 24
- dword Compression;
- dword Size_3;
- dword XPM;
- dword YPM;
- dword Nb_Clr;
- dword Clr_Imprt;
-} T_BMP_Header;
-#pragma pack()
-
-// -- Tester si un fichier est au format BMP --------------------------------
-void Test_BMP(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
- T_BMP_Header header;
-
- File_error=1;
- Get_full_filename(filename,0);
-
- if ((file=fopen(filename, "rb")))
- {
- if (Read_bytes(file,&(header.Signature),2) // "BM"
- && Read_dword_le(file,&(header.Size_1))
- && Read_word_le(file,&(header.Reserved_1))
- && Read_word_le(file,&(header.Reserved_2))
- && Read_dword_le(file,&(header.Offset))
- && Read_dword_le(file,&(header.Size_2))
- && Read_dword_le(file,&(header.Width))
- && Read_dword_le(file,&(header.Height))
- && Read_word_le(file,&(header.Planes))
- && Read_word_le(file,&(header.Nb_bits))
- && Read_dword_le(file,&(header.Compression))
- && Read_dword_le(file,&(header.Size_3))
- && Read_dword_le(file,&(header.XPM))
- && Read_dword_le(file,&(header.YPM))
- && Read_dword_le(file,&(header.Nb_Clr))
- && Read_dword_le(file,&(header.Clr_Imprt))
- )
- {
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- header.Signature = SDL_Swap16(header.Signature);
-#endif
-
- if ( (header.Signature==0x4D42) && (header.Size_2==40)
- && header.Width && header.Height )
- File_error=0;
- }
- fclose(file);
- }
-}
-
-// Find the 8 important bits in a dword
-byte Bitmap_mask(dword pixel, dword mask)
-{
- byte result;
- int i;
- int bits_found;
-
- switch(mask)
- {
- // Shortcuts to quickly handle the common 24/32bit cases
- case 0x000000FF:
- return (pixel & 0x000000FF);
- case 0x0000FF00:
- return (pixel & 0x0000FF00)>>8;
- case 0x00FF0000:
- return (pixel & 0x00FF0000)>>16;
- case 0xFF000000:
- return (pixel & 0xFF000000)>>24;
- }
- // Uncommon : do it bit by bit.
- bits_found=0;
- result=0;
- // Process the mask from low to high bit
- for (i=0;i<32;i++)
- {
- // Found a bit in the mask
- if (mask & (1<=8)
- return result;
- }
- }
- // Less than 8 bits in the mask: scale the result to 8 bits
- return result << (8-bits_found);
-}
-
-// -- Charger un fichier au format BMP --------------------------------------
-void Load_BMP(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
- T_BMP_Header header;
- byte * buffer;
- word index;
- byte local_palette[256][4]; // R,G,B,0
- word nb_colors = 0;
- short x_pos;
- short y_pos;
- word line_size;
- byte a,b,c=0;
- long file_size;
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- if ((file=fopen(filename, "rb")))
- {
- file_size=File_length_file(file);
-
- if (Read_word_le(file,&(header.Signature))
- && Read_dword_le(file,&(header.Size_1))
- && Read_word_le(file,&(header.Reserved_1))
- && Read_word_le(file,&(header.Reserved_2))
- && Read_dword_le(file,&(header.Offset))
- && Read_dword_le(file,&(header.Size_2))
- && Read_dword_le(file,&(header.Width))
- && Read_dword_le(file,&(header.Height))
- && Read_word_le(file,&(header.Planes))
- && Read_word_le(file,&(header.Nb_bits))
- && Read_dword_le(file,&(header.Compression))
- && Read_dword_le(file,&(header.Size_3))
- && Read_dword_le(file,&(header.XPM))
- && Read_dword_le(file,&(header.YPM))
- && Read_dword_le(file,&(header.Nb_Clr))
- && Read_dword_le(file,&(header.Clr_Imprt))
- )
- {
- switch (header.Nb_bits)
- {
- case 1 :
- case 4 :
- case 8 :
- if (header.Nb_Clr)
- nb_colors=header.Nb_Clr;
- else
- nb_colors=1<>3;
-
- buffer=(byte *)malloc(line_size);
- for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--)
- {
- if (Read_bytes(file,buffer,line_size))
- for (x_pos=0; x_pos>1] & 0xF);
- else
- Pixel_load_function(x_pos,y_pos,buffer[x_pos>>1] >> 4 );
- break;
- case 1 :
- if ( buffer[x_pos>>3] & (0x80>>(x_pos&7)) )
- Pixel_load_function(x_pos,y_pos,1);
- else
- Pixel_load_function(x_pos,y_pos,0);
- }
- else
- File_error=2;
- }
- free(buffer);
- break;
-
- case 1 : // Compression RLE 8 bits
- x_pos=0;
- y_pos=Main_image_height-1;
-
- /*Init_lecture();*/
- if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1)
- File_error=2;
- while (!File_error)
- {
- if (a) // Encoded mode
- for (index=1; index<=a; index++)
- Pixel_load_function(x_pos++,y_pos,b);
- else // Absolute mode
- switch (b)
- {
- case 0 : // End of line
- x_pos=0;
- y_pos--;
- break;
- case 1 : // End of bitmap
- break;
- case 2 : // Delta
- if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1)
- File_error=2;
- x_pos+=a;
- y_pos-=b;
- break;
- default: // Nouvelle série
- while (b)
- {
- if(Read_byte(file, &a)!=1)
- File_error=2;
- //Read_one_byte(file, &c);
- Pixel_load_function(x_pos++,y_pos,a);
- //if (--c)
- //{
- // Pixel_load_function(x_pos++,y_pos,c);
- // b--;
- //}
- b--;
- }
- if (ftell(file) & 1) fseek(file, 1, SEEK_CUR);
- }
- if (a==0 && b==1)
- break;
- if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1)
- {
- File_error=2;
- }
- }
- /*Close_lecture();*/
- break;
-
- case 2 : // Compression RLE 4 bits
- x_pos=0;
- y_pos=Main_image_height-1;
-
- /*Init_lecture();*/
- if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1)
- File_error =2;
- while ( (!File_error) && ((a)||(b!=1)) )
- {
- if (a) // Encoded mode (A fois les 1/2 pixels de B)
- for (index=1; index<=a; index++)
- {
- if (index & 1)
- Pixel_load_function(x_pos,y_pos,b>>4);
- else
- Pixel_load_function(x_pos,y_pos,b&0xF);
- x_pos++;
- }
- else // Absolute mode
- switch (b)
- {
- case 0 : //End of line
- x_pos=0;
- y_pos--;
- break;
- case 1 : // End of bitmap
- break;
- case 2 : // Delta
- if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1)
- File_error=2;
- x_pos+=a;
- y_pos-=b;
- break;
- default: // Nouvelle série (B 1/2 pixels bruts)
- for (index=1; ((index<=b) && (!File_error)); index++,x_pos++)
- {
- if (index&1)
- {
- if(Read_byte(file, &c)!=1) File_error=2;
- Pixel_load_function(x_pos,y_pos,c>>4);
- }
- else
- Pixel_load_function(x_pos,y_pos,c&0xF);
- }
- // On lit l'octet rendant le nombre d'octets pair, si
- // nécessaire. Encore un truc de crétin "made in MS".
- if ( ((b&3)==1) || ((b&3)==2) )
- {
- byte dummy;
- if(Read_byte(file, &dummy)!=1) File_error=2;
- }
- }
- if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) File_error=2;
- }
- /*Close_lecture();*/
- }
- fclose(file);
- }
- else
- {
- fclose(file);
- File_error=1;
- }
- }
- }
- else
- {
- // Image 16/24/32 bits
- dword red_mask;
- dword green_mask;
- dword blue_mask;
- if (header.Nb_bits == 16)
- {
- red_mask = 0x00007C00;
- green_mask = 0x000003E0;
- blue_mask = 0x0000001F;
- }
- else
- {
- red_mask = 0x00FF0000;
- green_mask = 0x0000FF00;
- blue_mask = 0x000000FF;
- }
- File_error=0;
-
- Main_image_width=header.Width;
- Main_image_height=header.Height;
- Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP);
- if (File_error==0)
- {
- switch (header.Compression)
- {
- case 3: // BI_BITFIELDS
- if (!Read_dword_le(file,&red_mask) ||
- !Read_dword_le(file,&green_mask) ||
- !Read_dword_le(file,&blue_mask))
- File_error=2;
- break;
- default:
- break;
- }
- if (fseek(file, header.Offset, SEEK_SET))
- File_error=2;
- }
- if (File_error==0)
- {
- switch (header.Nb_bits)
- {
- // 24bit bitmap
- default:
- case 24:
- line_size=Main_image_width*3;
- x_pos=(line_size % 4); // x_pos sert de variable temporaire
- if (x_pos>0)
- line_size+=(4-x_pos);
-
- buffer=(byte *)malloc(line_size);
- for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--)
- {
- if (Read_bytes(file,buffer,line_size))
- for (x_pos=0,index=0; x_pos=0) && (!File_error)); y_pos--)
- {
- if (Read_bytes(file,buffer,line_size))
- for (x_pos=0; x_pos=0) && (!File_error)); y_pos--)
- {
- if (Read_bytes(file,buffer,line_size))
- for (x_pos=0; x_pos> 3)+1) << 3;
- else
- line_size=Main_image_width;
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- header.Signature = 0x424D;
-#else
- header.Signature = 0x4D42;
-#endif
- header.Size_1 =(line_size*Main_image_height)+1078;
- header.Reserved_1 =0;
- header.Reserved_2 =0;
- header.Offset =1078;
- header.Size_2 =40;
- header.Width =Main_image_width;
- header.Height =Main_image_height;
- header.Planes =1;
- header.Nb_bits =8;
- header.Compression=0;
- header.Size_3 =0;
- header.XPM =0;
- header.YPM =0;
- header.Nb_Clr =0;
- header.Clr_Imprt =0;
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- header.Size_1 = SDL_Swap32( header.Size_1 );
- header.Offset = SDL_Swap32( header.Offset );
- header.Size_2 = SDL_Swap32( header.Size_2 );
- header.Width = SDL_Swap32( header.Width );
- header.Height = SDL_Swap32( header.Height );
- header.Planes = SDL_Swap16( header.Planes );
- header.Nb_bits = SDL_Swap16( header.Nb_bits );
- // If you ever set any more fields to non-zero, please swap here!
-#endif
-
- if (Write_bytes(file,&header,sizeof(T_BMP_Header)))
- {
- // Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre
- // inverse, et pour faire chier, on va les mettre sur une échelle de
- // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et
- // puis comme c'est pas assez débile, on va aussi y rajouter un octet
- // toujours à 0 pour forcer les gens à s'acheter des gros disques
- // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira
- // Windows 95." ...
- for (index=0; index<256; index++)
- {
- local_palette[index][0]=Main_palette[index].B;
- local_palette[index][1]=Main_palette[index].G;
- local_palette[index][2]=Main_palette[index].R;
- local_palette[index][3]=0;
- }
-
- 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."
- for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--)
- for (x_pos=0; x_pos>=current_nb_bits;
- nb_bits_processed +=current_nb_bits;
- nb_bits_to_process-=current_nb_bits;
- GIF_remainder_bits -=current_nb_bits;
- }
-
- return GIF_current_code;
- }
-
- // -- Affiche un nouveau pixel --
-
- void GIF_new_pixel(byte color)
- {
- Pixel_load_function(GIF_pos_X,GIF_pos_Y,color);
-
- GIF_pos_X++;
-
- if (GIF_pos_X>=Main_image_width)
- {
- GIF_pos_X=0;
-
- if (!GIF_interlaced)
- GIF_pos_Y++;
- else
- {
- switch (GIF_pass)
- {
- case 0 : GIF_pos_Y+=8;
- break;
- case 1 : GIF_pos_Y+=8;
- break;
- case 2 : GIF_pos_Y+=4;
- break;
- default: GIF_pos_Y+=2;
- }
-
- if (GIF_pos_Y>=Main_image_height)
- {
- switch(++GIF_pass)
- {
- case 1 : GIF_pos_Y=4;
- break;
- case 2 : GIF_pos_Y=2;
- break;
- case 3 : GIF_pos_Y=1;
- break;
- case 4 : GIF_finished_interlaced_image=1;
- }
- }
- }
- }
- }
-
-
-void Load_GIF(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- char signature[6];
-
- word * alphabet_stack; // Pile de décodage d'une chaîne
- word * alphabet_prefix; // Table des préfixes des codes
- word * alphabet_suffix; // Table des suffixes des codes
- word alphabet_free; // Position libre dans l'alphabet
- word alphabet_max; // Nombre d'entrées possibles dans l'alphabet
- word alphabet_stack_pos; // Position dans la pile de décodage d'un chaîne
-
- T_GIF_LSDB LSDB;
- T_GIF_IDB IDB;
-
- word nb_colors; // Nombre de couleurs dans l'image
- word color_index; // index de traitement d'une couleur
- byte size_to_read; // Nombre de données à lire (divers)
- byte block_indentifier; // Code indicateur du type de bloc en cours
- word initial_nb_bits; // Nb de bits au début du traitement LZW
- word special_case=0; // Mémoire pour le cas spécial
- word old_code=0; // Code précédent
- word byte_read; // Sauvegarde du code en cours de lecture
- word value_clr; // Valeur <=> Clear tables
- word value_eof; // Valeur <=> End d'image
- long file_size;
- int number_LID; // Nombre d'images trouvées dans le fichier
-
- /////////////////////////////////////////////////// FIN DES DECLARATIONS //
-
-
- GIF_pos_X=0;
- GIF_pos_Y=0;
- GIF_last_byte=0;
- GIF_remainder_bits=0;
- GIF_remainder_byte=0;
- number_LID=0;
-
- Get_full_filename(filename,0);
-
- if ((GIF_file=fopen(filename, "rb")))
- {
- file_size=File_length_file(GIF_file);
- if ( (Read_bytes(GIF_file,signature,6)) &&
- ( (memcmp(signature,"GIF87a",6)==0) ||
- (memcmp(signature,"GIF89a",6)==0) ) )
- {
-
- // Allocation de mémoire pour les tables & piles de traitement:
- alphabet_stack =(word *)malloc(4096*sizeof(word));
- alphabet_prefix=(word *)malloc(4096*sizeof(word));
- alphabet_suffix=(word *)malloc(4096*sizeof(word));
-
- if (Read_word_le(GIF_file,&(LSDB.Width))
- && Read_word_le(GIF_file,&(LSDB.Height))
- && Read_byte(GIF_file,&(LSDB.Resol))
- && Read_byte(GIF_file,&(LSDB.Backcol))
- && Read_byte(GIF_file,&(LSDB.Aspect))
- )
- {
- // Lecture du Logical Screen Descriptor Block réussie:
-
- Original_screen_X=LSDB.Width;
- Original_screen_Y=LSDB.Height;
-
- // Palette globale dispo = (LSDB.Resol and $80)
- // Profondeur de couleur =((LSDB.Resol and $70) shr 4)+1
- // Nombre de bits/pixel = (LSDB.Resol and $07)+1
- // Ordre de Classement = (LSDB.Aspect and $80)
-
- alphabet_stack_pos=0;
- GIF_last_byte =0;
- GIF_remainder_bits =0;
- GIF_remainder_byte =0;
-
- nb_colors=(1 << ((LSDB.Resol & 0x07)+1));
- initial_nb_bits=(LSDB.Resol & 0x07)+2;
-
- if (LSDB.Resol & 0x80)
- {
- // Palette globale dispo:
-
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
-
- // On peut maintenant charger la nouvelle palette:
- if (!(LSDB.Aspect & 0x80))
- // Palette dans l'ordre:
- for(color_index=0;color_indexnb_char_to_keep)
- fseek(GIF_file,size_to_read-nb_char_to_keep,SEEK_CUR);
- }
- break;
- case 0xF9: // Graphics Control Extension
- // Prévu pour la transparence
-
- default:
- // On saute le bloc:
- fseek(GIF_file,size_to_read,SEEK_CUR);
- break;
- }
- // Lecture de la taille du bloc suivant:
- Read_byte(GIF_file,&size_to_read);
- }
- }
- break;
- case 0x2C: // Local Image Descriptor
- {
- // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort.
- if (number_LID!=0)
- {
- File_error=2;
- break;
- }
- number_LID++;
-
- // lecture de 10 derniers octets
- if ( Read_word_le(GIF_file,&(IDB.Pos_X))
- && Read_word_le(GIF_file,&(IDB.Pos_Y))
- && Read_word_le(GIF_file,&(IDB.Image_width))
- && Read_word_le(GIF_file,&(IDB.Image_height))
- && Read_byte(GIF_file,&(IDB.Indicator))
- && Read_byte(GIF_file,&(IDB.Nb_bits_pixel))
- && IDB.Image_width && IDB.Image_height)
- {
- Main_image_width=IDB.Image_width;
- Main_image_height=IDB.Image_height;
-
- Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE);
-
- // Palette locale dispo = (IDB.Indicator and $80)
- // Image entrelacée = (IDB.Indicator and $40)
- // Ordre de classement = (IDB.Indicator and $20)
- // Nombre de bits/pixel = (IDB.Indicator and $07)+1 (si palette locale dispo)
-
- if (IDB.Indicator & 0x80)
- {
- // Palette locale dispo
-
- nb_colors=(1 << ((IDB.Indicator & 0x07)+1));
- initial_nb_bits=(IDB.Indicator & 0x07)+2;
-
- if (!(IDB.Indicator & 0x40))
- // Palette dans l'ordre:
- for(color_index=0;color_indexvalue_clr)
- {
- alphabet_stack[alphabet_stack_pos++]=alphabet_suffix[GIF_current_code];
- GIF_current_code=alphabet_prefix[GIF_current_code];
- }
-
- special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code;
-
- do
- GIF_new_pixel(alphabet_stack[--alphabet_stack_pos]);
- while (alphabet_stack_pos!=0);
-
- alphabet_prefix[alphabet_free ]=old_code;
- alphabet_suffix[alphabet_free++]=GIF_current_code;
- old_code=byte_read;
-
- if (alphabet_free>alphabet_max)
- {
- if (GIF_nb_bits<12)
- alphabet_max =((1 << (++GIF_nb_bits))-1);
- }
- }
- else // Code Clear rencontré
- {
- GIF_nb_bits =initial_nb_bits;
- alphabet_max =((1 << GIF_nb_bits)-1);
- alphabet_free =nb_colors+2;
- special_case =GIF_get_next_code();
- old_code =GIF_current_code;
- GIF_new_pixel(GIF_current_code);
- }
- }
- else
- File_error=2;
- } // Code End-Of-Information ou erreur de fichier rencontré
-
- /*Close_lecture();*/
-
- if (File_error>=0)
- if ( /* (GIF_pos_X!=0) || */
- ( ( (!GIF_interlaced) && (GIF_pos_Y!=Main_image_height) ) ||
- ( (GIF_interlaced) && (!GIF_finished_interlaced_image) )
- ) )
- File_error=2;
- } // Le fichier contenait un IDB
- else
- File_error=2;
- }
- default:
- break;
- }
- // Lecture du code de fonction suivant:
- Read_byte(GIF_file,&block_indentifier);
- }
- } // Le fichier contenait un LSDB
- else
- File_error=1;
-
- // Libération de la mémoire utilisée par les tables & piles de traitement:
- free(alphabet_suffix);
- free(alphabet_prefix);
- free(alphabet_stack);
- } // Le fichier contenait au moins la signature GIF87a ou GIF89a
- else
- File_error=1;
-
- fclose(GIF_file);
-
- } // Le fichier était ouvrable
- else
- File_error=1;
-}
-
-
-// -- Sauver un fichier au format GIF ---------------------------------------
-
- int GIF_stop; // "On peut arrêter la sauvegarde du fichier"
- byte GIF_buffer[256]; // buffer d'écriture de bloc de données compilées
-
- // -- Vider le buffer GIF dans le buffer KM --
-
- void GIF_empty_buffer(void)
- {
- word index;
-
- if (GIF_remainder_byte)
- {
- GIF_buffer[0]=GIF_remainder_byte;
-
- for (index=0;index<=GIF_remainder_byte;index++)
- Write_one_byte(GIF_file,GIF_buffer[index]);
-
- GIF_remainder_byte=0;
- }
- }
-
- // -- Ecrit un code à GIF_nb_bits --
-
- void GIF_set_code(word Code)
- {
- word nb_bits_to_process=GIF_nb_bits;
- word nb_bits_processed =0;
- word current_nb_bits;
-
- while (nb_bits_to_process)
- {
- current_nb_bits=(nb_bits_to_process<=(8-GIF_remainder_bits))?nb_bits_to_process:(8-GIF_remainder_bits);
-
- GIF_last_byte|=(Code & ((1<>=current_nb_bits;
- GIF_remainder_bits +=current_nb_bits;
- nb_bits_processed +=current_nb_bits;
- nb_bits_to_process-=current_nb_bits;
-
- if (GIF_remainder_bits==8) // Il ne reste plus de bits à coder sur l'octet courant
- {
- // Ecrire l'octet à balancer:
- GIF_buffer[++GIF_remainder_byte]=GIF_last_byte;
-
- // Si on a atteint la fin du bloc de Raster Data
- if (GIF_remainder_byte==255)
- // On doit vider le buffer qui est maintenant plein
- GIF_empty_buffer();
-
- GIF_last_byte=0;
- GIF_remainder_bits=0;
- }
- }
- }
-
-
- // -- Lire le pixel suivant --
-
- byte GIF_next_pixel(void)
- {
- byte temp;
-
- temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y);
-
- if (++GIF_pos_X>=Main_image_width)
- {
- GIF_pos_X=0;
- if (++GIF_pos_Y>=Main_image_height)
- GIF_stop=1;
- }
-
- return temp;
- }
-
-
-
-void Save_GIF(void)
-{
- char filename[MAX_PATH_CHARACTERS];
-
- word * alphabet_prefix; // Table des préfixes des codes
- word * alphabet_suffix; // Table des suffixes des codes
- word * alphabet_daughter; // Table des chaînes filles (plus longues)
- word * alphabet_sister; // Table des chaînes soeurs (même longueur)
- word alphabet_free; // Position libre dans l'alphabet
- word alphabet_max; // Nombre d'entrées possibles dans l'alphabet
- word start; // Code précédent (sert au linkage des chaînes)
- int descend; // Booléen "On vient de descendre"
-
- T_GIF_LSDB LSDB;
- T_GIF_IDB IDB;
-
-
- byte block_indentifier; // Code indicateur du type de bloc en cours
- word current_string; // Code de la chaîne en cours de traitement
- byte current_char; // Caractère à coder
- word index; // index de recherche de chaîne
-
-
- /////////////////////////////////////////////////// FIN DES DECLARATIONS //
-
-
- GIF_pos_X=0;
- GIF_pos_Y=0;
- GIF_last_byte=0;
- GIF_remainder_bits=0;
- GIF_remainder_byte=0;
-
- Get_full_filename(filename,0);
-
- if ((GIF_file=fopen(filename,"wb")))
- {
- // On écrit la signature du fichier
- if (Write_bytes(GIF_file,"GIF89a",6))
- {
- // La signature du fichier a été correctement écrite.
-
- // Allocation de mémoire pour les tables
- alphabet_prefix=(word *)malloc(4096*sizeof(word));
- alphabet_suffix=(word *)malloc(4096*sizeof(word));
- alphabet_daughter =(word *)malloc(4096*sizeof(word));
- alphabet_sister =(word *)malloc(4096*sizeof(word));
-
- // On initialise le LSDB du fichier
- if (Config.Screen_size_in_GIF)
- {
- LSDB.Width=Screen_width;
- LSDB.Height=Screen_height;
- }
- else
- {
- LSDB.Width=Main_image_width;
- LSDB.Height=Main_image_height;
- }
- LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette
- LSDB.Backcol=0;
- LSDB.Aspect =0; // Palette normale
-
- // On sauve le LSDB dans le fichier
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- LSDB.Width = SDL_Swap16(LSDB.Width);
- LSDB.Height = SDL_Swap16(LSDB.Height);
-#endif
-
- if (Write_bytes(GIF_file,&LSDB,sizeof(T_GIF_LSDB)))
- {
- // Le LSDB a été correctement écrit.
-
- // On sauve la palette
- if (Write_bytes(GIF_file,Main_palette,768))
- {
- // La palette a été correctement écrite.
-
- // Le jour où on se servira des blocks d'extensions pour placer
- // des commentaires, on le fera ici.
-
- // Ecriture de la transparence
- //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8);
-
- // Ecriture du commentaire
- if (Main_comment[0])
- {
- Write_bytes(GIF_file,"\x21\xFE",2);
- Write_byte(GIF_file,strlen(Main_comment));
- Write_bytes(GIF_file,Main_comment,strlen(Main_comment)+1);
- }
-
-
-
- // On va écrire un block indicateur d'IDB et l'IDB du fichier
-
- block_indentifier=0x2C;
- IDB.Pos_X=0;
- IDB.Pos_Y=0;
- IDB.Image_width=Main_image_width;
- IDB.Image_height=Main_image_height;
- IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale.
- IDB.Nb_bits_pixel=8; // Image 256 couleurs;
-
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- IDB.Image_width = SDL_Swap16(IDB.Image_width);
- IDB.Image_height = SDL_Swap16(IDB.Image_height);
-#endif
-
- if ( Write_bytes(GIF_file,&block_indentifier,1) &&
- Write_bytes(GIF_file,&IDB,sizeof(T_GIF_IDB)) )
- {
- // Le block indicateur d'IDB et l'IDB ont étés correctements
- // écrits.
-
- Init_write_buffer();
-
- index=4096;
- File_error=0;
- GIF_stop=0;
-
- // Réintialisation de la table:
- alphabet_free=258;
- GIF_nb_bits =9;
- alphabet_max =511;
- GIF_set_code(256);
- for (start=0;start<4096;start++)
- {
- alphabet_daughter[start]=4096;
- alphabet_sister[start]=4096;
- }
-
- ////////////////////////////////////////////// COMPRESSION LZW //
-
- start=current_string=GIF_next_pixel();
- descend=1;
-
- do
- {
- current_char=GIF_next_pixel();
-
- // On regarde si dans la table on aurait pas une chaîne
- // équivalente à current_string+Caractere
-
- while ( (index0xFFF)
- {
- // Réintialisation de la table:
- GIF_set_code(256);
- alphabet_free=258;
- GIF_nb_bits =9;
- alphabet_max =511;
- for (start=0;start<4096;start++)
- {
- alphabet_daughter[start]=4096;
- alphabet_sister[start]=4096;
- }
- }
- else if (alphabet_free>alphabet_max+1)
- {
- // On augmente le nb de bits
-
- GIF_nb_bits++;
- alphabet_max=(1< 16c , 1 => 256c , ...
- word Bytes_per_plane_line;// Doit toujours être pair
- word Palette_info; // 1 => color , 2 => Gris (ignoré à partir de la version 4)
- word Screen_X; // |_ Dimensions de
- word Screen_Y; // | l'écran d'origine
- byte Filler[54]; // Ca... J'adore!
- } T_PCX_Header;
-#pragma pack()
-
-T_PCX_Header PCX_header;
-
-// -- Tester si un fichier est au format PCX --------------------------------
-
-void Test_PCX(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
-
- File_error=0;
- Get_full_filename(filename,0);
-
- if ((file=fopen(filename, "rb")))
- {
- if (Read_byte(file,&(PCX_header.Manufacturer)) &&
- Read_byte(file,&(PCX_header.Version)) &&
- Read_byte(file,&(PCX_header.Compression)) &&
- Read_byte(file,&(PCX_header.Depth)) &&
- Read_word_le(file,&(PCX_header.X_min)) &&
- Read_word_le(file,&(PCX_header.Y_min)) &&
- Read_word_le(file,&(PCX_header.X_max)) &&
- Read_word_le(file,&(PCX_header.Y_max)) &&
- Read_word_le(file,&(PCX_header.X_dpi)) &&
- Read_word_le(file,&(PCX_header.Y_dpi)) &&
- Read_bytes(file,&(PCX_header.Palette_16c),48) &&
- Read_byte(file,&(PCX_header.Reserved)) &&
- Read_byte(file,&(PCX_header.Plane)) &&
- Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) &&
- Read_word_le(file,&(PCX_header.Palette_info)) &&
- Read_word_le(file,&(PCX_header.Screen_X)) &&
- Read_word_le(file,&(PCX_header.Screen_Y)) &&
- Read_bytes(file,&(PCX_header.Filler),54) )
- {
-
- // Vu que ce header a une signature de merde et peu significative, il
- // va falloir que je teste différentes petites valeurs dont je connais
- // l'intervalle. Grrr!
- if ( (PCX_header.Manufacturer!=10)
- || (PCX_header.Compression>1)
- || ( (PCX_header.Depth!=1) && (PCX_header.Depth!=2) && (PCX_header.Depth!=4) && (PCX_header.Depth!=8) )
- || ( (PCX_header.Plane!=1) && (PCX_header.Plane!=2) && (PCX_header.Plane!=4) && (PCX_header.Plane!=8) && (PCX_header.Plane!=3) )
- || (PCX_header.X_max>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask;
- Pixel_load_function(x_pos,y_pos,color);
- }
- }
-
-void Load_PCX(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
-
- short line_size;
- short real_line_size; // width de l'image corrigée
- short width_read;
- short x_pos;
- short y_pos;
- byte byte1;
- byte byte2;
- byte index;
- dword nb_colors;
- long file_size;
- byte palette_CGA[9]={ 84,252,252, 252, 84,252, 252,252,252};
-
- long position;
- long image_size;
- byte * buffer;
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- if ((file=fopen(filename, "rb")))
- {
- file_size=File_length_file(file);
- /*
- if (Read_bytes(file,&PCX_header,sizeof(T_PCX_Header)))
- {*/
-
- if (Read_byte(file,&(PCX_header.Manufacturer)) &&
- Read_byte(file,&(PCX_header.Version)) &&
- Read_byte(file,&(PCX_header.Compression)) &&
- Read_byte(file,&(PCX_header.Depth)) &&
- Read_word_le(file,&(PCX_header.X_min)) &&
- Read_word_le(file,&(PCX_header.Y_min)) &&
- Read_word_le(file,&(PCX_header.X_max)) &&
- Read_word_le(file,&(PCX_header.Y_max)) &&
- Read_word_le(file,&(PCX_header.X_dpi)) &&
- Read_word_le(file,&(PCX_header.Y_dpi)) &&
- Read_bytes(file,&(PCX_header.Palette_16c),48) &&
- Read_byte(file,&(PCX_header.Reserved)) &&
- Read_byte(file,&(PCX_header.Plane)) &&
- Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) &&
- Read_word_le(file,&(PCX_header.Palette_info)) &&
- Read_word_le(file,&(PCX_header.Screen_X)) &&
- Read_word_le(file,&(PCX_header.Screen_Y)) &&
- Read_bytes(file,&(PCX_header.Filler),54) )
- {
-
- Main_image_width=PCX_header.X_max-PCX_header.X_min+1;
- Main_image_height=PCX_header.Y_max-PCX_header.Y_min+1;
-
- Original_screen_X=PCX_header.Screen_X;
- Original_screen_Y=PCX_header.Screen_Y;
-
- if (PCX_header.Plane!=3)
- {
- Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE);
- if (File_error==0)
- {
- // On prépare la palette à accueillir les valeurs du fichier PCX
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
- nb_colors=(dword)(1<4)
- memcpy(Main_palette,PCX_header.Palette_16c,48);
- else
- {
- Main_palette[1].R=0;
- Main_palette[1].G=0;
- Main_palette[1].B=0;
- byte1=PCX_header.Palette_16c[3]>>5;
- if (nb_colors==4)
- { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :))
- memcpy(Main_palette+1,palette_CGA,9);
- if (!(byte1&2))
- {
- Main_palette[1].B=84;
- Main_palette[2].B=84;
- Main_palette[3].B=84;
- }
- } // Palette monochrome (on va dire que c'est du N&B)
- else
- {
- Main_palette[1].R=252;
- Main_palette[1].G=252;
- Main_palette[1].B=252;
- }
- }
-
- // On se positionne à la fin du fichier - 769 octets pour voir s'il y
- // a une palette.
- if ( (PCX_header.Depth==8) && (PCX_header.Version>=5) && (file_size>(256*3)) )
- {
- fseek(file,file_size-((256*3)+1),SEEK_SET);
- // On regarde s'il y a une palette après les données de l'image
- if (Read_byte(file,&byte1))
- if (byte1==12) // Lire la palette si c'est une image en 256 couleurs
- {
- int index;
- // On lit la palette 256c que ces crétins ont foutue à la fin du fichier
- for(index=0;index<256;index++)
- if ( ! Read_byte(file,&Main_palette[index].R)
- || ! Read_byte(file,&Main_palette[index].G)
- || ! Read_byte(file,&Main_palette[index].B) )
- {
- File_error=2;
- DEBUG("ERROR READING PCX PALETTE !",index);
- break;
- }
- }
- }
- Set_palette(Main_palette);
- Remap_fileselector();
-
- // Maintenant qu'on a lu la palette que ces crétins sont allés foutre
- // à la fin, on retourne juste après le header pour lire l'image.
- fseek(file,128,SEEK_SET);
- if (!File_error)
- {
- 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
- // couleurs se fait comme avec la structure ILBM.
- Image_HAM=0;
- HBPm1=PCX_header.Plane-1;
- LBM_buffer=(byte *)malloc(line_size);
-
- // Chargement de l'image
- if (PCX_header.Compression) // Image compressée
- {
- /*Init_lecture();*/
-
- image_size=(long)PCX_header.Bytes_per_plane_line*Main_image_height;
-
- if (PCX_header.Depth==8) // 256 couleurs (1 plan)
- {
- for (position=0; ((position=line_size)
- {
- for (x_pos=0; x_pos=line_size)
- {
- for (x_pos=0; x_pos1) || (last_pixel>=0xC0) )
- Write_one_byte(file,counter|0xC0);
- Write_one_byte(file,last_pixel);
-
- }
- }
-
- // Ecriture de l'octet (12) indiquant que la palette arrive
- if (!File_error)
- Write_one_byte(file,12);
-
- End_write(file);
-
- // Ecriture de la palette
- if (!File_error)
- {
- if (! Write_bytes(file,Main_palette,sizeof(T_Palette)))
- File_error=1;
- }
- }
- else
- File_error=1;
-
- fclose(file);
-
- if (File_error)
- remove(filename);
-
- }
- else
- File_error=1;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// CEL ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-#pragma pack(1)
-typedef struct
-{
- word Width; // width de l'image
- word Height; // height de l'image
-} T_CEL_Header1;
-
-typedef struct
-{
- byte Signature[4]; // Signature du format
- byte Kind; // Type de fichier ($10=PALette $20=BitMaP)
- byte Nb_bits; // Nombre de bits
- word Filler1; // ???
- word Width; // width de l'image
- word Height; // height de l'image
- word X_offset; // Offset en X de l'image
- word Y_offset; // Offset en Y de l'image
- byte Filler2[16]; // ???
-} T_CEL_Header2;
-#pragma pack()
-
-// -- Tester si un fichier est au format CEL --------------------------------
-
-void Test_CEL(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- int size;
- FILE *file;
- T_CEL_Header1 header1;
- T_CEL_Header2 header2;
- int file_size;
-
- File_error=0;
- Get_full_filename(filename,0);
- file_size=File_length(filename);
- if (file_size==0)
- {
- File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber
- return;
- }
-
- if (! (file=fopen(filename, "rb")))
- {
- File_error = 1;
- return;
- }
- if (Read_word_le(file,&header1.Width) &&
- Read_word_le(file,&header1.Height) )
- {
- // Vu que ce header n'a pas de signature, il va falloir tester la
- // cohérence de la dimension de l'image avec celle du fichier.
-
- size=file_size-sizeof(T_CEL_Header1);
- if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) )
- {
- // Tentative de reconnaissance de la signature des nouveaux fichiers
-
- fseek(file,0,SEEK_SET);
- if (Read_bytes(file,&header2.Signature,4) &&
- !memcmp(header2.Signature,"KiSS",4) &&
- Read_byte(file,&header2.Kind) &&
- (header2.Kind==0x20) &&
- Read_byte(file,&header2.Nb_bits) &&
- Read_word_le(file,&header2.Filler1) &&
- Read_word_le(file,&header2.Width) &&
- Read_word_le(file,&header2.Height) &&
- Read_word_le(file,&header2.X_offset) &&
- Read_word_le(file,&header2.Y_offset) &&
- Read_bytes(file,&header2.Filler2,16))
- {
- // ok
- }
- else
- File_error=1;
- }
- else
- File_error=1;
- }
- else
- {
- File_error=1;
- }
- fclose(file);
-}
-
-
-// -- Lire un fichier au format CEL -----------------------------------------
-
-void Load_CEL(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
- T_CEL_Header1 header1;
- T_CEL_Header2 header2;
- short x_pos;
- short y_pos;
- byte last_byte=0;
- long file_size;
-
- File_error=0;
- Get_full_filename(filename,0);
- if ((file=fopen(filename, "rb")))
- {
- if (Read_bytes(file,&header1,sizeof(T_CEL_Header1)))
- {
- file_size=File_length_file(file);
- if ( (file_size>(long int)sizeof(T_CEL_Header1))
- && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-(long int)sizeof(T_CEL_Header1)) ) )
- {
- // Chargement d'un fichier CEL sans signature (vieux fichiers)
- Main_image_width=header1.Width;
- Main_image_height=header1.Height;
- Original_screen_X=Main_image_width;
- Original_screen_Y=Main_image_height;
- Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE);
- if (File_error==0)
- {
- // Chargement de l'image
- /*Init_lecture();*/
- for (y_pos=0;((y_pos> 4));
- }
- else
- Pixel_load_function(x_pos,y_pos,(last_byte & 15));
- /*Close_lecture();*/
- }
- }
- else
- {
- // On réessaye avec le nouveau format
-
- fseek(file,0,SEEK_SET);
- if (Read_bytes(file,&header2,sizeof(T_CEL_Header2)))
- {
- // Chargement d'un fichier CEL avec signature (nouveaux fichiers)
-
- Main_image_width=header2.Width+header2.X_offset;
- Main_image_height=header2.Height+header2.Y_offset;
- Original_screen_X=Main_image_width;
- Original_screen_Y=Main_image_height;
- Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE);
- if (File_error==0)
- {
- // Chargement de l'image
- /*Init_lecture();*/
-
- if (!File_error)
- {
- // Effacement du décalage
- for (y_pos=0;y_pos> 4));
- }
- else
- Pixel_load_function(x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15));
- break;
-
- case 8:
- for (y_pos=0;((y_pos16 sont utilisées dans l'image
- for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++);
-
- if (x_pos==256)
- {
- // Cas d'une image 16 couleurs (écriture à l'ancien format)
-
- header1.Width =Main_image_width;
- header1.Height=Main_image_height;
-
- if (Write_bytes(file,&header1,sizeof(T_CEL_Header1)))
- {
- // Sauvegarde de l'image
- Init_write_buffer();
- for (y_pos=0;((y_pos>4)!=0)
- File_error=1;
- }
- else
- {
- if (Read_bytes(file,&header2,sizeof(T_CEL_Header2)))
- {
- if (memcmp(header2.Signature,"KiSS",4)==0)
- {
- if (header2.Kind!=0x10)
- File_error=1;
- }
- else
- File_error=1;
- }
- else
- File_error=1;
- }
- fclose(file);
- }
- else
- File_error=1;
-}
-
-
-// -- Lire un fichier au format KCF -----------------------------------------
-
-void Load_KCF(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
- T_KCF_Header buffer;
- T_CEL_Header2 header2;
- byte bytes[3];
- int pal_index;
- int color_index;
- int index;
- long file_size;
-
-
- File_error=0;
- Get_full_filename(filename,0);
- if ((file=fopen(filename, "rb")))
- {
- file_size=File_length_file(file);
- if (file_size==sizeof(T_KCF_Header))
- {
- // Fichier KCF à l'ancien format
-
- if (Read_bytes(file,&buffer,sizeof(T_KCF_Header)))
- {
- // Init_preview(?); // Pas possible... pas d'image...
-
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
-
- // Chargement de la palette
- for (pal_index=0;pal_index<10;pal_index++)
- for (color_index=0;color_index<16;color_index++)
- {
- index=16+(pal_index*16)+color_index;
- Main_palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4);
- Main_palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4);
- Main_palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4);
- }
-
- for (index=0;index<16;index++)
- {
- Main_palette[index].R=Main_palette[index+16].R;
- Main_palette[index].G=Main_palette[index+16].G;
- Main_palette[index].B=Main_palette[index+16].B;
- }
-
- Set_palette(Main_palette);
- Remap_fileselector();
- }
- else
- File_error=1;
- }
- else
- {
- // Fichier KCF au nouveau format
-
- if (Read_bytes(file,&header2,sizeof(T_CEL_Header2)))
- {
- // Init_preview(?); // Pas possible... pas d'image...
-
- index=(header2.Nb_bits==12)?16:0;
- for (pal_index=0;pal_index> 4) << 4;
- Main_palette[index].B=(bytes[0] & 15) << 4;
- Main_palette[index].G=(bytes[1] & 15) << 4;
- break;
-
- case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB
- Read_bytes(file,bytes,3);
- Main_palette[index].R=bytes[0];
- Main_palette[index].G=bytes[1];
- Main_palette[index].B=bytes[2];
- }
-
- index++;
- }
- }
-
- if (header2.Nb_bits==12)
- for (index=0;index<16;index++)
- {
- Main_palette[index].R=Main_palette[index+16].R;
- Main_palette[index].G=Main_palette[index+16].G;
- Main_palette[index].B=Main_palette[index+16].B;
- }
-
- Set_palette(Main_palette);
- Remap_fileselector();
- }
- else
- File_error=1;
- }
- fclose(file);
- }
- else
- File_error=1;
-
- if (!File_error) Draw_palette_preview();
-}
-
-
-// -- Ecrire un fichier au format KCF ---------------------------------------
-
-void Save_KCF(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- FILE *file;
- T_KCF_Header buffer;
- T_CEL_Header2 header2;
- byte bytes[3];
- int pal_index;
- int color_index;
- int index;
- dword Utilisation[256]; // Table d'utilisation de couleurs
-
- // On commence par compter l'utilisation de chaque couleurs
- Count_used_colors(Utilisation);
-
- File_error=0;
- Get_full_filename(filename,0);
- if ((file=fopen(filename,"wb")))
- {
- // Sauvegarde de la palette
-
- // On regarde si des couleurs >16 sont utilisées dans l'image
- for (index=16;((index<256) && (!Utilisation[index]));index++);
-
- if (index==256)
- {
- // Cas d'une image 16 couleurs (écriture à l'ancien format)
-
- for (pal_index=0;pal_index<10;pal_index++)
- for (color_index=0;color_index<16;color_index++)
- {
- index=16+(pal_index*16)+color_index;
- buffer.Palette[pal_index].color[color_index].Byte1=((Main_palette[index].R>>4)<<4) | (Main_palette[index].B>>4);
- buffer.Palette[pal_index].color[color_index].Byte2=Main_palette[index].G>>4;
- }
-
- if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header)))
- File_error=1;
- }
- else
- {
- // Cas d'une image 256 couleurs (écriture au nouveau format)
-
- memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature
- header2.Kind=0x10; // Initialisation du type (PALette)
- header2.Nb_bits=24; // Initialisation du nombre de bits
- header2.Filler1=0; // Initialisation du filler 1 (?)
- header2.Width=256; // Initialisation du nombre de couleurs
- header2.Height=1; // Initialisation du nombre de palettes
- header2.X_offset=0; // Initialisation du décalage X
- header2.Y_offset=0; // Initialisation du décalage Y
- for (index=0;index<16;index++) // Initialisation du filler 2 (?)
- header2.Filler2[index]=0;
-
- if (! Write_bytes(file,&header2,sizeof(T_CEL_Header2)))
- File_error=1;
-
- for (index=0;(index<256) && (!File_error);index++)
- {
- bytes[0]=Main_palette[index].R;
- bytes[1]=Main_palette[index].G;
- bytes[2]=Main_palette[index].B;
- if (! Write_bytes(file,bytes,3))
- File_error=1;
- }
- }
-
- fclose(file);
-
- if (File_error)
- remove(filename);
- }
- else
- File_error=1;
-}
-
-
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// SCx ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-#pragma pack(1)
-typedef struct
-{
- byte Filler1[4];
- word Width;
- word Height;
- byte Filler2;
- byte Planes;
-} T_SCx_Header;
-#pragma pack()
-
-// -- Tester si un fichier est au format SCx --------------------------------
-void Test_SCx(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- //byte Signature[3];
- T_SCx_Header SCx_header;
-
-
- Get_full_filename(filename,0);
-
- File_error=1;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- // Lecture et vérification de la signature
- if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header))))
- {
- if ( (!memcmp(SCx_header.Filler1,"RIX",3))
- && SCx_header.Width && SCx_header.Height)
- File_error=0;
- }
- // Fermeture du fichier
- fclose(file);
- }
-}
-
-
-// -- Lire un fichier au format SCx -----------------------------------------
-void Load_SCx(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- FILE *file;
- word x_pos,y_pos;
- long size,real_size;
- long file_size;
- T_SCx_Header SCx_header;
- T_Palette SCx_Palette;
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- if ((file=fopen(filename, "rb")))
- {
- file_size=File_length_file(file);
-
- if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header))))
- {
- Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE);
- if (File_error==0)
- {
- if (!SCx_header.Planes)
- size=sizeof(T_Palette);
- else
- size=sizeof(T_Components)*(1<>3)*SCx_header.Planes;
- real_size=(size/SCx_header.Planes)<<3;
- LBM_buffer=(byte *)malloc(size);
- HBPm1=SCx_header.Planes-1;
- Image_HAM=0;
-
- for (y_pos=0;(y_pos>=1;
- }
-}
-
-//// CODAGE d'une partie d'IMAGE ////
-
-void PI1_16p_to_8b(byte * src,byte * dest)
-{
- int i; // index du pixel à calculer
- word byte_mask; // Masque de codage
- word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination
-
- byte_mask=0x8000;
- w0=w1=w2=w3=0;
- for (i=0;i<16;i++)
- {
- // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit
- // correspondant à celui du masque
-
- w0|=(src[i] & 0x01)?byte_mask:0x00;
- w1|=(src[i] & 0x02)?byte_mask:0x00;
- w2|=(src[i] & 0x04)?byte_mask:0x00;
- w3|=(src[i] & 0x08)?byte_mask:0x00;
- byte_mask>>=1;
- }
- dest[0]=w0 >> 8;
- dest[1]=w0 & 0x00FF;
- dest[2]=w1 >> 8;
- dest[3]=w1 & 0x00FF;
- dest[4]=w2 >> 8;
- dest[5]=w2 & 0x00FF;
- dest[6]=w3 >> 8;
- dest[7]=w3 & 0x00FF;
-}
-
-//// DECODAGE de la PALETTE ////
-
-void PI1_decode_palette(byte * src,byte * palette)
-{
- int i; // Numéro de la couleur traitée
- int ip; // index dans la palette
- word w; // Word contenant le code
-
- // Schéma d'un word =
- //
- // Low High
- // VVVV RRRR | 0000 BBBB
- // 0321 0321 | 0321
-
- ip=0;
- for (i=0;i<16;i++)
- {
- w=((word)src[(i*2)+1]<<8) | src[(i*2)+0];
-
- // Traitement des couleurs rouge, verte et bleue:
- palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
- palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
- palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
- }
-}
-
-//// CODAGE de la PALETTE ////
-
-void PI1_code_palette(byte * palette,byte * dest)
-{
- int i; // Numéro de la couleur traitée
- int ip; // index dans la palette
- word w; // Word contenant le code
-
- // Schéma d'un word =
- //
- // Low High
- // VVVV RRRR | 0000 BBBB
- // 0321 0321 | 0321
-
- ip=0;
- for (i=0;i<16;i++)
- {
- // Traitement des couleurs rouge, verte et bleue:
- w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++;
- w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++;
- w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++;
-
- dest[(i*2)+0]=w & 0x00FF;
- dest[(i*2)+1]=(w>>8);
- }
-}
-
-
-// -- Tester si un fichier est au format PI1 --------------------------------
-void Test_PI1(void)
-{
- FILE * file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- int size; // Taille du fichier
- word resolution; // Résolution de l'image
-
-
- Get_full_filename(filename,0);
-
- File_error=1;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- // Vérification de la taille
- size=File_length_file(file);
- if ((size==32034) || (size==32066))
- {
- // Lecture et vérification de la résolution
- if (Read_word_le(file,&resolution))
- {
- if (resolution==0x0000)
- File_error=0;
- }
- }
- // Fermeture du fichier
- fclose(file);
- }
-}
-
-
-// -- Lire un fichier au format PI1 -----------------------------------------
-void Load_PI1(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- FILE *file;
- word x_pos,y_pos;
- byte * buffer;
- byte * ptr;
- byte pixels[320];
-
- Get_full_filename(filename,0);
-
- File_error=0;
- if ((file=fopen(filename, "rb")))
- {
- // allocation d'un buffer mémoire
- buffer=(byte *)malloc(32034);
- if (buffer!=NULL)
- {
- // Lecture du fichier dans le buffer
- if (Read_bytes(file,buffer,32034))
- {
- // Initialisation de la preview
- Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE);
- if (File_error==0)
- {
- // Initialisation de la palette
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
- PI1_decode_palette(buffer+2,(byte *)Main_palette);
- Set_palette(Main_palette);
- Remap_fileselector();
-
- Main_image_width=320;
- Main_image_height=200;
-
- // Chargement/décompression de l'image
- ptr=buffer+34;
- for (y_pos=0;y_pos<200;y_pos++)
- {
- for (x_pos=0;x_pos<(320>>4);x_pos++)
- {
- PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
- ptr+=8;
- }
- for (x_pos=0;x_pos<320;x_pos++)
- Pixel_load_function(x_pos,y_pos,pixels[x_pos]);
- }
- }
- }
- else
- File_error=1;
- free(buffer);
- }
- else
- File_error=1;
- fclose(file);
- }
- else
- File_error=1;
-}
-
-
-// -- Sauver un fichier au format PI1 ---------------------------------------
-void Save_PI1(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- FILE *file;
- short x_pos,y_pos;
- byte * buffer;
- byte * ptr;
- byte pixels[320];
-
- Get_full_filename(filename,0);
-
- File_error=0;
- // Ouverture du fichier
- if ((file=fopen(filename,"wb")))
- {
- // allocation d'un buffer mémoire
- buffer=(byte *)malloc(32066);
- // Codage de la résolution
- buffer[0]=0x00;
- buffer[1]=0x00;
- // Codage de la palette
- PI1_code_palette((byte *)Main_palette,buffer+2);
- // Codage de l'image
- ptr=buffer+34;
- for (y_pos=0;y_pos<200;y_pos++)
- {
- // Codage de la ligne
- memset(pixels,0,320);
- if (y_pos>4);x_pos++)
- {
- PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
- ptr+=8;
- }
- }
-
- memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy
-
- if (Write_bytes(file,buffer,32066))
- {
- fclose(file);
- }
- else // Error d'écriture (disque plein ou protégé)
- {
- fclose(file);
- remove(filename);
- File_error=1;
- }
- // Libération du buffer mémoire
- free(buffer);
- }
- else
- {
- fclose(file);
- remove(filename);
- File_error=1;
- }
-}
-
-
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// PC1 ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-
-//// DECOMPRESSION d'un buffer selon la méthode PACKBITS ////
-
-void PC1_uncompress_packbits(byte * src,byte * dest)
-{
- int is,id; // Les indices de parcour des buffers
- int n; // Octet de contrôle
-
- for (is=id=0;id<32000;)
- {
- n=src[is++];
-
- if (n & 0x80)
- {
- // Recopier src[is] -n+1 fois
- n=257-n;
- for (;(n>0) && (id<32000);n--)
- dest[id++]=src[is];
- is++;
- }
- else
- {
- // Recopier n+1 octets littéralement
- n=n+1;
- for (;(n>0) && (id<32000);n--)
- dest[id++]=src[is++];
- }
-
- // Contrôle des erreurs
- if (n>0)
- File_error=1;
- }
-}
-
-//// COMPRESSION d'un buffer selon la méthode PACKBITS ////
-
-void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size)
-{
- int is; // index dans la source
- int id; // index dans la destination
- int ir; // index de la répétition
- int n; // Taille des séquences
- int repet; // "Il y a répétition"
-
- for (is=id=0;is0;n--)
- dest[id++]=src[is++];
- }
-
- // On code la partie sans répétitions
- if (repet)
- {
- // On compte la quantité de fois qu'il faut répéter la valeur
- for (ir+=3;ir>=1;
- }
- }
-}
-
-//// CODAGE d'une partie d'IMAGE ////
-
-// Transformation d'1 ligne de pixels en 4 plans de bits
-
-void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3)
-{
- int i,j; // Compteurs
- int ip; // index du pixel à calculer
- byte byte_mask; // Masque de decodage
- byte b0,b1,b2,b3; // Les 4 octets des plans bits sources
-
- ip=0;
- // Pour chacun des 40 octets des plans de bits
- for (i=0;i<40;i++)
- {
- // Pour chacun des 8 bits des octets
- byte_mask=0x80;
- b0=b1=b2=b3=0;
- for (j=0;j<8;j++)
- {
- b0|=(src[ip] & 0x01)?byte_mask:0x00;
- b1|=(src[ip] & 0x02)?byte_mask:0x00;
- b2|=(src[ip] & 0x04)?byte_mask:0x00;
- b3|=(src[ip] & 0x08)?byte_mask:0x00;
- ip++;
- byte_mask>>=1;
- }
- dst0[i]=b0;
- dst1[i]=b1;
- dst2[i]=b2;
- dst3[i]=b3;
- }
-}
-
-
-// -- Tester si un fichier est au format PC1 --------------------------------
-void Test_PC1(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- int size; // Taille du fichier
- word resolution; // Résolution de l'image
-
-
- Get_full_filename(filename,0);
-
- File_error=1;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- // Vérification de la taille
- size=File_length_file(file);
- if ((size<=32066))
- {
- // Lecture et vérification de la résolution
- if (Read_word_le(file,&resolution))
- {
- if (resolution==0x0080)
- File_error=0;
- }
- }
- // Fermeture du fichier
- fclose(file);
- }
-}
-
-
-// -- Lire un fichier au format PC1 -----------------------------------------
-void Load_PC1(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- FILE *file;
- int size;
- word x_pos,y_pos;
- byte * buffercomp;
- byte * bufferdecomp;
- byte * ptr;
- byte pixels[320];
-
- Get_full_filename(filename,0);
-
- File_error=0;
- if ((file=fopen(filename, "rb")))
- {
- size=File_length_file(file);
- // allocation des buffers mémoire
- buffercomp=(byte *)malloc(size);
- bufferdecomp=(byte *)malloc(32000);
- if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) )
- {
- // Lecture du fichier dans le buffer
- if (Read_bytes(file,buffercomp,size))
- {
- // Initialisation de la preview
- Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE);
- if (File_error==0)
- {
- // Initialisation de la palette
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
- PI1_decode_palette(buffercomp+2,(byte *)Main_palette);
- Set_palette(Main_palette);
- Remap_fileselector();
-
- Main_image_width=320;
- Main_image_height=200;
-
- // Décompression du buffer
- PC1_uncompress_packbits(buffercomp+34,bufferdecomp);
-
- // Décodage de l'image
- ptr=bufferdecomp;
- for (y_pos=0;y_pos<200;y_pos++)
- {
- // Décodage de la scanline
- PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels);
- ptr+=160;
- // Chargement de la ligne
- for (x_pos=0;x_pos<320;x_pos++)
- Pixel_load_function(x_pos,y_pos,pixels[x_pos]);
- }
- }
- }
- else
- File_error=1;
- free(bufferdecomp);
- free(buffercomp);
- }
- else
- {
- File_error=1;
- free(bufferdecomp);
- free(buffercomp);
- }
- fclose(file);
- }
- else
- File_error=1;
-}
-
-
-// -- Sauver un fichier au format PC1 ---------------------------------------
-void Save_PC1(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- FILE *file;
- int size;
- short x_pos,y_pos;
- byte * buffercomp;
- byte * bufferdecomp;
- byte * ptr;
- byte pixels[320];
-
- Get_full_filename(filename,0);
-
- File_error=0;
- // Ouverture du fichier
- if ((file=fopen(filename,"wb")))
- {
- // Allocation des buffers mémoire
- bufferdecomp=(byte *)malloc(32000);
- buffercomp =(byte *)malloc(64066);
- // Codage de la résolution
- buffercomp[0]=0x80;
- buffercomp[1]=0x00;
- // Codage de la palette
- PI1_code_palette((byte *)Main_palette,buffercomp+2);
- // Codage de l'image
- ptr=bufferdecomp;
- for (y_pos=0;y_pos<200;y_pos++)
- {
- // Codage de la ligne
- memset(pixels,0,320);
- if (y_pos>4);x_pos++)
- {
- PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
- ptr+=8;
- }
- for (x_pos=0;x_pos<320;x_pos++)
- Pixel_load_function(x_pos,y_pos,pixels[x_pos]);
- }
- }
- }
- else
- File_error=1;
- free(buffer);
- }
- else
- File_error=1;
- fclose(file);
- }
- else
- File_error=1;
-}
-
-void Save_NEO(void)
-{
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- FILE *file;
- short x_pos,y_pos;
- byte * buffer;
- byte * ptr;
- byte pixels[320];
-
- Get_full_filename(filename,0);
-
- File_error=0;
- // Ouverture du fichier
- if ((file=fopen(filename,"wb")))
- {
- // allocation d'un buffer mémoire
- buffer=(byte *)malloc(32128);
- // Codage de la résolution
- buffer[0]=0x00;
- buffer[1]=0x00;
- buffer[2]=0x00;
- buffer[3]=0x00;
- // Codage de la palette
- PI1_code_palette((byte *)Main_palette,buffer+4);
- // Codage de l'image
- ptr=buffer+128;
- for (y_pos=0;y_pos<200;y_pos++)
- {
- // Codage de la ligne
- memset(pixels,0,320);
- if (y_pos>4);x_pos++)
- {
- PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
- ptr+=8;
- }
- }
-
- if (Write_bytes(file,buffer,32128))
- {
- fclose(file);
- }
- else // Error d'écriture (disque plein ou protégé)
- {
- fclose(file);
- remove(filename);
- File_error=1;
- }
- // Libération du buffer mémoire
- free(buffer);
- }
- else
- {
- fclose(file);
- remove(filename);
- File_error=1;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// C64 ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-void Test_C64(void)
-{
- FILE* file;
- char filename[MAX_PATH_CHARACTERS];
- long file_size;
-
- Get_full_filename(filename,0);
-
- file = fopen(filename,"rb");
-
- if (file)
- {
- file_size = File_length_file(file);
- switch (file_size)
- {
- 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 10001: // multicolor
- case 10003: // multicolor + loadaddr
- File_error = 0;
- break;
- default: // then we don't know for now.
- File_error = 1;
- }
- fclose (file);
- }
- else
- {
- File_error = 1;
- }
-}
-
-void Load_C64_hires(byte *bitmap, byte *colors)
-{
- int cx,cy,x,y,c[4],pixel,color;
-
- for(cy=0; cy<25; cy++)
- {
- for(cx=0; cx<40; cx++)
- {
- c[1]=colors[cy*40+cx]&15;
- c[0]=colors[cy*40+cx]>>4;
- for(y=0; y<8; y++)
- {
- pixel=bitmap[cy*320+cx*8+y];
- for(x=0; x<8; x++)
- {
- color=c[pixel&(1<<(7-x))?1:0];
- Pixel_load_function(cx*8+x,cy*8+y,color);
- }
- }
- }
- }
-}
-
-void Load_C64_multi(byte *bitmap, byte *colors, byte *nybble, byte background)
-{
- int cx,cy,x,y,c[4],pixel,color;
- c[0]=background;
- for(cy=0; cy<25; cy++)
- {
- 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];
-
- for(y=0; y<8; y++)
- {
- pixel=bitmap[cy*320+cx*8+y];
- for(x=0; x<4; x++)
- {
- color=c[(pixel&3)];
- pixel>>=2;
- Pixel_load_function(cx*4+(3-x),cy*8+y,color);
- }
- }
- }
- }
-}
-
-void Load_C64(void)
-{
- FILE* file;
- char filename[MAX_PATH_CHARACTERS];
- long file_size;
- int i;
- byte background,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"};
-
- // Palette from http://www.pepto.de/projects/colorvic/
- byte pal[48]={
- 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF,
- 0x68, 0x37, 0x2B,
- 0x70, 0xA4, 0xB2,
- 0x6F, 0x3D, 0x86,
- 0x58, 0x8D, 0x43,
- 0x35, 0x28, 0x79,
- 0xB8, 0xC7, 0x6F,
- 0x6F, 0x4F, 0x25,
- 0x43, 0x39, 0x00,
- 0x9A, 0x67, 0x59,
- 0x44, 0x44, 0x44,
- 0x6C, 0x6C, 0x6C,
- 0x9A, 0xD2, 0x84,
- 0x6C, 0x5E, 0xB5,
- 0x95, 0x95, 0x95};
-
- byte bitmap[8000],colors[1000],nybble[1000];
- word width=320, height=200;
-
- Get_full_filename(filename,0);
- file = fopen(filename,"rb");
-
- if (file)
- {
- File_error=0;
- file_size = File_length_file(file);
-
- 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;
-
- case 8002: // raw bitmap with loadaddr
- hasLoadAddr=1;
- loadFormat=F_bitmap;
- break;
-
- case 9000: // bitmap + screen
- hasLoadAddr=0;
- loadFormat=F_hires;
- break;
-
- case 9002: // bitmap + screen + loadaddr
- hasLoadAddr=1;
- loadFormat=F_hires;
- break;
-
- case 10001: // multicolor
- hasLoadAddr=0;
- loadFormat=F_multi;
- break;
-
- case 10003: // multicolor + loadaddr
- hasLoadAddr=1;
- loadFormat=F_multi;
- break;
-
- default: // then we don't know what it is.
- File_error = 1;
-
- }
-
- memcpy(Main_palette,pal,48); // this set the software palette for grafx2
- Set_palette(Main_palette); // this set the hardware palette for SDL
- Remap_fileselector(); // 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)
- {
- Ratio_of_loaded_image = PIXEL_WIDE;
- }
- sprintf(Main_comment,"C64 %s, %s",
- c64_format_names[loadFormat],filename);
- Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // Do this as soon as you can
-
- Main_image_width = width ;
- Main_image_height = height;
-
- Read_bytes(file,bitmap,8000);
-
- if (file_size>8002)
- Read_bytes(file,colors,1000);
- else
- {
- for(i=0;i<1000;i++)
- {
- colors[i]=1;
- }
- }
-
- if(width==160)
- {
- Read_bytes(file,nybble,1000);
- Read_byte(file,&background);
- Load_C64_multi(bitmap,colors,nybble,background);
- }
- else
- {
- Load_C64_hires(bitmap,colors);
- }
-
- File_error = 0;
- fclose(file);
- }
- else
- File_error = 1;
-}
-
-int Save_C64_window(byte *saveWhat, byte *loadAddr)
-{
- int button;
- unsigned int i;
- T_Dropdown_button *what, *addr;
- char * what_label[] = {
- "All",
- "Bitmap",
- "Screen",
- "Color"
- };
- char * address_label[] = {
- "None",
- "$2000",
- "$4000",
- "$6000",
- "$8000",
- "$A000",
- "$C000",
- "$E000"
- };
-
- 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);
-
- 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);
- Window_dropdown_clear_items(what);
- for (i=0; i2)
- {
- Warning_message("More than 2 colors in 8x8 pixels");
- // TODO here we should hilite the offending block
- printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors);
- return 1;
- }
- for(i=0;i<16;i++)
- {
- if(cusage[i])
- {
- c2=i;
- break;
- }
- }
- c1=c2;
- for(i=c2+1;i<16;i++)
- {
- if(cusage[i])
- {
- c1=i;
- }
- }
- colors[cx+cy*40]=(c2<<4)|c1;
-
- for(y=0; y<8; y++)
- {
- bits=0;
- for(x=0; x<8; x++)
- {
- pixel=Read_pixel_function(x+cx*8,y+cy*8);
- if(pixel>15)
- {
- Warning_message("Color above 15 used");
- // TODO hilite offending block here too?
- // or make it smarter with color allocation?
- // However, the palette is fixed to the 16 first colors
- return 1;
- }
- bits=bits<<1;
- if (pixel==c1) bits|=1;
- }
- bitmap[pos++]=bits;
- //Write_byte(file,bits&255);
- }
- }
- }
-
- file = fopen(filename,"wb");
-
- if(!file)
- {
- Warning_message("File open failed");
- File_error = 1;
- return 1;
- }
-
- if (loadAddr)
- {
- Write_byte(file,0);
- Write_byte(file,loadAddr);
- }
- if (saveWhat==0 || saveWhat==1)
- Write_bytes(file,bitmap,8000);
- if (saveWhat==0 || saveWhat==2)
- Write_bytes(file,colors,1000);
-
- fclose(file);
- return 0;
-}
-
-int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr)
-{
- /*
- 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)
- */
-
- 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];
- word numcolors,count;
- dword cusage[256];
- byte i,background=0;
- FILE *file;
-
- numcolors=Count_used_colors(cusage);
-
- count=0;
- for(x=0;x<16;x++)
- {
- //printf("color %d, pixels %d\n",x,cusage[x]);
- if(cusage[x]>count)
- {
- count=cusage[x];
- background=x;
- }
- }
-
- for(cy=0; cy<25; cy++)
- {
- //printf("\ny:%2d ",cy);
- for(cx=0; cx<40; cx++)
- {
- numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8);
- if(numcolors>4)
- {
- Warning_message("More than 4 colors in 4x8");
- // TODO hilite offending block
- return 1;
- }
- color=1;
- c[0]=background;
- for(i=0; i<16; i++)
- {
- lut[i]=0;
- if(cusage[i])
- {
- if(i!=background)
- {
- lut[i]=color;
- c[color]=i;
- color++;
- }
- else
- {
- lut[i]=0;
- }
- }
- }
- // add to screen and nybble
- screen[cx+cy*40]=c[1]<<4|c[2];
- nybble[cx+cy*40]=c[3];
- //printf("%x%x%x ",c[1],c[2],c[3]);
- for(y=0;y<8;y++)
- {
- bits=0;
- for(x=0;x<4;x++)
- {
- pixel=Read_pixel_function(cx*4+x,cy*8+y);
- if(pixel>15)
- {
- Warning_message("Color above 15 used");
- // TODO hilite as in hires, you should stay to
- // the fixed 16 color palette
- return 1;
- }
- bits=bits<<2;
- bits|=lut[pixel];
-
- }
- //Write_byte(file,bits&255);
- bitmap[pos++]=bits;
- }
- }
- }
-
- file = fopen(filename,"wb");
-
- if(!file)
- {
- Warning_message("File open failed");
- File_error = 1;
- return 1;
- }
-
- if (loadAddr)
- {
- Write_byte(file,0);
- Write_byte(file,loadAddr);
- }
-
- if (saveWhat==0 || saveWhat==1)
- Write_bytes(file,bitmap,8000);
-
- if (saveWhat==0 || saveWhat==2)
- Write_bytes(file,screen,1000);
-
- if (saveWhat==0 || saveWhat==3)
- Write_bytes(file,nybble,1000);
-
- if (saveWhat==0)
- Write_byte(file,background);
-
- fclose(file);
- //printf("\nbg:%d\n",background);
- return 0;
-}
-
-void Save_C64(void)
-{
- char filename[MAX_PATH_CHARACTERS];
- static byte saveWhat=0, loadAddr=0;
- dword numcolors,cusage[256];
- numcolors=Count_used_colors(cusage);
-
- Get_full_filename(filename,0);
-
- if (numcolors>16)
- {
- Warning_message("Error: Max 16 colors");
- File_error = 1;
- return;
- }
- if (((Main_image_width!=320) && (Main_image_width!=160)) || Main_image_height!=200)
- {
- Warning_message("must be 320x200 or 160x200");
- File_error = 1;
- return;
- }
-
- if(!Save_C64_window(&saveWhat,&loadAddr))
- {
- File_error = 1;
- return;
- }
- //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr);
-
- if (Main_image_width==320)
- File_error = Save_C64_hires(filename,saveWhat,loadAddr);
- else
- File_error = Save_C64_multi(filename,saveWhat,loadAddr);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////// PNG ////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-#ifndef __no_pnglib__
-
-// -- Tester si un fichier est au format PNG --------------------------------
-void Test_PNG(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- byte png_header[8];
-
- Get_full_filename(filename,0);
-
- File_error=1;
-
- // Ouverture du fichier
- if ((file=fopen(filename, "rb")))
- {
- // Lecture du header du fichier
- if (Read_bytes(file,png_header,8))
- {
- if ( !png_sig_cmp(png_header, 0, 8))
- File_error=0;
- }
- fclose(file);
- }
-}
-
-png_bytep * Row_pointers;
-// -- Lire un fichier au format PNG -----------------------------------------
-void Load_PNG(void)
-{
- FILE *file; // Fichier du fichier
- char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
- byte png_header[8];
- byte row_pointers_allocated;
-
- png_structp png_ptr;
- png_infop info_ptr;
-
- Get_full_filename(filename,0);
-
- File_error=0;
-
- if ((file=fopen(filename, "rb")))
- {
- // Load header (8 first bytes)
- if (Read_bytes(file,png_header,8))
- {
- // Do we recognize a png file signature ?
- if ( !png_sig_cmp(png_header, 0, 8))
- {
- // Prepare internal PNG loader
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (png_ptr)
- {
- // Prepare internal PNG loader
- info_ptr = png_create_info_struct(png_ptr);
- if (info_ptr)
- {
- png_byte color_type;
- png_byte bit_depth;
-
- // Setup a return point. If a pnglib loading error occurs
- // in this if(), the else will be executed.
- if (!setjmp(png_jmpbuf(png_ptr)))
- {
- png_init_io(png_ptr, file);
- // Inform pnglib we already loaded the header.
- png_set_sig_bytes(png_ptr, 8);
-
- // Load file information
- png_read_info(png_ptr, info_ptr);
- color_type = info_ptr->color_type;
- bit_depth = info_ptr->bit_depth;
-
- // If it's any supported file
- // (Note: As of writing this, this test covers every possible
- // image format of libpng)
- if (color_type == PNG_COLOR_TYPE_PALETTE
- || color_type == PNG_COLOR_TYPE_GRAY
- || color_type == PNG_COLOR_TYPE_GRAY_ALPHA
- || color_type == PNG_COLOR_TYPE_RGB
- || color_type == PNG_COLOR_TYPE_RGB_ALPHA
- )
- {
- int num_text;
- png_text *text_ptr;
-
- int unit_type;
- png_uint_32 res_x;
- png_uint_32 res_y;
-
- // Comment (tEXt)
- Main_comment[0]='\0'; // Clear the previous comment
- if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL)))
- {
- while (num_text--)
- {
- if (!strcmp(text_ptr[num_text].key,"Title"))
- {
- int size;
- size = Min(text_ptr[num_text].text_length, COMMENT_SIZE);
- strncpy(Main_comment, text_ptr[num_text].text, size);
- Main_comment[size]='\0';
- break; // Skip all others tEXt chunks
- }
- }
- }
- // Pixel Ratio (pHYs)
- if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type))
- {
- // Ignore unit, and use the X/Y ratio as a hint for
- // WIDE or TALL pixels
- if (res_x>0 && res_y>0)
- {
- if (res_y/res_x>1)
- {
- Ratio_of_loaded_image=PIXEL_WIDE;
- }
- else if (res_x/res_y>1)
- {
- Ratio_of_loaded_image=PIXEL_TALL;
- }
- }
- }
- if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG);
- else
- Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image);
-
- if (File_error==0)
- {
- int x,y;
- png_colorp palette;
- int num_palette;
-
- // 16-bit images
- if (bit_depth == 16)
- {
- // Reduce to 8-bit
- png_set_strip_16(png_ptr);
- }
- else if (bit_depth < 8)
- {
- // Inform libpng we want one byte per pixel,
- // even though the file was less than 8bpp
- png_set_packing(png_ptr);
- }
-
- // Images with alpha channel
- if (color_type & PNG_COLOR_MASK_ALPHA)
- {
- // Tell libpng to ignore it
- png_set_strip_alpha(png_ptr);
- }
-
- // Greyscale images :
- if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- {
- // Map low bpp greyscales to full 8bit (0-255 range)
- if (bit_depth < 8)
- png_set_gray_1_2_4_to_8(png_ptr);
-
- // Create greyscale palette
- for (x=0;x<256;x++)
- {
- Main_palette[x].R=x;
- Main_palette[x].G=x;
- Main_palette[x].B=x;
- }
- }
- else if (color_type == PNG_COLOR_TYPE_PALETTE) // Palette images
- {
-
- if (bit_depth < 8)
- {
- // Clear unused colors
- if (Config.Clear_palette)
- memset(Main_palette,0,sizeof(T_Palette));
- }
- // Load the palette
- png_get_PLTE(png_ptr, info_ptr, &palette,
- &num_palette);
- for (x=0;xwidth;
- Main_image_height=info_ptr->height;
-
- png_set_interlace_handling(png_ptr);
- png_read_update_info(png_ptr, info_ptr);
-
- // Allocate row pointers
- Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height);
- row_pointers_allocated = 0;
-
- /* read file */
- if (!setjmp(png_jmpbuf(png_ptr)))
- {
- if (color_type == PNG_COLOR_TYPE_GRAY
- || color_type == PNG_COLOR_TYPE_GRAY_ALPHA
- || color_type == PNG_COLOR_TYPE_PALETTE
- )
- {
- // 8bpp
-
- for (y=0; yrowbytes);
- row_pointers_allocated = 1;
-
- png_read_image(png_ptr, Row_pointers);
-
- for (y=0; yrowbytes);
- row_pointers_allocated = 1;
-
- png_read_image(png_ptr, Row_pointers);
-
- for (y=0; y
+*/
+
+///@file miscfileformats.c
+/// Formats that aren't fully saving, either because of palette restrictions or other things
+
+#include "global.h"
+#include "limits.h"
+#include "loadsave.h"
+#include "struct.h"
+#include "windows.h"
+
+//////////////////////////////////// PAL ////////////////////////////////////
+
+// -- Tester si un fichier est au format PAL --------------------------------
+void Test_PAL(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ long file_size; // Taille du fichier
+
+ Get_full_filename(filename,0);
+
+ File_error=1;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ // Lecture de la taille du fichier
+ file_size=File_length_file(file);
+ fclose(file);
+ // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets
+ if (file_size==sizeof(T_Palette))
+ File_error=0;
+ }
+}
+
+
+// -- Lire un fichier au format PAL -----------------------------------------
+void Load_PAL(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ //long file_size; // Taille du fichier
+
+
+ Get_full_filename(filename,0);
+ File_error=0;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ T_Palette palette_64;
+ // Init_preview(?); // Pas possible... pas d'image...
+
+ // Lecture du fichier dans Main_palette
+ if (Read_bytes(file,palette_64,sizeof(T_Palette)))
+ {
+ Palette_64_to_256(palette_64);
+ memcpy(Main_palette,palette_64,sizeof(T_Palette));
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ // On dessine une preview de la palette (si chargement=preview)
+ Draw_palette_preview();
+ }
+ else
+ File_error=2;
+
+ // Fermeture du fichier
+ fclose(file);
+ }
+ else
+ // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
+ File_error=1;
+}
+
+
+// -- Sauver un fichier au format PAL ---------------------------------------
+void Save_PAL(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ //long file_size; // Taille du fichier
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename,"wb")))
+ {
+ T_Palette palette_64;
+ memcpy(palette_64,Main_palette,sizeof(T_Palette));
+ Palette_256_to_64(palette_64);
+ // Enregistrement de Main_palette dans le fichier
+ if (! Write_bytes(file,palette_64,sizeof(T_Palette)))
+ {
+ File_error=1;
+ fclose(file);
+ remove(filename);
+ }
+ else // Ecriture correcte => Fermeture normale du fichier
+ fclose(file);
+ }
+ else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
+ {
+ File_error=1;
+ fclose(file);
+ remove(filename);
+ // On se fout du résultat de l'opération car si ça
+ // renvoie 0 c'est que le fichier avait été partiel-
+ // -lement écrit, sinon pas du tout. Or dans tous les
+ // cas ça revient au même pour nous: Sauvegarde ratée!
+ }
+}
+
+
+//////////////////////////////////// PKM ////////////////////////////////////
+#pragma pack(1)
+typedef struct
+{
+ char Ident[3]; // Chaîne "PKM" }
+ byte Method; // Compression method
+ // 0 = compression en ligne (c)KM
+ // autres = inconnues pour le moment
+ byte recog1; // Octet de reconnaissance sur 1 octet }
+ byte recog2; // Octet de reconnaissance sur 2 octets }
+ word Width; // width de l'image
+ word Height; // height de l'image
+ T_Palette Palette; // Palette RVB 256*3
+ word Jump; // Taille du saut entre le header et l'image:
+ // On va s'en servir pour rajouter un commentaire
+} T_PKM_Header;
+#pragma pack()
+
+// -- Tester si un fichier est au format PKM --------------------------------
+void Test_PKM(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ T_PKM_Header header;
+
+
+ Get_full_filename(filename,0);
+
+ File_error=1;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ // Lecture du header du fichier
+ if (Read_bytes(file,&header,sizeof(T_PKM_Header)))
+ {
+ // On regarde s'il y a la signature PKM suivie de la méthode 0.
+ // La constante "PKM" étant un chaîne, elle se termine toujours par 0.
+ // Donc pas la peine de s'emm...er à regarder si la méthode est à 0.
+ if ( (!memcmp(&header,"PKM",4)) && header.Width && header.Height)
+ File_error=0;
+ }
+ fclose(file);
+ }
+}
+
+
+// -- Lire un fichier au format PKM -----------------------------------------
+void Load_PKM(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ T_PKM_Header header;
+ byte color;
+ byte temp_byte;
+ word len;
+ word index;
+ dword Compteur_de_pixels;
+ dword Compteur_de_donnees_packees;
+ dword image_size;
+ dword Taille_pack;
+ long file_size;
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+
+ if ((file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(file);
+
+ if (Read_bytes(file,&header,sizeof(T_PKM_Header)))
+ {
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ header.Width = SDL_Swap16(header.Width);
+ header.Height = SDL_Swap16(header.Height);
+ header.Jump = SDL_Swap16(header.Jump);
+#endif
+
+ Main_comment[0]='\0'; // On efface le commentaire
+ if (header.Jump)
+ {
+ index=0;
+ while ( (indexCOMMENT_SIZE)
+ {
+ color=temp_byte; // On se sert de color comme
+ temp_byte=COMMENT_SIZE; // variable temporaire
+ color-=COMMENT_SIZE;
+ }
+ else
+ color=0;
+
+ if (Read_bytes(file,Main_comment,temp_byte))
+ {
+ index+=temp_byte;
+ Main_comment[temp_byte]='\0';
+ if (color)
+ if (fseek(file,color,SEEK_CUR))
+ File_error=2;
+ }
+ else
+ File_error=2;
+ }
+ else
+ File_error=2;
+ break;
+
+ case 1 : // Dimensions de l'écran d'origine
+ if (Read_byte(file,&temp_byte))
+ {
+ if (temp_byte==4)
+ {
+ index+=4;
+ if ( ! Read_word_le(file,(word *) &Original_screen_X)
+ || !Read_word_le(file,(word *) &Original_screen_Y) )
+ File_error=2;
+ }
+ else
+ File_error=2;
+ }
+ else
+ File_error=2;
+ break;
+
+ case 2 : // color de transparence
+ if (Read_byte(file,&temp_byte))
+ {
+ if (temp_byte==1)
+ {
+ index++;
+ if (! Read_byte(file,&Back_color))
+ File_error=2;
+ }
+ else
+ File_error=2;
+ }
+ else
+ File_error=2;
+ break;
+
+ default:
+ if (Read_byte(file,&temp_byte))
+ {
+ index+=temp_byte;
+ if (fseek(file,temp_byte,SEEK_CUR))
+ File_error=2;
+ }
+ else
+ File_error=2;
+ }
+ }
+ else
+ File_error=2;
+ }
+ if ( (!File_error) && (index!=header.Jump) )
+ File_error=2;
+ }
+
+ /*Init_lecture();*/
+
+ if (!File_error)
+ {
+ Init_preview(header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+
+ Main_image_width=header.Width;
+ Main_image_height=header.Height;
+ image_size=(dword)(Main_image_width*Main_image_height);
+ // Palette lue en 64
+ memcpy(Main_palette,header.Palette,sizeof(T_Palette));
+ Palette_64_to_256(Main_palette);
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ Compteur_de_donnees_packees=0;
+ Compteur_de_pixels=0;
+ Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump;
+
+ // Boucle de décompression:
+ while ( (Compteur_de_pixels>8);
+ Write_one_byte(file,Screen_height&0xFF);
+ Write_one_byte(file,Screen_height>>8);
+ // Ecriture de la back-color
+ Write_one_byte(file,2);
+ Write_one_byte(file,1);
+ Write_one_byte(file,Back_color);
+
+ // Routine de compression PKM de l'image
+ image_size=(dword)(Main_image_width*Main_image_height);
+ Compteur_de_pixels=0;
+ pixel_value=Read_pixel_function(0,0);
+
+ while ( (Compteur_de_pixels=image_size) break;
+ pixel_value=Read_pixel_function(Compteur_de_pixels % Main_image_width,Compteur_de_pixels / Main_image_width);
+ }
+
+ if ( (last_color!=header.recog1) && (last_color!=header.recog2) )
+ {
+ if (repetitions==1)
+ Write_one_byte(file,last_color);
+ else
+ if (repetitions==2)
+ {
+ Write_one_byte(file,last_color);
+ Write_one_byte(file,last_color);
+ }
+ else
+ if ( (repetitions>2) && (repetitions<256) )
+ { // RECON1/couleur/nombre
+ Write_one_byte(file,header.recog1);
+ Write_one_byte(file,last_color);
+ Write_one_byte(file,repetitions&0xFF);
+ }
+ else
+ if (repetitions>=256)
+ { // RECON2/couleur/hi(nombre)/lo(nombre)
+ Write_one_byte(file,header.recog2);
+ Write_one_byte(file,last_color);
+ Write_one_byte(file,repetitions>>8);
+ Write_one_byte(file,repetitions&0xFF);
+ }
+ }
+ else
+ {
+ if (repetitions<256)
+ {
+ Write_one_byte(file,header.recog1);
+ Write_one_byte(file,last_color);
+ Write_one_byte(file,repetitions&0xFF);
+ }
+ else
+ {
+ Write_one_byte(file,header.recog2);
+ Write_one_byte(file,last_color);
+ Write_one_byte(file,repetitions>>8);
+ Write_one_byte(file,repetitions&0xFF);
+ }
+ }
+ }
+
+ End_write(file);
+ }
+ else
+ File_error=1;
+ fclose(file);
+ }
+ else
+ {
+ File_error=1;
+ fclose(file);
+ }
+ // S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser
+ // ce fichier pourri traîner... Ca fait pas propre.
+ if (File_error)
+ remove(filename);
+}
+
+
+//////////////////////////////////// CEL ////////////////////////////////////
+#pragma pack(1)
+typedef struct
+{
+ word Width; // width de l'image
+ word Height; // height de l'image
+} T_CEL_Header1;
+
+typedef struct
+{
+ byte Signature[4]; // Signature du format
+ byte Kind; // Type de fichier ($10=PALette $20=BitMaP)
+ byte Nb_bits; // Nombre de bits
+ word Filler1; // ???
+ word Width; // width de l'image
+ word Height; // height de l'image
+ word X_offset; // Offset en X de l'image
+ word Y_offset; // Offset en Y de l'image
+ byte Filler2[16]; // ???
+} T_CEL_Header2;
+#pragma pack()
+
+// -- Tester si un fichier est au format CEL --------------------------------
+
+void Test_CEL(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ int size;
+ FILE *file;
+ T_CEL_Header1 header1;
+ T_CEL_Header2 header2;
+ int file_size;
+
+ File_error=0;
+ Get_full_filename(filename,0);
+ file_size=File_length(filename);
+ if (file_size==0)
+ {
+ File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber
+ return;
+ }
+
+ if (! (file=fopen(filename, "rb")))
+ {
+ File_error = 1;
+ return;
+ }
+ if (Read_word_le(file,&header1.Width) &&
+ Read_word_le(file,&header1.Height) )
+ {
+ // Vu que ce header n'a pas de signature, il va falloir tester la
+ // cohérence de la dimension de l'image avec celle du fichier.
+
+ size=file_size-sizeof(T_CEL_Header1);
+ if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) )
+ {
+ // Tentative de reconnaissance de la signature des nouveaux fichiers
+
+ fseek(file,0,SEEK_SET);
+ if (Read_bytes(file,&header2.Signature,4) &&
+ !memcmp(header2.Signature,"KiSS",4) &&
+ Read_byte(file,&header2.Kind) &&
+ (header2.Kind==0x20) &&
+ Read_byte(file,&header2.Nb_bits) &&
+ Read_word_le(file,&header2.Filler1) &&
+ Read_word_le(file,&header2.Width) &&
+ Read_word_le(file,&header2.Height) &&
+ Read_word_le(file,&header2.X_offset) &&
+ Read_word_le(file,&header2.Y_offset) &&
+ Read_bytes(file,&header2.Filler2,16))
+ {
+ // ok
+ }
+ else
+ File_error=1;
+ }
+ else
+ File_error=1;
+ }
+ else
+ {
+ File_error=1;
+ }
+ fclose(file);
+}
+
+
+// -- Lire un fichier au format CEL -----------------------------------------
+
+void Load_CEL(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+ T_CEL_Header1 header1;
+ T_CEL_Header2 header2;
+ short x_pos;
+ short y_pos;
+ byte last_byte=0;
+ long file_size;
+
+ File_error=0;
+ Get_full_filename(filename,0);
+ if ((file=fopen(filename, "rb")))
+ {
+ if (Read_bytes(file,&header1,sizeof(T_CEL_Header1)))
+ {
+ file_size=File_length_file(file);
+ if ( (file_size>(long int)sizeof(T_CEL_Header1))
+ && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-(long int)sizeof(T_CEL_Header1)) ) )
+ {
+ // Chargement d'un fichier CEL sans signature (vieux fichiers)
+ Main_image_width=header1.Width;
+ Main_image_height=header1.Height;
+ Original_screen_X=Main_image_width;
+ Original_screen_Y=Main_image_height;
+ Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ // Chargement de l'image
+ /*Init_lecture();*/
+ for (y_pos=0;((y_pos> 4));
+ }
+ else
+ Pixel_load_function(x_pos,y_pos,(last_byte & 15));
+ /*Close_lecture();*/
+ }
+ }
+ else
+ {
+ // On réessaye avec le nouveau format
+
+ fseek(file,0,SEEK_SET);
+ if (Read_bytes(file,&header2,sizeof(T_CEL_Header2)))
+ {
+ // Chargement d'un fichier CEL avec signature (nouveaux fichiers)
+
+ Main_image_width=header2.Width+header2.X_offset;
+ Main_image_height=header2.Height+header2.Y_offset;
+ Original_screen_X=Main_image_width;
+ Original_screen_Y=Main_image_height;
+ Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ // Chargement de l'image
+ /*Init_lecture();*/
+
+ if (!File_error)
+ {
+ // Effacement du décalage
+ for (y_pos=0;y_pos> 4));
+ }
+ else
+ Pixel_load_function(x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15));
+ break;
+
+ case 8:
+ for (y_pos=0;((y_pos16 sont utilisées dans l'image
+ for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++);
+
+ if (x_pos==256)
+ {
+ // Cas d'une image 16 couleurs (écriture à l'ancien format)
+
+ header1.Width =Main_image_width;
+ header1.Height=Main_image_height;
+
+ if (Write_bytes(file,&header1,sizeof(T_CEL_Header1)))
+ {
+ // Sauvegarde de l'image
+ Init_write_buffer();
+ for (y_pos=0;((y_pos>4)!=0)
+ File_error=1;
+ }
+ else
+ {
+ if (Read_bytes(file,&header2,sizeof(T_CEL_Header2)))
+ {
+ if (memcmp(header2.Signature,"KiSS",4)==0)
+ {
+ if (header2.Kind!=0x10)
+ File_error=1;
+ }
+ else
+ File_error=1;
+ }
+ else
+ File_error=1;
+ }
+ fclose(file);
+ }
+ else
+ File_error=1;
+}
+
+
+// -- Lire un fichier au format KCF -----------------------------------------
+
+void Load_KCF(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+ T_KCF_Header buffer;
+ T_CEL_Header2 header2;
+ byte bytes[3];
+ int pal_index;
+ int color_index;
+ int index;
+ long file_size;
+
+
+ File_error=0;
+ Get_full_filename(filename,0);
+ if ((file=fopen(filename, "rb")))
+ {
+ file_size=File_length_file(file);
+ if (file_size==sizeof(T_KCF_Header))
+ {
+ // Fichier KCF à l'ancien format
+
+ if (Read_bytes(file,&buffer,sizeof(T_KCF_Header)))
+ {
+ // Init_preview(?); // Pas possible... pas d'image...
+
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+
+ // Chargement de la palette
+ for (pal_index=0;pal_index<10;pal_index++)
+ for (color_index=0;color_index<16;color_index++)
+ {
+ index=16+(pal_index*16)+color_index;
+ Main_palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4);
+ Main_palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4);
+ Main_palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4);
+ }
+
+ for (index=0;index<16;index++)
+ {
+ Main_palette[index].R=Main_palette[index+16].R;
+ Main_palette[index].G=Main_palette[index+16].G;
+ Main_palette[index].B=Main_palette[index+16].B;
+ }
+
+ Set_palette(Main_palette);
+ Remap_fileselector();
+ }
+ else
+ File_error=1;
+ }
+ else
+ {
+ // Fichier KCF au nouveau format
+
+ if (Read_bytes(file,&header2,sizeof(T_CEL_Header2)))
+ {
+ // Init_preview(?); // Pas possible... pas d'image...
+
+ index=(header2.Nb_bits==12)?16:0;
+ for (pal_index=0;pal_index> 4) << 4;
+ Main_palette[index].B=(bytes[0] & 15) << 4;
+ Main_palette[index].G=(bytes[1] & 15) << 4;
+ break;
+
+ case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB
+ Read_bytes(file,bytes,3);
+ Main_palette[index].R=bytes[0];
+ Main_palette[index].G=bytes[1];
+ Main_palette[index].B=bytes[2];
+ }
+
+ index++;
+ }
+ }
+
+ if (header2.Nb_bits==12)
+ for (index=0;index<16;index++)
+ {
+ Main_palette[index].R=Main_palette[index+16].R;
+ Main_palette[index].G=Main_palette[index+16].G;
+ Main_palette[index].B=Main_palette[index+16].B;
+ }
+
+ Set_palette(Main_palette);
+ Remap_fileselector();
+ }
+ else
+ File_error=1;
+ }
+ fclose(file);
+ }
+ else
+ File_error=1;
+
+ if (!File_error) Draw_palette_preview();
+}
+
+
+// -- Ecrire un fichier au format KCF ---------------------------------------
+
+void Save_KCF(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ FILE *file;
+ T_KCF_Header buffer;
+ T_CEL_Header2 header2;
+ byte bytes[3];
+ int pal_index;
+ int color_index;
+ int index;
+ dword Utilisation[256]; // Table d'utilisation de couleurs
+
+ // On commence par compter l'utilisation de chaque couleurs
+ Count_used_colors(Utilisation);
+
+ File_error=0;
+ Get_full_filename(filename,0);
+ if ((file=fopen(filename,"wb")))
+ {
+ // Sauvegarde de la palette
+
+ // On regarde si des couleurs >16 sont utilisées dans l'image
+ for (index=16;((index<256) && (!Utilisation[index]));index++);
+
+ if (index==256)
+ {
+ // Cas d'une image 16 couleurs (écriture à l'ancien format)
+
+ for (pal_index=0;pal_index<10;pal_index++)
+ for (color_index=0;color_index<16;color_index++)
+ {
+ index=16+(pal_index*16)+color_index;
+ buffer.Palette[pal_index].color[color_index].Byte1=((Main_palette[index].R>>4)<<4) | (Main_palette[index].B>>4);
+ buffer.Palette[pal_index].color[color_index].Byte2=Main_palette[index].G>>4;
+ }
+
+ if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header)))
+ File_error=1;
+ }
+ else
+ {
+ // Cas d'une image 256 couleurs (écriture au nouveau format)
+
+ memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature
+ header2.Kind=0x10; // Initialisation du type (PALette)
+ header2.Nb_bits=24; // Initialisation du nombre de bits
+ header2.Filler1=0; // Initialisation du filler 1 (?)
+ header2.Width=256; // Initialisation du nombre de couleurs
+ header2.Height=1; // Initialisation du nombre de palettes
+ header2.X_offset=0; // Initialisation du décalage X
+ header2.Y_offset=0; // Initialisation du décalage Y
+ for (index=0;index<16;index++) // Initialisation du filler 2 (?)
+ header2.Filler2[index]=0;
+
+ if (! Write_bytes(file,&header2,sizeof(T_CEL_Header2)))
+ File_error=1;
+
+ for (index=0;(index<256) && (!File_error);index++)
+ {
+ bytes[0]=Main_palette[index].R;
+ bytes[1]=Main_palette[index].G;
+ bytes[2]=Main_palette[index].B;
+ if (! Write_bytes(file,bytes,3))
+ File_error=1;
+ }
+ }
+
+ fclose(file);
+
+ if (File_error)
+ remove(filename);
+ }
+ else
+ File_error=1;
+}
+
+
+//////////////////////////////////// PI1 ////////////////////////////////////
+
+//// DECODAGE d'une partie d'IMAGE ////
+
+void PI1_8b_to_16p(byte * src,byte * dest)
+{
+ int i; // index du pixel à calculer
+ word byte_mask; // Masque de decodage
+ word w0,w1,w2,w3; // Les 4 words bien ordonnés de la source
+
+ byte_mask=0x8000;
+ w0=(((word)src[0])<<8) | src[1];
+ w1=(((word)src[2])<<8) | src[3];
+ w2=(((word)src[4])<<8) | src[5];
+ w3=(((word)src[6])<<8) | src[7];
+ for (i=0;i<16;i++)
+ {
+ // Pour décoder le pixel n°i, il faut traiter les 4 words sur leur bit
+ // correspondant à celui du masque
+
+ dest[i]=((w0 & byte_mask)?0x01:0x00) |
+ ((w1 & byte_mask)?0x02:0x00) |
+ ((w2 & byte_mask)?0x04:0x00) |
+ ((w3 & byte_mask)?0x08:0x00);
+ byte_mask>>=1;
+ }
+}
+
+//// CODAGE d'une partie d'IMAGE ////
+
+void PI1_16p_to_8b(byte * src,byte * dest)
+{
+ int i; // index du pixel à calculer
+ word byte_mask; // Masque de codage
+ word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination
+
+ byte_mask=0x8000;
+ w0=w1=w2=w3=0;
+ for (i=0;i<16;i++)
+ {
+ // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit
+ // correspondant à celui du masque
+
+ w0|=(src[i] & 0x01)?byte_mask:0x00;
+ w1|=(src[i] & 0x02)?byte_mask:0x00;
+ w2|=(src[i] & 0x04)?byte_mask:0x00;
+ w3|=(src[i] & 0x08)?byte_mask:0x00;
+ byte_mask>>=1;
+ }
+ dest[0]=w0 >> 8;
+ dest[1]=w0 & 0x00FF;
+ dest[2]=w1 >> 8;
+ dest[3]=w1 & 0x00FF;
+ dest[4]=w2 >> 8;
+ dest[5]=w2 & 0x00FF;
+ dest[6]=w3 >> 8;
+ dest[7]=w3 & 0x00FF;
+}
+
+//// DECODAGE de la PALETTE ////
+
+void PI1_decode_palette(byte * src,byte * palette)
+{
+ int i; // Numéro de la couleur traitée
+ int ip; // index dans la palette
+ word w; // Word contenant le code
+
+ // Schéma d'un word =
+ //
+ // Low High
+ // VVVV RRRR | 0000 BBBB
+ // 0321 0321 | 0321
+
+ ip=0;
+ for (i=0;i<16;i++)
+ {
+ w=((word)src[(i*2)+1]<<8) | src[(i*2)+0];
+
+ // Traitement des couleurs rouge, verte et bleue:
+ palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
+ palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
+ palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
+ }
+}
+
+//// CODAGE de la PALETTE ////
+
+void PI1_code_palette(byte * palette,byte * dest)
+{
+ int i; // Numéro de la couleur traitée
+ int ip; // index dans la palette
+ word w; // Word contenant le code
+
+ // Schéma d'un word =
+ //
+ // Low High
+ // VVVV RRRR | 0000 BBBB
+ // 0321 0321 | 0321
+
+ ip=0;
+ for (i=0;i<16;i++)
+ {
+ // Traitement des couleurs rouge, verte et bleue:
+ w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++;
+ w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++;
+ w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++;
+
+ dest[(i*2)+0]=w & 0x00FF;
+ dest[(i*2)+1]=(w>>8);
+ }
+}
+
+
+// -- Tester si un fichier est au format PI1 --------------------------------
+void Test_PI1(void)
+{
+ FILE * file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ int size; // Taille du fichier
+ word resolution; // Résolution de l'image
+
+
+ Get_full_filename(filename,0);
+
+ File_error=1;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ // Vérification de la taille
+ size=File_length_file(file);
+ if ((size==32034) || (size==32066))
+ {
+ // Lecture et vérification de la résolution
+ if (Read_word_le(file,&resolution))
+ {
+ if (resolution==0x0000)
+ File_error=0;
+ }
+ }
+ // Fermeture du fichier
+ fclose(file);
+ }
+}
+
+
+// -- Lire un fichier au format PI1 -----------------------------------------
+void Load_PI1(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ FILE *file;
+ word x_pos,y_pos;
+ byte * buffer;
+ byte * ptr;
+ byte pixels[320];
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+ if ((file=fopen(filename, "rb")))
+ {
+ // allocation d'un buffer mémoire
+ buffer=(byte *)malloc(32034);
+ if (buffer!=NULL)
+ {
+ // Lecture du fichier dans le buffer
+ if (Read_bytes(file,buffer,32034))
+ {
+ // Initialisation de la preview
+ Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ // Initialisation de la palette
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+ PI1_decode_palette(buffer+2,(byte *)Main_palette);
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ Main_image_width=320;
+ Main_image_height=200;
+
+ // Chargement/décompression de l'image
+ ptr=buffer+34;
+ for (y_pos=0;y_pos<200;y_pos++)
+ {
+ for (x_pos=0;x_pos<(320>>4);x_pos++)
+ {
+ PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
+ ptr+=8;
+ }
+ for (x_pos=0;x_pos<320;x_pos++)
+ Pixel_load_function(x_pos,y_pos,pixels[x_pos]);
+ }
+ }
+ }
+ else
+ File_error=1;
+ free(buffer);
+ }
+ else
+ File_error=1;
+ fclose(file);
+ }
+ else
+ File_error=1;
+}
+
+
+// -- Sauver un fichier au format PI1 ---------------------------------------
+void Save_PI1(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ FILE *file;
+ short x_pos,y_pos;
+ byte * buffer;
+ byte * ptr;
+ byte pixels[320];
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+ // Ouverture du fichier
+ if ((file=fopen(filename,"wb")))
+ {
+ // allocation d'un buffer mémoire
+ buffer=(byte *)malloc(32066);
+ // Codage de la résolution
+ buffer[0]=0x00;
+ buffer[1]=0x00;
+ // Codage de la palette
+ PI1_code_palette((byte *)Main_palette,buffer+2);
+ // Codage de l'image
+ ptr=buffer+34;
+ for (y_pos=0;y_pos<200;y_pos++)
+ {
+ // Codage de la ligne
+ memset(pixels,0,320);
+ if (y_pos>4);x_pos++)
+ {
+ PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
+ ptr+=8;
+ }
+ }
+
+ memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy
+
+ if (Write_bytes(file,buffer,32066))
+ {
+ fclose(file);
+ }
+ else // Error d'écriture (disque plein ou protégé)
+ {
+ fclose(file);
+ remove(filename);
+ File_error=1;
+ }
+ // Libération du buffer mémoire
+ free(buffer);
+ }
+ else
+ {
+ fclose(file);
+ remove(filename);
+ File_error=1;
+ }
+}
+
+
+//////////////////////////////////// PC1 ////////////////////////////////////
+
+//// DECOMPRESSION d'un buffer selon la méthode PACKBITS ////
+
+void PC1_uncompress_packbits(byte * src,byte * dest)
+{
+ int is,id; // Les indices de parcour des buffers
+ int n; // Octet de contrôle
+
+ for (is=id=0;id<32000;)
+ {
+ n=src[is++];
+
+ if (n & 0x80)
+ {
+ // Recopier src[is] -n+1 fois
+ n=257-n;
+ for (;(n>0) && (id<32000);n--)
+ dest[id++]=src[is];
+ is++;
+ }
+ else
+ {
+ // Recopier n+1 octets littéralement
+ n=n+1;
+ for (;(n>0) && (id<32000);n--)
+ dest[id++]=src[is++];
+ }
+
+ // Contrôle des erreurs
+ if (n>0)
+ File_error=1;
+ }
+}
+
+//// COMPRESSION d'un buffer selon la méthode PACKBITS ////
+
+void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size)
+{
+ int is; // index dans la source
+ int id; // index dans la destination
+ int ir; // index de la répétition
+ int n; // Taille des séquences
+ int repet; // "Il y a répétition"
+
+ for (is=id=0;is0;n--)
+ dest[id++]=src[is++];
+ }
+
+ // On code la partie sans répétitions
+ if (repet)
+ {
+ // On compte la quantité de fois qu'il faut répéter la valeur
+ for (ir+=3;ir>=1;
+ }
+ }
+}
+
+//// CODAGE d'une partie d'IMAGE ////
+
+// Transformation d'1 ligne de pixels en 4 plans de bits
+
+void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3)
+{
+ int i,j; // Compteurs
+ int ip; // index du pixel à calculer
+ byte byte_mask; // Masque de decodage
+ byte b0,b1,b2,b3; // Les 4 octets des plans bits sources
+
+ ip=0;
+ // Pour chacun des 40 octets des plans de bits
+ for (i=0;i<40;i++)
+ {
+ // Pour chacun des 8 bits des octets
+ byte_mask=0x80;
+ b0=b1=b2=b3=0;
+ for (j=0;j<8;j++)
+ {
+ b0|=(src[ip] & 0x01)?byte_mask:0x00;
+ b1|=(src[ip] & 0x02)?byte_mask:0x00;
+ b2|=(src[ip] & 0x04)?byte_mask:0x00;
+ b3|=(src[ip] & 0x08)?byte_mask:0x00;
+ ip++;
+ byte_mask>>=1;
+ }
+ dst0[i]=b0;
+ dst1[i]=b1;
+ dst2[i]=b2;
+ dst3[i]=b3;
+ }
+}
+
+
+// -- Tester si un fichier est au format PC1 --------------------------------
+void Test_PC1(void)
+{
+ FILE *file; // Fichier du fichier
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ int size; // Taille du fichier
+ word resolution; // Résolution de l'image
+
+
+ Get_full_filename(filename,0);
+
+ File_error=1;
+
+ // Ouverture du fichier
+ if ((file=fopen(filename, "rb")))
+ {
+ // Vérification de la taille
+ size=File_length_file(file);
+ if ((size<=32066))
+ {
+ // Lecture et vérification de la résolution
+ if (Read_word_le(file,&resolution))
+ {
+ if (resolution==0x0080)
+ File_error=0;
+ }
+ }
+ // Fermeture du fichier
+ fclose(file);
+ }
+}
+
+
+// -- Lire un fichier au format PC1 -----------------------------------------
+void Load_PC1(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ FILE *file;
+ int size;
+ word x_pos,y_pos;
+ byte * buffercomp;
+ byte * bufferdecomp;
+ byte * ptr;
+ byte pixels[320];
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+ if ((file=fopen(filename, "rb")))
+ {
+ size=File_length_file(file);
+ // allocation des buffers mémoire
+ buffercomp=(byte *)malloc(size);
+ bufferdecomp=(byte *)malloc(32000);
+ if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) )
+ {
+ // Lecture du fichier dans le buffer
+ if (Read_bytes(file,buffercomp,size))
+ {
+ // Initialisation de la preview
+ Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE);
+ if (File_error==0)
+ {
+ // Initialisation de la palette
+ if (Config.Clear_palette)
+ memset(Main_palette,0,sizeof(T_Palette));
+ PI1_decode_palette(buffercomp+2,(byte *)Main_palette);
+ Set_palette(Main_palette);
+ Remap_fileselector();
+
+ Main_image_width=320;
+ Main_image_height=200;
+
+ // Décompression du buffer
+ PC1_uncompress_packbits(buffercomp+34,bufferdecomp);
+
+ // Décodage de l'image
+ ptr=bufferdecomp;
+ for (y_pos=0;y_pos<200;y_pos++)
+ {
+ // Décodage de la scanline
+ PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels);
+ ptr+=160;
+ // Chargement de la ligne
+ for (x_pos=0;x_pos<320;x_pos++)
+ Pixel_load_function(x_pos,y_pos,pixels[x_pos]);
+ }
+ }
+ }
+ else
+ File_error=1;
+ free(bufferdecomp);
+ free(buffercomp);
+ }
+ else
+ {
+ File_error=1;
+ free(bufferdecomp);
+ free(buffercomp);
+ }
+ fclose(file);
+ }
+ else
+ File_error=1;
+}
+
+
+// -- Sauver un fichier au format PC1 ---------------------------------------
+void Save_PC1(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ FILE *file;
+ int size;
+ short x_pos,y_pos;
+ byte * buffercomp;
+ byte * bufferdecomp;
+ byte * ptr;
+ byte pixels[320];
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+ // Ouverture du fichier
+ if ((file=fopen(filename,"wb")))
+ {
+ // Allocation des buffers mémoire
+ bufferdecomp=(byte *)malloc(32000);
+ buffercomp =(byte *)malloc(64066);
+ // Codage de la résolution
+ buffercomp[0]=0x80;
+ buffercomp[1]=0x00;
+ // Codage de la palette
+ PI1_code_palette((byte *)Main_palette,buffercomp+2);
+ // Codage de l'image
+ ptr=bufferdecomp;
+ for (y_pos=0;y_pos<200;y_pos++)
+ {
+ // Codage de la ligne
+ memset(pixels,0,320);
+ if (y_pos>4);x_pos++)
+ {
+ PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
+ ptr+=8;
+ }
+ for (x_pos=0;x_pos<320;x_pos++)
+ Pixel_load_function(x_pos,y_pos,pixels[x_pos]);
+ }
+ }
+ }
+ else
+ File_error=1;
+ free(buffer);
+ }
+ else
+ File_error=1;
+ fclose(file);
+ }
+ else
+ File_error=1;
+}
+
+void Save_NEO(void)
+{
+ char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
+ FILE *file;
+ short x_pos,y_pos;
+ byte * buffer;
+ byte * ptr;
+ byte pixels[320];
+
+ Get_full_filename(filename,0);
+
+ File_error=0;
+ // Ouverture du fichier
+ if ((file=fopen(filename,"wb")))
+ {
+ // allocation d'un buffer mémoire
+ buffer=(byte *)malloc(32128);
+ // Codage de la résolution
+ buffer[0]=0x00;
+ buffer[1]=0x00;
+ buffer[2]=0x00;
+ buffer[3]=0x00;
+ // Codage de la palette
+ PI1_code_palette((byte *)Main_palette,buffer+4);
+ // Codage de l'image
+ ptr=buffer+128;
+ for (y_pos=0;y_pos<200;y_pos++)
+ {
+ // Codage de la ligne
+ memset(pixels,0,320);
+ if (y_pos>4);x_pos++)
+ {
+ PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
+ ptr+=8;
+ }
+ }
+
+ if (Write_bytes(file,buffer,32128))
+ {
+ fclose(file);
+ }
+ else // Error d'écriture (disque plein ou protégé)
+ {
+ fclose(file);
+ remove(filename);
+ File_error=1;
+ }
+ // Libération du buffer mémoire
+ free(buffer);
+ }
+ else
+ {
+ fclose(file);
+ remove(filename);
+ File_error=1;
+ }
+}
+
+//////////////////////////////////// C64 ////////////////////////////////////
+void Test_C64(void)
+{
+ FILE* file;
+ char filename[MAX_PATH_CHARACTERS];
+ long file_size;
+
+ Get_full_filename(filename,0);
+
+ file = fopen(filename,"rb");
+
+ if (file)
+ {
+ file_size = File_length_file(file);
+ switch (file_size)
+ {
+ 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 10001: // multicolor
+ case 10003: // multicolor + loadaddr
+ File_error = 0;
+ break;
+ default: // then we don't know for now.
+ File_error = 1;
+ }
+ fclose (file);
+ }
+ else
+ {
+ File_error = 1;
+ }
+}
+
+void Load_C64_hires(byte *bitmap, byte *colors)
+{
+ int cx,cy,x,y,c[4],pixel,color;
+
+ for(cy=0; cy<25; cy++)
+ {
+ for(cx=0; cx<40; cx++)
+ {
+ c[1]=colors[cy*40+cx]&15;
+ c[0]=colors[cy*40+cx]>>4;
+ for(y=0; y<8; y++)
+ {
+ pixel=bitmap[cy*320+cx*8+y];
+ for(x=0; x<8; x++)
+ {
+ color=c[pixel&(1<<(7-x))?1:0];
+ Pixel_load_function(cx*8+x,cy*8+y,color);
+ }
+ }
+ }
+ }
+}
+
+void Load_C64_multi(byte *bitmap, byte *colors, byte *nybble, byte background)
+{
+ int cx,cy,x,y,c[4],pixel,color;
+ c[0]=background;
+ for(cy=0; cy<25; cy++)
+ {
+ 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];
+
+ for(y=0; y<8; y++)
+ {
+ pixel=bitmap[cy*320+cx*8+y];
+ for(x=0; x<4; x++)
+ {
+ color=c[(pixel&3)];
+ pixel>>=2;
+ Pixel_load_function(cx*4+(3-x),cy*8+y,color);
+ }
+ }
+ }
+ }
+}
+
+void Load_C64(void)
+{
+ FILE* file;
+ char filename[MAX_PATH_CHARACTERS];
+ long file_size;
+ int i;
+ byte background,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"};
+
+ // Palette from http://www.pepto.de/projects/colorvic/
+ byte pal[48]={
+ 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF,
+ 0x68, 0x37, 0x2B,
+ 0x70, 0xA4, 0xB2,
+ 0x6F, 0x3D, 0x86,
+ 0x58, 0x8D, 0x43,
+ 0x35, 0x28, 0x79,
+ 0xB8, 0xC7, 0x6F,
+ 0x6F, 0x4F, 0x25,
+ 0x43, 0x39, 0x00,
+ 0x9A, 0x67, 0x59,
+ 0x44, 0x44, 0x44,
+ 0x6C, 0x6C, 0x6C,
+ 0x9A, 0xD2, 0x84,
+ 0x6C, 0x5E, 0xB5,
+ 0x95, 0x95, 0x95};
+
+ byte bitmap[8000],colors[1000],nybble[1000];
+ word width=320, height=200;
+
+ Get_full_filename(filename,0);
+ file = fopen(filename,"rb");
+
+ if (file)
+ {
+ File_error=0;
+ file_size = File_length_file(file);
+
+ 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;
+
+ case 8002: // raw bitmap with loadaddr
+ hasLoadAddr=1;
+ loadFormat=F_bitmap;
+ break;
+
+ case 9000: // bitmap + screen
+ hasLoadAddr=0;
+ loadFormat=F_hires;
+ break;
+
+ case 9002: // bitmap + screen + loadaddr
+ hasLoadAddr=1;
+ loadFormat=F_hires;
+ break;
+
+ case 10001: // multicolor
+ hasLoadAddr=0;
+ loadFormat=F_multi;
+ break;
+
+ case 10003: // multicolor + loadaddr
+ hasLoadAddr=1;
+ loadFormat=F_multi;
+ break;
+
+ default: // then we don't know what it is.
+ File_error = 1;
+
+ }
+
+ memcpy(Main_palette,pal,48); // this set the software palette for grafx2
+ Set_palette(Main_palette); // this set the hardware palette for SDL
+ Remap_fileselector(); // 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)
+ {
+ Ratio_of_loaded_image = PIXEL_WIDE;
+ }
+ sprintf(Main_comment,"C64 %s, %s",
+ c64_format_names[loadFormat],filename);
+ Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // Do this as soon as you can
+
+ Main_image_width = width ;
+ Main_image_height = height;
+
+ Read_bytes(file,bitmap,8000);
+
+ if (file_size>8002)
+ Read_bytes(file,colors,1000);
+ else
+ {
+ for(i=0;i<1000;i++)
+ {
+ colors[i]=1;
+ }
+ }
+
+ if(width==160)
+ {
+ Read_bytes(file,nybble,1000);
+ Read_byte(file,&background);
+ Load_C64_multi(bitmap,colors,nybble,background);
+ }
+ else
+ {
+ Load_C64_hires(bitmap,colors);
+ }
+
+ File_error = 0;
+ fclose(file);
+ }
+ else
+ File_error = 1;
+}
+
+int Save_C64_window(byte *saveWhat, byte *loadAddr)
+{
+ int button;
+ unsigned int i;
+ T_Dropdown_button *what, *addr;
+ char * what_label[] = {
+ "All",
+ "Bitmap",
+ "Screen",
+ "Color"
+ };
+ char * address_label[] = {
+ "None",
+ "$2000",
+ "$4000",
+ "$6000",
+ "$8000",
+ "$A000",
+ "$C000",
+ "$E000"
+ };
+
+ 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);
+
+ 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);
+ Window_dropdown_clear_items(what);
+ for (i=0; i2)
+ {
+ Warning_message("More than 2 colors in 8x8 pixels");
+ // TODO here we should hilite the offending block
+ printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors);
+ return 1;
+ }
+ for(i=0;i<16;i++)
+ {
+ if(cusage[i])
+ {
+ c2=i;
+ break;
+ }
+ }
+ c1=c2;
+ for(i=c2+1;i<16;i++)
+ {
+ if(cusage[i])
+ {
+ c1=i;
+ }
+ }
+ colors[cx+cy*40]=(c2<<4)|c1;
+
+ for(y=0; y<8; y++)
+ {
+ bits=0;
+ for(x=0; x<8; x++)
+ {
+ pixel=Read_pixel_function(x+cx*8,y+cy*8);
+ if(pixel>15)
+ {
+ Warning_message("Color above 15 used");
+ // TODO hilite offending block here too?
+ // or make it smarter with color allocation?
+ // However, the palette is fixed to the 16 first colors
+ return 1;
+ }
+ bits=bits<<1;
+ if (pixel==c1) bits|=1;
+ }
+ bitmap[pos++]=bits;
+ //Write_byte(file,bits&255);
+ }
+ }
+ }
+
+ file = fopen(filename,"wb");
+
+ if(!file)
+ {
+ Warning_message("File open failed");
+ File_error = 1;
+ return 1;
+ }
+
+ if (loadAddr)
+ {
+ Write_byte(file,0);
+ Write_byte(file,loadAddr);
+ }
+ if (saveWhat==0 || saveWhat==1)
+ Write_bytes(file,bitmap,8000);
+ if (saveWhat==0 || saveWhat==2)
+ Write_bytes(file,colors,1000);
+
+ fclose(file);
+ return 0;
+}
+
+int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr)
+{
+ /*
+ 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)
+ */
+
+ 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];
+ word numcolors,count;
+ dword cusage[256];
+ byte i,background=0;
+ FILE *file;
+
+ numcolors=Count_used_colors(cusage);
+
+ count=0;
+ for(x=0;x<16;x++)
+ {
+ //printf("color %d, pixels %d\n",x,cusage[x]);
+ if(cusage[x]>count)
+ {
+ count=cusage[x];
+ background=x;
+ }
+ }
+
+ for(cy=0; cy<25; cy++)
+ {
+ //printf("\ny:%2d ",cy);
+ for(cx=0; cx<40; cx++)
+ {
+ numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8);
+ if(numcolors>4)
+ {
+ Warning_message("More than 4 colors in 4x8");
+ // TODO hilite offending block
+ return 1;
+ }
+ color=1;
+ c[0]=background;
+ for(i=0; i<16; i++)
+ {
+ lut[i]=0;
+ if(cusage[i])
+ {
+ if(i!=background)
+ {
+ lut[i]=color;
+ c[color]=i;
+ color++;
+ }
+ else
+ {
+ lut[i]=0;
+ }
+ }
+ }
+ // add to screen and nybble
+ screen[cx+cy*40]=c[1]<<4|c[2];
+ nybble[cx+cy*40]=c[3];
+ //printf("%x%x%x ",c[1],c[2],c[3]);
+ for(y=0;y<8;y++)
+ {
+ bits=0;
+ for(x=0;x<4;x++)
+ {
+ pixel=Read_pixel_function(cx*4+x,cy*8+y);
+ if(pixel>15)
+ {
+ Warning_message("Color above 15 used");
+ // TODO hilite as in hires, you should stay to
+ // the fixed 16 color palette
+ return 1;
+ }
+ bits=bits<<2;
+ bits|=lut[pixel];
+
+ }
+ //Write_byte(file,bits&255);
+ bitmap[pos++]=bits;
+ }
+ }
+ }
+
+ file = fopen(filename,"wb");
+
+ if(!file)
+ {
+ Warning_message("File open failed");
+ File_error = 1;
+ return 1;
+ }
+
+ if (loadAddr)
+ {
+ Write_byte(file,0);
+ Write_byte(file,loadAddr);
+ }
+
+ if (saveWhat==0 || saveWhat==1)
+ Write_bytes(file,bitmap,8000);
+
+ if (saveWhat==0 || saveWhat==2)
+ Write_bytes(file,screen,1000);
+
+ if (saveWhat==0 || saveWhat==3)
+ Write_bytes(file,nybble,1000);
+
+ if (saveWhat==0)
+ Write_byte(file,background);
+
+ fclose(file);
+ //printf("\nbg:%d\n",background);
+ return 0;
+}
+
+void Save_C64(void)
+{
+ char filename[MAX_PATH_CHARACTERS];
+ static byte saveWhat=0, loadAddr=0;
+ dword numcolors,cusage[256];
+ numcolors=Count_used_colors(cusage);
+
+ Get_full_filename(filename,0);
+
+ if (numcolors>16)
+ {
+ Warning_message("Error: Max 16 colors");
+ File_error = 1;
+ return;
+ }
+ if (((Main_image_width!=320) && (Main_image_width!=160)) || Main_image_height!=200)
+ {
+ Warning_message("must be 320x200 or 160x200");
+ File_error = 1;
+ return;
+ }
+
+ if(!Save_C64_window(&saveWhat,&loadAddr))
+ {
+ File_error = 1;
+ return;
+ }
+ //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr);
+
+ if (Main_image_width==320)
+ File_error = Save_C64_hires(filename,saveWhat,loadAddr);
+ else
+ File_error = Save_C64_multi(filename,saveWhat,loadAddr);
+}
+