1
/* vim:expandtab:ts=2 sw=2:
3
/* Grafx2 - The Ultimate 256-color bitmap paint program
5
Copyright 2009 Petter Lindquist
6
Copyright 2008 Yves Rizoud
7
Copyright 2008 Franck Charlet
8
Copyright 2007 Adrien Destugues
9
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
11
Grafx2 is free software; you can redistribute it and/or
12
modify it under the terms of the GNU General Public License
13
as published by the Free Software Foundation; version 2
16
Grafx2 is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
25
///@file miscfileformats.c
26
/// Formats that aren't fully saving, either because of palette restrictions or other things
35
#include "libraw2crtc.h"
39
#include "sdlscreen.h"
43
//////////////////////////////////// PAL ////////////////////////////////////
46
// -- Tester si un fichier est au format PAL --------------------------------
47
void Test_PAL(T_IO_Context * context)
49
FILE *file; // Fichier du fichier
50
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
51
long file_size; // Taille du fichier
53
Get_full_filename(filename, context->File_name, context->File_directory);
57
// Ouverture du fichier
58
if ((file = fopen(filename, "rb")))
60
// Lecture de la taille du fichier
61
file_size = File_length_file(file);
62
// Le fichier ne peut �tre au format PAL que si sa taille vaut 768 octets
63
if (file_size == sizeof(T_Palette))
66
// Sinon c'est peut �tre un fichier palette ASCII "Jasc"
67
fread(filename, 1, 8, file);
68
if (strncmp(filename,"JASC-PAL",8) == 0)
78
// -- Lire un fichier au format PAL -----------------------------------------
79
void Load_PAL(T_IO_Context * context)
81
FILE *file; // Fichier du fichier
82
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
83
//long file_size; // Taille du fichier
86
Get_full_filename(filename, context->File_name, context->File_directory);
89
// Ouverture du fichier
90
if ((file=fopen(filename, "rb")))
92
long file_size = File_length_file(file);
93
// Le fichier ne peut �tre au format PAL que si sa taille vaut 768 octets
94
if (file_size == sizeof(T_Palette))
97
// Pre_load(context, ?); // Pas possible... pas d'image...
99
// Lecture du fichier dans context->Palette
100
if (Read_bytes(file, palette_64, sizeof(T_Palette)))
102
Palette_64_to_256(palette_64);
103
memcpy(context->Palette, palette_64, sizeof(T_Palette));
104
Palette_loaded(context);
109
fread(filename, 1, 8, file);
110
if (strncmp(filename,"JASC-PAL",8) == 0)
113
fscanf(file, "%d",&n);
121
fscanf(file, "%d",&n);
122
for (i = 0; i < n; i++)
124
fscanf(file, "%d %d %d",&r, &g, &b);
125
context->Palette[i].R = r;
126
context->Palette[i].G = g;
127
context->Palette[i].B = b;
129
Palette_loaded(context);
130
} else File_error = 2;
134
// Fermeture du fichier
138
// Si on n'a pas r�ussi � ouvrir le fichier, alors il y a eu une erreur
143
// -- Sauver un fichier au format PAL ---------------------------------------
144
void Save_PAL(T_IO_Context * context)
147
char filename[MAX_PATH_CHARACTERS]; ///< full filename
149
Get_full_filename(filename, context->File_name, context->File_directory);
154
if ((file=fopen(filename,"w")))
157
if (fputs("JASC-PAL\n0100\n256\n", file)==EOF)
159
for (i = 0; i < 256 && File_error==0; i++)
161
if (fprintf(file,"%d %d %d\n",context->Palette[i].R, context->Palette[i].G, context->Palette[i].B) <= 0)
172
// unable to open output file, nothing saved.
178
//////////////////////////////////// PKM ////////////////////////////////////
181
char Ident[3]; // String "PKM" }
182
byte Method; // Compression method
183
// 0 = per-line compression (c)KM
184
// others = unknown at the moment
185
byte Recog1; // Recognition byte 1
186
byte Recog2; // Recognition byte 2
187
word Width; // Image width
188
word Height; // Image height
189
T_Palette Palette;// RGB Palette 256*3, on a 1-64 scale for each component
190
word Jump; // Size of the jump between header and image:
191
// Used to insert a comment
194
// -- Tester si un fichier est au format PKM --------------------------------
195
void Test_PKM(T_IO_Context * context)
197
FILE *file; // Fichier du fichier
198
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
202
Get_full_filename(filename, context->File_name, context->File_directory);
206
// Ouverture du fichier
207
if ((file=fopen(filename, "rb")))
209
// Lecture du header du fichier
210
if (Read_bytes(file,&header.Ident,3) &&
211
Read_byte(file,&header.Method) &&
212
Read_byte(file,&header.Recog1) &&
213
Read_byte(file,&header.Recog2) &&
214
Read_word_le(file,&header.Width) &&
215
Read_word_le(file,&header.Height) &&
216
Read_bytes(file,&header.Palette,sizeof(T_Palette)) &&
217
Read_word_le(file,&header.Jump))
219
// On regarde s'il y a la signature PKM suivie de la m�thode 0.
220
// La constante "PKM" �tant un cha�ne, elle se termine toujours par 0.
221
// Donc pas la peine de s'emm...er � regarder si la m�thode est � 0.
222
if ( (!memcmp(&header,"PKM",4)) && header.Width && header.Height)
230
// -- Lire un fichier au format PKM -----------------------------------------
231
void Load_PKM(T_IO_Context * context)
233
FILE *file; // Fichier du fichier
234
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
240
dword Compteur_de_pixels;
241
dword Compteur_de_donnees_packees;
246
Get_full_filename(filename, context->File_name, context->File_directory);
250
if ((file=fopen(filename, "rb")))
252
file_size=File_length_file(file);
254
if (Read_bytes(file,&header.Ident,3) &&
255
Read_byte(file,&header.Method) &&
256
Read_byte(file,&header.Recog1) &&
257
Read_byte(file,&header.Recog2) &&
258
Read_word_le(file,&header.Width) &&
259
Read_word_le(file,&header.Height) &&
260
Read_bytes(file,&header.Palette,sizeof(T_Palette)) &&
261
Read_word_le(file,&header.Jump))
263
context->Comment[0]='\0'; // On efface le commentaire
267
while ( (index<header.Jump) && (!File_error) )
269
if (Read_byte(file,&temp_byte))
271
index+=2; // On rajoute le "Field-id" et "le Field-size" pas encore lu
274
case 0 : // Commentaire
275
if (Read_byte(file,&temp_byte))
277
if (temp_byte>COMMENT_SIZE)
279
color=temp_byte; // On se sert de color comme
280
temp_byte=COMMENT_SIZE; // variable temporaire
286
if (Read_bytes(file,context->Comment,temp_byte))
289
context->Comment[temp_byte]='\0';
291
if (fseek(file,color,SEEK_CUR))
301
case 1 : // Dimensions de l'�cran d'origine
302
if (Read_byte(file,&temp_byte))
307
if ( ! Read_word_le(file,(word *) &Original_screen_X)
308
|| !Read_word_le(file,(word *) &Original_screen_Y) )
318
case 2 : // color de transparence
319
if (Read_byte(file,&temp_byte))
324
if (! Read_byte(file,&Back_color))
335
if (Read_byte(file,&temp_byte))
338
if (fseek(file,temp_byte,SEEK_CUR))
348
if ( (!File_error) && (index!=header.Jump) )
356
Pre_load(context, header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE,0);
360
context->Width=header.Width;
361
context->Height=header.Height;
362
image_size=(dword)(context->Width*context->Height);
364
memcpy(context->Palette,header.Palette,sizeof(T_Palette));
365
Palette_64_to_256(context->Palette);
366
Palette_loaded(context);
368
Compteur_de_donnees_packees=0;
369
Compteur_de_pixels=0;
370
Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump;
372
// Boucle de d�compression:
373
while ( (Compteur_de_pixels<image_size) && (Compteur_de_donnees_packees<Taille_pack) && (!File_error) )
375
if(Read_byte(file, &temp_byte)!=1)
381
// Si ce n'est pas un octet de reconnaissance, c'est un pixel brut
382
if ( (temp_byte!=header.Recog1) && (temp_byte!=header.Recog2) )
384
Set_pixel(context, Compteur_de_pixels % context->Width,
385
Compteur_de_pixels / context->Width,
387
Compteur_de_donnees_packees++;
388
Compteur_de_pixels++;
390
else // Sinon, On regarde si on va d�compacter un...
391
{ // ... nombre de pixels tenant sur un byte
392
if (temp_byte==header.Recog1)
394
if(Read_byte(file, &color)!=1)
399
if(Read_byte(file, &temp_byte)!=1)
404
for (index=0; index<temp_byte; index++)
405
Set_pixel(context, (Compteur_de_pixels+index) % context->Width,
406
(Compteur_de_pixels+index) / context->Width,
408
Compteur_de_pixels+=temp_byte;
409
Compteur_de_donnees_packees+=3;
411
else // ... nombre de pixels tenant sur un word
413
if(Read_byte(file, &color)!=1)
418
Read_word_be(file, &len);
419
for (index=0; index<len; index++)
420
Set_pixel(context, (Compteur_de_pixels+index) % context->Width,
421
(Compteur_de_pixels+index) / context->Width,
423
Compteur_de_pixels+=len;
424
Compteur_de_donnees_packees+=4;
432
else // Lecture header impossible: Error ne modifiant pas l'image
437
else // Ouv. fichier impossible: Error ne modifiant pas l'image
442
// -- Sauver un fichier au format PKM ---------------------------------------
444
// Trouver quels sont les octets de reconnaissance
445
void Find_recog(byte * recog1, byte * recog2)
447
dword Find_recon[256]; // Table d'utilisation de couleurs
448
byte best; // Meilleure couleur pour recon (recon1 puis recon2)
449
dword NBest; // Nombre d'occurences de cette couleur
453
// On commence par compter l'utilisation de chaque couleurs
454
Count_used_colors(Find_recon);
456
// Ensuite recog1 devient celle la moins utilis�e de celles-ci
459
NBest=INT_MAX; // Une m�me couleur ne pourra jamais �tre utilis�e 1M de fois.
460
for (index=1;index<=255;index++)
461
if (Find_recon[index]<NBest)
464
NBest=Find_recon[index];
468
// Enfin recog2 devient la 2�me moins utilis�e
472
for (index=0;index<=255;index++)
473
if ( (Find_recon[index]<NBest) && (index!=*recog1) )
476
NBest=Find_recon[index];
482
void Save_PKM(T_IO_Context * context)
484
char filename[MAX_PATH_CHARACTERS];
487
dword Compteur_de_pixels;
496
// Construction du header
497
memcpy(header.Ident,"PKM",3);
499
Find_recog(&header.Recog1,&header.Recog2);
500
header.Width=context->Width;
501
header.Height=context->Height;
502
memcpy(header.Palette,context->Palette,sizeof(T_Palette));
503
Palette_256_to_64(header.Palette);
505
// Calcul de la taille du Post-header
506
header.Jump=9; // 6 pour les dimensions de l'ecran + 3 pour la back-color
507
comment_size=strlen(context->Comment);
509
header.Jump+=comment_size+2;
512
Get_full_filename(filename, context->File_name, context->File_directory);
516
// Ouverture du fichier
517
if ((file=fopen(filename,"wb")))
519
// Ecriture du header
520
if (Write_bytes(file,&header.Ident,3) &&
521
Write_byte(file,header.Method) &&
522
Write_byte(file,header.Recog1) &&
523
Write_byte(file,header.Recog2) &&
524
Write_word_le(file,header.Width) &&
525
Write_word_le(file,header.Height) &&
526
Write_bytes(file,&header.Palette,sizeof(T_Palette)) &&
527
Write_word_le(file,header.Jump))
531
// Ecriture du commentaire
532
// (Compteur_de_pixels est utilis� ici comme simple index de comptage)
535
Write_one_byte(file,0);
536
Write_one_byte(file,comment_size);
537
for (Compteur_de_pixels=0; Compteur_de_pixels<comment_size; Compteur_de_pixels++)
538
Write_one_byte(file,context->Comment[Compteur_de_pixels]);
540
// Ecriture des dimensions de l'�cran
541
Write_one_byte(file,1);
542
Write_one_byte(file,4);
543
Write_one_byte(file,Screen_width&0xFF);
544
Write_one_byte(file,Screen_width>>8);
545
Write_one_byte(file,Screen_height&0xFF);
546
Write_one_byte(file,Screen_height>>8);
547
// Ecriture de la back-color
548
Write_one_byte(file,2);
549
Write_one_byte(file,1);
550
Write_one_byte(file,Back_color);
552
// Routine de compression PKM de l'image
553
image_size=(dword)(context->Width*context->Height);
554
Compteur_de_pixels=0;
555
pixel_value=Get_pixel(context, 0,0);
557
while ( (Compteur_de_pixels<image_size) && (!File_error) )
559
Compteur_de_pixels++;
561
last_color=pixel_value;
562
if(Compteur_de_pixels<image_size)
564
pixel_value=Get_pixel(context, Compteur_de_pixels % context->Width,Compteur_de_pixels / context->Width);
566
while ( (pixel_value==last_color)
567
&& (Compteur_de_pixels<image_size)
568
&& (repetitions<65535) )
570
Compteur_de_pixels++;
572
if(Compteur_de_pixels>=image_size) break;
573
pixel_value=Get_pixel(context, Compteur_de_pixels % context->Width,Compteur_de_pixels / context->Width);
576
if ( (last_color!=header.Recog1) && (last_color!=header.Recog2) )
579
Write_one_byte(file,last_color);
583
Write_one_byte(file,last_color);
584
Write_one_byte(file,last_color);
587
if ( (repetitions>2) && (repetitions<256) )
588
{ // RECON1/couleur/nombre
589
Write_one_byte(file,header.Recog1);
590
Write_one_byte(file,last_color);
591
Write_one_byte(file,repetitions&0xFF);
594
if (repetitions>=256)
595
{ // RECON2/couleur/hi(nombre)/lo(nombre)
596
Write_one_byte(file,header.Recog2);
597
Write_one_byte(file,last_color);
598
Write_one_byte(file,repetitions>>8);
599
Write_one_byte(file,repetitions&0xFF);
606
Write_one_byte(file,header.Recog1);
607
Write_one_byte(file,last_color);
608
Write_one_byte(file,repetitions&0xFF);
612
Write_one_byte(file,header.Recog2);
613
Write_one_byte(file,last_color);
614
Write_one_byte(file,repetitions>>8);
615
Write_one_byte(file,repetitions&0xFF);
631
// S'il y a eu une erreur de sauvegarde, on ne va tout de m�me pas laisser
632
// ce fichier pourri tra�ner... Ca fait pas propre.
638
//////////////////////////////////// CEL ////////////////////////////////////
642
word Width; // width de l'image
643
word Height; // height de l'image
648
byte Signature[4]; // Signature du format
649
byte Kind; // Type de fichier ($10=PALette $20=BitMaP)
650
byte Nb_bits; // Nombre de bits
652
word Width; // width de l'image
653
word Height; // height de l'image
654
word X_offset; // Offset en X de l'image
655
word Y_offset; // Offset en Y de l'image
656
byte Filler2[16]; // ???
660
// -- Tester si un fichier est au format CEL --------------------------------
662
void Test_CEL(T_IO_Context * context)
664
char filename[MAX_PATH_CHARACTERS];
667
T_CEL_Header1 header1;
668
T_CEL_Header2 header2;
672
Get_full_filename(filename, context->File_name, context->File_directory);
673
file_size=File_length(filename);
676
File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber
680
if (! (file=fopen(filename, "rb")))
685
if (Read_word_le(file,&header1.Width) &&
686
Read_word_le(file,&header1.Height) )
688
// Vu que ce header n'a pas de signature, il va falloir tester la
689
// coh�rence de la dimension de l'image avec celle du fichier.
691
size=file_size-sizeof(T_CEL_Header1);
692
if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) )
694
// Tentative de reconnaissance de la signature des nouveaux fichiers
696
fseek(file,0,SEEK_SET);
697
if (Read_bytes(file,&header2.Signature,4) &&
698
!memcmp(header2.Signature,"KiSS",4) &&
699
Read_byte(file,&header2.Kind) &&
700
(header2.Kind==0x20) &&
701
Read_byte(file,&header2.Nb_bits) &&
702
Read_word_le(file,&header2.Filler1) &&
703
Read_word_le(file,&header2.Width) &&
704
Read_word_le(file,&header2.Height) &&
705
Read_word_le(file,&header2.X_offset) &&
706
Read_word_le(file,&header2.Y_offset) &&
707
Read_bytes(file,&header2.Filler2,16))
725
// -- Lire un fichier au format CEL -----------------------------------------
727
void Load_CEL(T_IO_Context * context)
729
char filename[MAX_PATH_CHARACTERS];
731
T_CEL_Header1 header1;
732
T_CEL_Header2 header2;
737
const long int header_size = (long int)(sizeof(header1.Width)+sizeof(header1.Height));
740
Get_full_filename(filename, context->File_name, context->File_directory);
741
if ((file=fopen(filename, "rb")))
743
if (Read_word_le(file,&(header1.Width))
744
&& Read_word_le(file,&(header1.Height)))
746
file_size=File_length_file(file);
747
if ( (file_size>header_size)
748
&& ( (((header1.Width+1)>>1)*header1.Height)==(file_size-header_size) ) )
750
// Chargement d'un fichier CEL sans signature (vieux fichiers)
751
context->Width=header1.Width;
752
context->Height=header1.Height;
753
Original_screen_X=context->Width;
754
Original_screen_Y=context->Height;
755
Pre_load(context, context->Width,context->Height,file_size,FORMAT_CEL,PIXEL_SIMPLE,0);
758
// Chargement de l'image
760
for (y_pos=0;((y_pos<context->Height) && (!File_error));y_pos++)
761
for (x_pos=0;((x_pos<context->Width) && (!File_error));x_pos++)
764
if(Read_byte(file,&last_byte)!=1) File_error = 2;
765
Set_pixel(context, x_pos,y_pos,(last_byte >> 4));
768
Set_pixel(context, x_pos,y_pos,(last_byte & 15));
774
// On r�essaye avec le nouveau format
776
fseek(file,0,SEEK_SET);
777
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature))
778
&& Read_byte(file,&(header2.Kind))
779
&& Read_byte(file,&(header2.Nb_bits))
780
&& Read_word_le(file,&(header2.Filler1))
781
&& Read_word_le(file,&(header2.Width))
782
&& Read_word_le(file,&(header2.Height))
783
&& Read_word_le(file,&(header2.X_offset))
784
&& Read_word_le(file,&(header2.Y_offset))
785
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2))
788
// Chargement d'un fichier CEL avec signature (nouveaux fichiers)
790
context->Width=header2.Width+header2.X_offset;
791
context->Height=header2.Height+header2.Y_offset;
792
Original_screen_X=context->Width;
793
Original_screen_Y=context->Height;
794
Pre_load(context, context->Width,context->Height,file_size,FORMAT_CEL,PIXEL_SIMPLE,0);
797
// Chargement de l'image
802
// Effacement du d�calage
803
for (y_pos=0;y_pos<header2.Y_offset;y_pos++)
804
for (x_pos=0;x_pos<context->Width;x_pos++)
805
Set_pixel(context, x_pos,y_pos,0);
806
for (y_pos=header2.Y_offset;y_pos<context->Height;y_pos++)
807
for (x_pos=0;x_pos<header2.X_offset;x_pos++)
808
Set_pixel(context, x_pos,y_pos,0);
810
switch(header2.Nb_bits)
813
for (y_pos=0;((y_pos<header2.Height) && (!File_error));y_pos++)
814
for (x_pos=0;((x_pos<header2.Width) && (!File_error));x_pos++)
817
if(Read_byte(file,&last_byte)!=1) File_error=2;
818
Set_pixel(context, x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte >> 4));
821
Set_pixel(context, x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15));
825
for (y_pos=0;((y_pos<header2.Height) && (!File_error));y_pos++)
826
for (x_pos=0;((x_pos<header2.Width) && (!File_error));x_pos++)
829
if(Read_byte(file,&byte_read)!=1) File_error = 2;
830
Set_pixel(context, x_pos+header2.X_offset,y_pos+header2.Y_offset,byte_read);
854
// -- Ecrire un fichier au format CEL ---------------------------------------
856
void Save_CEL(T_IO_Context * context)
858
char filename[MAX_PATH_CHARACTERS];
860
T_CEL_Header1 header1;
861
T_CEL_Header2 header2;
865
dword Utilisation[256]; // Table d'utilisation de couleurs
868
// On commence par compter l'utilisation de chaque couleurs
869
Count_used_colors(Utilisation);
872
Get_full_filename(filename, context->File_name, context->File_directory);
873
if ((file=fopen(filename,"wb")))
875
// On regarde si des couleurs >16 sont utilis�es dans l'image
876
for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++);
880
// Cas d'une image 16 couleurs (�criture � l'ancien format)
882
header1.Width =context->Width;
883
header1.Height=context->Height;
885
if (Write_word_le(file,header1.Width)
886
&& Write_word_le(file,header1.Height)
889
// Sauvegarde de l'image
891
for (y_pos=0;((y_pos<context->Height) && (!File_error));y_pos++)
893
for (x_pos=0;((x_pos<context->Width) && (!File_error));x_pos++)
895
last_byte=(Get_pixel(context, x_pos,y_pos) << 4);
898
last_byte=last_byte | (Get_pixel(context, x_pos,y_pos) & 15);
899
Write_one_byte(file,last_byte);
903
Write_one_byte(file,last_byte);
913
// Cas d'une image 256 couleurs (�criture au nouveau format)
915
// Recherche du d�calage
916
for (y_pos=0;y_pos<context->Height;y_pos++)
918
for (x_pos=0;x_pos<context->Width;x_pos++)
919
if (Get_pixel(context, x_pos,y_pos)!=0)
921
if (Get_pixel(context, x_pos,y_pos)!=0)
924
header2.Y_offset=y_pos;
925
for (x_pos=0;x_pos<context->Width;x_pos++)
927
for (y_pos=0;y_pos<context->Height;y_pos++)
928
if (Get_pixel(context, x_pos,y_pos)!=0)
930
if (Get_pixel(context, x_pos,y_pos)!=0)
933
header2.X_offset=x_pos;
935
memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature
936
header2.Kind=0x20; // Initialisation du type (BitMaP)
937
header2.Nb_bits=8; // Initialisation du nombre de bits
938
header2.Filler1=0; // Initialisation du filler 1 (?)
939
header2.Width=context->Width-header2.X_offset; // Initialisation de la largeur
940
header2.Height=context->Height-header2.Y_offset; // Initialisation de la hauteur
941
for (x_pos=0;x_pos<16;x_pos++) // Initialisation du filler 2 (?)
942
header2.Filler2[x_pos]=0;
944
if (Write_bytes(file,header2.Signature,sizeof(header2.Signature))
945
&& Write_byte(file,header2.Kind)
946
&& Write_byte(file,header2.Nb_bits)
947
&& Write_word_le(file,header2.Filler1)
948
&& Write_word_le(file,header2.Width)
949
&& Write_word_le(file,header2.Height)
950
&& Write_word_le(file,header2.X_offset)
951
&& Write_word_le(file,header2.Y_offset)
952
&& Write_bytes(file,header2.Filler2,sizeof(header2.Filler2))
955
// Sauvegarde de l'image
957
for (y_pos=0;((y_pos<header2.Height) && (!File_error));y_pos++)
958
for (x_pos=0;((x_pos<header2.Width) && (!File_error));x_pos++)
959
Write_one_byte(file,Get_pixel(context, x_pos+header2.X_offset,y_pos+header2.Y_offset));
975
//////////////////////////////////// KCF ////////////////////////////////////
990
// -- Tester si un fichier est au format KCF --------------------------------
992
void Test_KCF(T_IO_Context * context)
994
char filename[MAX_PATH_CHARACTERS];
997
T_CEL_Header2 header2;
1002
Get_full_filename(filename, context->File_name, context->File_directory);
1003
if ((file=fopen(filename, "rb")))
1005
if (File_length_file(file)==sizeof(T_KCF_Header))
1007
Read_bytes(file,&buffer,sizeof(T_KCF_Header));
1008
// On v�rifie une propri�t� de la structure de palette:
1009
for (pal_index=0;pal_index<10;pal_index++)
1010
for (color_index=0;color_index<16;color_index++)
1011
if ((buffer.Palette[pal_index].color[color_index].Byte2>>4)!=0)
1016
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature))
1017
&& Read_byte(file,&(header2.Kind))
1018
&& Read_byte(file,&(header2.Nb_bits))
1019
&& Read_word_le(file,&(header2.Filler1))
1020
&& Read_word_le(file,&(header2.Width))
1021
&& Read_word_le(file,&(header2.Height))
1022
&& Read_word_le(file,&(header2.X_offset))
1023
&& Read_word_le(file,&(header2.Y_offset))
1024
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2))
1027
if (memcmp(header2.Signature,"KiSS",4)==0)
1029
if (header2.Kind!=0x10)
1045
// -- Lire un fichier au format KCF -----------------------------------------
1047
void Load_KCF(T_IO_Context * context)
1049
char filename[MAX_PATH_CHARACTERS];
1051
T_KCF_Header buffer;
1052
T_CEL_Header2 header2;
1061
Get_full_filename(filename, context->File_name, context->File_directory);
1062
if ((file=fopen(filename, "rb")))
1064
file_size=File_length_file(file);
1065
if (file_size==sizeof(T_KCF_Header))
1067
// Fichier KCF � l'ancien format
1069
if (Read_bytes(file,&buffer,sizeof(T_KCF_Header)))
1071
// Pre_load(context, ?); // Pas possible... pas d'image...
1073
if (Config.Clear_palette)
1074
memset(context->Palette,0,sizeof(T_Palette));
1076
// Chargement de la palette
1077
for (pal_index=0;pal_index<10;pal_index++)
1078
for (color_index=0;color_index<16;color_index++)
1080
index=16+(pal_index*16)+color_index;
1081
context->Palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4);
1082
context->Palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4);
1083
context->Palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4);
1086
for (index=0;index<16;index++)
1088
context->Palette[index].R=context->Palette[index+16].R;
1089
context->Palette[index].G=context->Palette[index+16].G;
1090
context->Palette[index].B=context->Palette[index+16].B;
1093
Palette_loaded(context);
1100
// Fichier KCF au nouveau format
1102
if (Read_bytes(file,header2.Signature,sizeof(header2.Signature))
1103
&& Read_byte(file,&(header2.Kind))
1104
&& Read_byte(file,&(header2.Nb_bits))
1105
&& Read_word_le(file,&(header2.Filler1))
1106
&& Read_word_le(file,&(header2.Width))
1107
&& Read_word_le(file,&(header2.Height))
1108
&& Read_word_le(file,&(header2.X_offset))
1109
&& Read_word_le(file,&(header2.Y_offset))
1110
&& Read_bytes(file,header2.Filler2,sizeof(header2.Filler2))
1113
// Pre_load(context, ?); // Pas possible... pas d'image...
1115
index=(header2.Nb_bits==12)?16:0;
1116
for (pal_index=0;pal_index<header2.Height;pal_index++)
1118
// Pour chaque palette
1120
for (color_index=0;color_index<header2.Width;color_index++)
1122
// Pour chaque couleur
1124
switch(header2.Nb_bits)
1126
case 12: // RRRR BBBB | 0000 VVVV
1127
Read_bytes(file,bytes,2);
1128
context->Palette[index].R=(bytes[0] >> 4) << 4;
1129
context->Palette[index].B=(bytes[0] & 15) << 4;
1130
context->Palette[index].G=(bytes[1] & 15) << 4;
1133
case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB
1134
Read_bytes(file,bytes,3);
1135
context->Palette[index].R=bytes[0];
1136
context->Palette[index].G=bytes[1];
1137
context->Palette[index].B=bytes[2];
1144
if (header2.Nb_bits==12)
1145
for (index=0;index<16;index++)
1147
context->Palette[index].R=context->Palette[index+16].R;
1148
context->Palette[index].G=context->Palette[index+16].G;
1149
context->Palette[index].B=context->Palette[index+16].B;
1152
Palette_loaded(context);
1164
// -- Ecrire un fichier au format KCF ---------------------------------------
1166
void Save_KCF(T_IO_Context * context)
1168
char filename[MAX_PATH_CHARACTERS];
1170
T_KCF_Header buffer;
1171
T_CEL_Header2 header2;
1176
dword Utilisation[256]; // Table d'utilisation de couleurs
1178
// On commence par compter l'utilisation de chaque couleurs
1179
Count_used_colors(Utilisation);
1182
Get_full_filename(filename, context->File_name, context->File_directory);
1183
if ((file=fopen(filename,"wb")))
1185
// Sauvegarde de la palette
1187
// On regarde si des couleurs >16 sont utilis�es dans l'image
1188
for (index=16;((index<256) && (!Utilisation[index]));index++);
1192
// Cas d'une image 16 couleurs (�criture � l'ancien format)
1194
for (pal_index=0;pal_index<10;pal_index++)
1195
for (color_index=0;color_index<16;color_index++)
1197
index=16+(pal_index*16)+color_index;
1198
buffer.Palette[pal_index].color[color_index].Byte1=((context->Palette[index].R>>4)<<4) | (context->Palette[index].B>>4);
1199
buffer.Palette[pal_index].color[color_index].Byte2=context->Palette[index].G>>4;
1202
if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header)))
1207
// Cas d'une image 256 couleurs (�criture au nouveau format)
1209
memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature
1210
header2.Kind=0x10; // Initialisation du type (PALette)
1211
header2.Nb_bits=24; // Initialisation du nombre de bits
1212
header2.Filler1=0; // Initialisation du filler 1 (?)
1213
header2.Width=256; // Initialisation du nombre de couleurs
1214
header2.Height=1; // Initialisation du nombre de palettes
1215
header2.X_offset=0; // Initialisation du d�calage X
1216
header2.Y_offset=0; // Initialisation du d�calage Y
1217
for (index=0;index<16;index++) // Initialisation du filler 2 (?)
1218
header2.Filler2[index]=0;
1220
if (!Write_bytes(file,header2.Signature,sizeof(header2.Signature))
1221
|| !Write_byte(file,header2.Kind)
1222
|| !Write_byte(file,header2.Nb_bits)
1223
|| !Write_word_le(file,header2.Filler1)
1224
|| !Write_word_le(file,header2.Width)
1225
|| !Write_word_le(file,header2.Height)
1226
|| !Write_word_le(file,header2.X_offset)
1227
|| !Write_word_le(file,header2.Y_offset)
1228
|| !Write_bytes(file,header2.Filler2,sizeof(header2.Filler2))
1232
for (index=0;(index<256) && (!File_error);index++)
1234
bytes[0]=context->Palette[index].R;
1235
bytes[1]=context->Palette[index].G;
1236
bytes[2]=context->Palette[index].B;
1237
if (! Write_bytes(file,bytes,3))
1252
//////////////////////////////////// PI1 ////////////////////////////////////
1254
//// DECODAGE d'une partie d'IMAGE ////
1256
void PI1_8b_to_16p(byte * src,byte * dest)
1258
int i; // index du pixel � calculer
1259
word byte_mask; // Masque de decodage
1260
word w0,w1,w2,w3; // Les 4 words bien ordonn�s de la source
1263
w0=(((word)src[0])<<8) | src[1];
1264
w1=(((word)src[2])<<8) | src[3];
1265
w2=(((word)src[4])<<8) | src[5];
1266
w3=(((word)src[6])<<8) | src[7];
1269
// Pour d�coder le pixel n�i, il faut traiter les 4 words sur leur bit
1270
// correspondant � celui du masque
1272
dest[i]=((w0 & byte_mask)?0x01:0x00) |
1273
((w1 & byte_mask)?0x02:0x00) |
1274
((w2 & byte_mask)?0x04:0x00) |
1275
((w3 & byte_mask)?0x08:0x00);
1280
//// CODAGE d'une partie d'IMAGE ////
1282
void PI1_16p_to_8b(byte * src,byte * dest)
1284
int i; // index du pixel � calculer
1285
word byte_mask; // Masque de codage
1286
word w0,w1,w2,w3; // Les 4 words bien ordonn�s de la destination
1292
// Pour coder le pixel n�i, il faut modifier les 4 words sur leur bit
1293
// correspondant � celui du masque
1295
w0|=(src[i] & 0x01)?byte_mask:0x00;
1296
w1|=(src[i] & 0x02)?byte_mask:0x00;
1297
w2|=(src[i] & 0x04)?byte_mask:0x00;
1298
w3|=(src[i] & 0x08)?byte_mask:0x00;
1302
dest[1]=w0 & 0x00FF;
1304
dest[3]=w1 & 0x00FF;
1306
dest[5]=w2 & 0x00FF;
1308
dest[7]=w3 & 0x00FF;
1311
//// DECODAGE de la PALETTE ////
1313
void PI1_decode_palette(byte * src,byte * palette)
1315
int i; // Num�ro de la couleur trait�e
1316
int ip; // index dans la palette
1317
word w; // Word contenant le code
1319
// Sch�ma d'un word =
1322
// VVVV RRRR | 0000 BBBB
1328
w=((word)src[(i*2)+1]<<8) | src[(i*2)+0];
1330
// Traitement des couleurs rouge, verte et bleue:
1331
palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4;
1332
palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
1333
palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4;
1337
//// CODAGE de la PALETTE ////
1339
void PI1_code_palette(byte * palette,byte * dest)
1341
int i; // Num�ro de la couleur trait�e
1342
int ip; // index dans la palette
1343
word w; // Word contenant le code
1345
// Sch�ma d'un word =
1348
// VVVV RRRR | 0000 BBBB
1354
// Traitement des couleurs rouge, verte et bleue:
1355
w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++;
1356
w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++;
1357
w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++;
1359
dest[(i*2)+0]=w & 0x00FF;
1360
dest[(i*2)+1]=(w>>8);
1365
// -- Tester si un fichier est au format PI1 --------------------------------
1366
void Test_PI1(T_IO_Context * context)
1368
FILE * file; // Fichier du fichier
1369
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1370
int size; // Taille du fichier
1371
word resolution; // R�solution de l'image
1374
Get_full_filename(filename, context->File_name, context->File_directory);
1378
// Ouverture du fichier
1379
if ((file=fopen(filename, "rb")))
1381
// V�rification de la taille
1382
size=File_length_file(file);
1383
if ((size==32034) || (size==32066))
1385
// Lecture et v�rification de la r�solution
1386
if (Read_word_le(file,&resolution))
1388
if (resolution==0x0000)
1392
// Fermeture du fichier
1398
// -- Lire un fichier au format PI1 -----------------------------------------
1399
void Load_PI1(T_IO_Context * context)
1401
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1408
Get_full_filename(filename, context->File_name, context->File_directory);
1411
if ((file=fopen(filename, "rb")))
1413
// allocation d'un buffer m�moire
1414
buffer=(byte *)malloc(32034);
1417
// Lecture du fichier dans le buffer
1418
if (Read_bytes(file,buffer,32034))
1420
// Initialisation de la preview
1421
Pre_load(context, 320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE,0);
1424
// Initialisation de la palette
1425
if (Config.Clear_palette)
1426
memset(context->Palette,0,sizeof(T_Palette));
1427
PI1_decode_palette(buffer+2,(byte *)context->Palette);
1428
Palette_loaded(context);
1431
context->Height=200;
1433
// Chargement/d�compression de l'image
1435
for (y_pos=0;y_pos<200;y_pos++)
1437
for (x_pos=0;x_pos<(320>>4);x_pos++)
1439
PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
1442
for (x_pos=0;x_pos<320;x_pos++)
1443
Set_pixel(context, x_pos,y_pos,pixels[x_pos]);
1461
// -- Sauver un fichier au format PI1 ---------------------------------------
1462
void Save_PI1(T_IO_Context * context)
1464
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1471
Get_full_filename(filename, context->File_name, context->File_directory);
1474
// Ouverture du fichier
1475
if ((file=fopen(filename,"wb")))
1477
// allocation d'un buffer m�moire
1478
buffer=(byte *)malloc(32066);
1479
// Codage de la r�solution
1482
// Codage de la palette
1483
PI1_code_palette((byte *)context->Palette,buffer+2);
1484
// Codage de l'image
1486
for (y_pos=0;y_pos<200;y_pos++)
1488
// Codage de la ligne
1489
memset(pixels,0,320);
1490
if (y_pos<context->Height)
1492
for (x_pos=0;(x_pos<320) && (x_pos<context->Width);x_pos++)
1493
pixels[x_pos]=Get_pixel(context, x_pos,y_pos);
1496
for (x_pos=0;x_pos<(320>>4);x_pos++)
1498
PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
1503
memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy
1505
if (Write_bytes(file,buffer,32066))
1509
else // Error d'�criture (disque plein ou prot�g�)
1515
// Lib�ration du buffer m�moire
1528
//////////////////////////////////// PC1 ////////////////////////////////////
1530
//// DECOMPRESSION d'un buffer selon la m�thode PACKBITS ////
1532
void PC1_uncompress_packbits(byte * src,byte * dest)
1534
int is,id; // Les indices de parcour des buffers
1535
int n; // Octet de contr�le
1537
for (is=id=0;id<32000;)
1543
// Recopier src[is] -n+1 fois
1545
for (;(n>0) && (id<32000);n--)
1551
// Recopier n+1 octets litt�ralement
1553
for (;(n>0) && (id<32000);n--)
1554
dest[id++]=src[is++];
1557
// Contr�le des erreurs
1563
//// COMPRESSION d'un buffer selon la m�thode PACKBITS ////
1565
void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size)
1567
int is; // index dans la source
1568
int id; // index dans la destination
1569
int ir; // index de la r�p�tition
1570
int n; // Taille des s�quences
1571
int repet; // "Il y a r�p�tition"
1573
for (is=id=0;is<source_size;)
1575
// On recherche le 1er endroit o� il y a r�p�tition d'au moins 3 valeurs
1579
for (ir=is;ir<source_size-2;ir++)
1581
if ((src[ir]==src[ir+1]) && (src[ir+1]==src[ir+2]))
1590
// On code la partie sans r�p�titions
1596
dest[id++]=src[is++];
1599
// On code la partie sans r�p�titions
1602
// On compte la quantit� de fois qu'il faut r�p�ter la valeur
1603
for (ir+=3;ir<source_size;ir++)
1605
if (src[ir]!=src[is])
1617
// On renseigne la taille du buffer compress�
1621
//// DECODAGE d'une partie d'IMAGE ////
1623
// Transformation de 4 plans de bits en 1 ligne de pixels
1625
void PC1_4bp_to_1line(byte * src0,byte * src1,byte * src2,byte * src3,byte * dest)
1627
int i,j; // Compteurs
1628
int ip; // index du pixel � calculer
1629
byte byte_mask; // Masque de decodage
1630
byte b0,b1,b2,b3; // Les 4 octets des plans bits sources
1633
// Pour chacun des 40 octets des plans de bits
1640
// Pour chacun des 8 bits des octets
1644
dest[ip++]=((b0 & byte_mask)?0x01:0x00) |
1645
((b1 & byte_mask)?0x02:0x00) |
1646
((b2 & byte_mask)?0x04:0x00) |
1647
((b3 & byte_mask)?0x08:0x00);
1653
//// CODAGE d'une partie d'IMAGE ////
1655
// Transformation d'1 ligne de pixels en 4 plans de bits
1657
void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3)
1659
int i,j; // Compteurs
1660
int ip; // index du pixel � calculer
1661
byte byte_mask; // Masque de decodage
1662
byte b0,b1,b2,b3; // Les 4 octets des plans bits sources
1665
// Pour chacun des 40 octets des plans de bits
1668
// Pour chacun des 8 bits des octets
1673
b0|=(src[ip] & 0x01)?byte_mask:0x00;
1674
b1|=(src[ip] & 0x02)?byte_mask:0x00;
1675
b2|=(src[ip] & 0x04)?byte_mask:0x00;
1676
b3|=(src[ip] & 0x08)?byte_mask:0x00;
1688
// -- Tester si un fichier est au format PC1 --------------------------------
1689
void Test_PC1(T_IO_Context * context)
1691
FILE *file; // Fichier du fichier
1692
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1693
int size; // Taille du fichier
1694
word resolution; // R�solution de l'image
1697
Get_full_filename(filename, context->File_name, context->File_directory);
1701
// Ouverture du fichier
1702
if ((file=fopen(filename, "rb")))
1704
// V�rification de la taille
1705
size=File_length_file(file);
1708
// Lecture et v�rification de la r�solution
1709
if (Read_word_le(file,&resolution))
1711
if (resolution==0x0080)
1715
// Fermeture du fichier
1721
// -- Lire un fichier au format PC1 -----------------------------------------
1722
void Load_PC1(T_IO_Context * context)
1724
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1729
byte * bufferdecomp;
1733
Get_full_filename(filename, context->File_name, context->File_directory);
1736
if ((file=fopen(filename, "rb")))
1738
size=File_length_file(file);
1739
// allocation des buffers m�moire
1740
buffercomp=(byte *)malloc(size);
1741
bufferdecomp=(byte *)malloc(32000);
1742
if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) )
1744
// Lecture du fichier dans le buffer
1745
if (Read_bytes(file,buffercomp,size))
1747
// Initialisation de la preview
1748
Pre_load(context, 320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE,0);
1751
// Initialisation de la palette
1752
if (Config.Clear_palette)
1753
memset(context->Palette,0,sizeof(T_Palette));
1754
PI1_decode_palette(buffercomp+2,(byte *)context->Palette);
1755
Palette_loaded(context);
1758
context->Height=200;
1760
// D�compression du buffer
1761
PC1_uncompress_packbits(buffercomp+34,bufferdecomp);
1763
// D�codage de l'image
1765
for (y_pos=0;y_pos<200;y_pos++)
1767
// D�codage de la scanline
1768
PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels);
1770
// Chargement de la ligne
1771
for (x_pos=0;x_pos<320;x_pos++)
1772
Set_pixel(context, x_pos,y_pos,pixels[x_pos]);
1780
buffercomp = bufferdecomp = NULL;
1787
buffercomp = bufferdecomp = NULL;
1796
// -- Sauver un fichier au format PC1 ---------------------------------------
1797
void Save_PC1(T_IO_Context * context)
1799
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1804
byte * bufferdecomp;
1808
Get_full_filename(filename, context->File_name, context->File_directory);
1811
// Ouverture du fichier
1812
if ((file=fopen(filename,"wb")))
1814
// Allocation des buffers m�moire
1815
bufferdecomp=(byte *)malloc(32000);
1816
buffercomp =(byte *)malloc(64066);
1817
// Codage de la r�solution
1820
// Codage de la palette
1821
PI1_code_palette((byte *)context->Palette,buffercomp+2);
1822
// Codage de l'image
1824
for (y_pos=0;y_pos<200;y_pos++)
1826
// Codage de la ligne
1827
memset(pixels,0,320);
1828
if (y_pos<context->Height)
1830
for (x_pos=0;(x_pos<320) && (x_pos<context->Width);x_pos++)
1831
pixels[x_pos]=Get_pixel(context, x_pos,y_pos);
1834
// Encodage de la scanline
1835
PC1_1line_to_4bp(pixels,ptr,ptr+40,ptr+80,ptr+120);
1839
// Compression du buffer
1840
PC1_compress_packbits(bufferdecomp,buffercomp+34,32000,&size);
1842
for (x_pos=0;x_pos<16;x_pos++)
1843
buffercomp[size++]=0;
1845
if (Write_bytes(file,buffercomp,size))
1849
else // Error d'�criture (disque plein ou prot�g�)
1855
// Lib�ration des buffers m�moire
1858
buffercomp = bufferdecomp = NULL;
1869
//////////////////////////////////// NEO ////////////////////////////////////
1871
void Test_NEO(T_IO_Context * context)
1873
FILE *file; // Fichier du fichier
1874
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1875
int size; // Taille du fichier
1876
word resolution; // R�solution de l'image
1879
Get_full_filename(filename, context->File_name, context->File_directory);
1883
// Ouverture du fichier
1884
if ((file=fopen(filename, "rb")))
1886
// V�rification de la taille
1887
size=File_length_file(file);
1890
// Flag word : toujours 0
1891
if (Read_word_le(file,&resolution))
1893
if (resolution == 0)
1897
// Lecture et v�rification de la r�solution
1898
if (Read_word_le(file,&resolution))
1900
if (resolution==0 || resolution==1 || resolution==2)
1904
// Fermeture du fichier
1910
void Load_NEO(T_IO_Context * context)
1912
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1919
Get_full_filename(filename, context->File_name, context->File_directory);
1922
if ((file=fopen(filename, "rb")))
1924
// allocation d'un buffer m�moire
1925
buffer=(byte *)malloc(32128);
1928
// Lecture du fichier dans le buffer
1929
if (Read_bytes(file,buffer,32128))
1931
// Initialisation de la preview
1932
Pre_load(context, 320,200,File_length_file(file),FORMAT_NEO,PIXEL_SIMPLE,0);
1935
// Initialisation de la palette
1936
if (Config.Clear_palette)
1937
memset(context->Palette,0,sizeof(T_Palette));
1938
// on saute la r�solution et le flag, chacun 2 bits
1939
PI1_decode_palette(buffer+4,(byte *)context->Palette);
1940
Palette_loaded(context);
1943
context->Height=200;
1945
// Chargement/d�compression de l'image
1947
for (y_pos=0;y_pos<200;y_pos++)
1949
for (x_pos=0;x_pos<(320>>4);x_pos++)
1951
PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
1954
for (x_pos=0;x_pos<320;x_pos++)
1955
Set_pixel(context, x_pos,y_pos,pixels[x_pos]);
1972
void Save_NEO(T_IO_Context * context)
1974
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
1981
Get_full_filename(filename, context->File_name, context->File_directory);
1984
// Ouverture du fichier
1985
if ((file=fopen(filename,"wb")))
1987
// allocation d'un buffer m�moire
1988
buffer=(byte *)malloc(32128);
1989
// Codage de la r�solution
1994
// Codage de la palette
1995
PI1_code_palette((byte *)context->Palette,buffer+4);
1996
// Codage de l'image
1998
for (y_pos=0;y_pos<200;y_pos++)
2000
// Codage de la ligne
2001
memset(pixels,0,320);
2002
if (y_pos<context->Height)
2004
for (x_pos=0;(x_pos<320) && (x_pos<context->Width);x_pos++)
2005
pixels[x_pos]=Get_pixel(context, x_pos,y_pos);
2008
for (x_pos=0;x_pos<(320>>4);x_pos++)
2010
PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
2015
if (Write_bytes(file,buffer,32128))
2019
else // Error d'�criture (disque plein ou prot�g�)
2025
// Lib�ration du buffer m�moire
2037
//////////////////////////////////// C64 ////////////////////////////////////
2038
void Test_C64(T_IO_Context * context)
2041
char filename[MAX_PATH_CHARACTERS];
2044
Get_full_filename(filename, context->File_name, context->File_directory);
2046
file = fopen(filename,"rb");
2050
file_size = File_length_file(file);
2053
case 1000: // screen or color
2054
case 1002: // (screen or color) + loadaddr
2055
case 8000: // raw bitmap
2056
case 8002: // raw bitmap with loadaddr
2057
case 9000: // bitmap + screen
2058
case 9002: // bitmap + screen + loadaddr
2059
case 10001: // multicolor
2060
case 10003: // multicolor + loadaddr
2063
default: // then we don't know for now.
2074
void Load_C64_hires(T_IO_Context *context, byte *bitmap, byte *colors)
2076
int cx,cy,x,y,c[4],pixel,color;
2078
for(cy=0; cy<25; cy++)
2080
for(cx=0; cx<40; cx++)
2082
c[0]=colors[cy*40+cx]&15;
2083
c[1]=colors[cy*40+cx]>>4;
2086
pixel=bitmap[cy*320+cx*8+y];
2089
color=c[pixel&(1<<(7-x))?1:0];
2090
Set_pixel(context, cx*8+x,cy*8+y,color);
2097
void Load_C64_multi(T_IO_Context *context, byte *bitmap, byte *colors, byte *nybble, byte background)
2099
int cx,cy,x,y,c[4],pixel,color;
2101
for(cy=0; cy<25; cy++)
2103
for(cx=0; cx<40; cx++)
2105
c[1]=colors[cy*40+cx]>>4;
2106
c[2]=colors[cy*40+cx]&15;
2107
c[3]=nybble[cy*40+cx]&15;
2111
pixel=bitmap[cy*320+cx*8+y];
2116
Set_pixel(context, cx*4+(3-x),cy*8+y,color);
2123
void Load_C64(T_IO_Context * context)
2126
char filename[MAX_PATH_CHARACTERS];
2129
byte background,hasLoadAddr=0;
2131
enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color};
2132
const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"};
2134
// Palette from http://www.pepto.de/projects/colorvic/
2153
byte bitmap[8000],colors[1000],nybble[1000];
2154
word width=320, height=200;
2156
Get_full_filename(filename, context->File_name, context->File_directory);
2157
file = fopen(filename,"rb");
2162
file_size = File_length_file(file);
2166
case 1000: // screen or color
2168
loadFormat=F_screen;
2171
case 1002: // (screen or color) + loadaddr
2173
loadFormat=F_screen;
2176
case 8000: // raw bitmap
2178
loadFormat=F_bitmap;
2181
case 8002: // raw bitmap with loadaddr
2183
loadFormat=F_bitmap;
2186
case 9000: // bitmap + screen
2191
case 9002: // bitmap + screen + loadaddr
2196
case 10001: // multicolor
2201
case 10003: // multicolor + loadaddr
2206
default: // then we don't know what it is.
2211
memcpy(context->Palette,pal,48); // this set the software palette for grafx2
2212
Palette_loaded(context); // Always call it if you change the palette
2220
Read_byte(file,&background);
2221
Read_byte(file,&background);
2222
sprintf(filename,"load at $%02x00",background);
2226
sprintf(filename,"no addr");
2231
context->Ratio = PIXEL_WIDE;
2233
sprintf(context->Comment,"C64 %s, %s",
2234
c64_format_names[loadFormat],filename);
2235
Pre_load(context, width, height, file_size, FORMAT_C64, context->Ratio,0); // Do this as soon as you can
2237
context->Width = width ;
2238
context->Height = height;
2240
Read_bytes(file,bitmap,8000);
2243
Read_bytes(file,colors,1000);
2254
Read_bytes(file,nybble,1000);
2255
Read_byte(file,&background);
2256
Load_C64_multi(context,bitmap,colors,nybble,background);
2260
Load_C64_hires(context,bitmap,colors);
2270
int Save_C64_window(byte *saveWhat, byte *loadAddr)
2274
T_Dropdown_button *what, *addr;
2275
char * what_label[] = {
2281
char * address_label[] = {
2292
Open_window(200,120,"c64 settings");
2293
Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN);
2294
Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE);
2296
Print_in_window(13,18,"Data:",MC_Dark,MC_Light);
2297
what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE,0);
2298
Window_dropdown_clear_items(what);
2299
for (i=0; i<sizeof(what_label)/sizeof(char *); i++)
2300
Window_dropdown_add_item(what,i,what_label[i]);
2302
Print_in_window(113,18,"Address:",MC_Dark,MC_Light);
2303
addr=Window_set_dropdown_button(110,28,70,15,70,address_label[*loadAddr/32],1, 0, 1, LEFT_SIDE,0);
2304
Window_dropdown_clear_items(addr);
2305
for (i=0; i<sizeof(address_label)/sizeof(char *); i++)
2306
Window_dropdown_add_item(addr,i,address_label[i]);
2308
Update_window_area(0,0,Window_width,Window_height);
2313
button = Window_clicked_button();
2316
case 3: // Save what
2317
*saveWhat=Window_attribute2;
2318
//printf("what=%d\n",Window_attribute2);
2321
case 4: // Load addr
2322
*loadAddr=Window_attribute2*32;
2323
//printf("addr=$%02x00 (%d)\n",loadAddr,Window_attribute2);
2328
}while(button!=1 && button!=2);
2335
int Save_C64_hires(T_IO_Context *context, char *filename, byte saveWhat, byte loadAddr)
2337
int cx,cy,x,y,c1,c2=0,i,pixel,bits,pos=0;
2340
byte colors[1000],bitmap[8000];
2343
for(x=0;x<1000;x++)colors[x]=1; // init colormem to black/white
2345
for(cy=0; cy<25; cy++) // Character line, 25 lines
2347
for(cx=0; cx<40; cx++) // Character column, 40 columns
2352
numcolors=Count_used_colors_area(cusage,cx*8,cy*8,8,8);
2355
Warning_message("More than 2 colors in 8x8 pixels");
2356
// TODO here we should hilite the offending block
2357
printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors);
2377
colors[cx+cy*40]=(c2<<4)|c1;
2384
pixel=Get_pixel(context, x+cx*8,y+cy*8);
2387
Warning_message("Color above 15 used");
2388
// TODO hilite offending block here too?
2389
// or make it smarter with color allocation?
2390
// However, the palette is fixed to the 16 first colors
2394
if (pixel==c2) bits|=1;
2397
//Write_byte(file,bits&255);
2402
file = fopen(filename,"wb");
2406
Warning_message("File open failed");
2414
Write_byte(file,loadAddr);
2416
if (saveWhat==0 || saveWhat==1)
2417
Write_bytes(file,bitmap,8000);
2418
if (saveWhat==0 || saveWhat==2)
2419
Write_bytes(file,colors,1000);
2425
int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte loadAddr)
2428
BITS COLOR INFORMATION COMES FROM
2429
00 Background color #0 (screen color)
2430
01 Upper 4 bits of screen memory
2431
10 Lower 4 bits of screen memory
2432
11 Color nybble (nybble = 1/2 byte = 4 bits)
2435
int cx,cy,x,y,c[4]={0,0,0,0},color,lut[16],bits,pixel,pos=0;
2436
byte bitmap[8000],screen[1000],nybble[1000];
2437
word numcolors,count;
2439
byte i,background=0;
2442
numcolors=Count_used_colors(cusage);
2447
//printf("color %d, pixels %d\n",x,cusage[x]);
2455
for(cy=0; cy<25; cy++)
2457
//printf("\ny:%2d ",cy);
2458
for(cx=0; cx<40; cx++)
2460
numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8);
2463
Warning_message("More than 4 colors in 4x8");
2464
// TODO hilite offending block
2486
// add to screen and nybble
2487
screen[cx+cy*40]=c[1]<<4|c[2];
2488
nybble[cx+cy*40]=c[3];
2489
//printf("%x%x%x ",c[1],c[2],c[3]);
2495
pixel=Get_pixel(context, cx*4+x,cy*8+y);
2498
Warning_message("Color above 15 used");
2499
// TODO hilite as in hires, you should stay to
2500
// the fixed 16 color palette
2507
//Write_byte(file,bits&255);
2513
file = fopen(filename,"wb");
2517
Warning_message("File open failed");
2525
Write_byte(file,loadAddr);
2528
if (saveWhat==0 || saveWhat==1)
2529
Write_bytes(file,bitmap,8000);
2531
if (saveWhat==0 || saveWhat==2)
2532
Write_bytes(file,screen,1000);
2534
if (saveWhat==0 || saveWhat==3)
2535
Write_bytes(file,nybble,1000);
2538
Write_byte(file,background);
2541
//printf("\nbg:%d\n",background);
2545
void Save_C64(T_IO_Context * context)
2547
char filename[MAX_PATH_CHARACTERS];
2548
static byte saveWhat=0, loadAddr=0;
2549
dword numcolors,cusage[256];
2550
numcolors=Count_used_colors(cusage);
2552
Get_full_filename(filename, context->File_name, context->File_directory);
2556
Warning_message("Error: Max 16 colors");
2560
if (((context->Width!=320) && (context->Width!=160)) || context->Height!=200)
2562
Warning_message("must be 320x200 or 160x200");
2567
if(!Save_C64_window(&saveWhat,&loadAddr))
2572
//printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr);
2574
if (context->Width==320)
2575
File_error = Save_C64_hires(context,filename,saveWhat,loadAddr);
2577
File_error = Save_C64_multi(context,filename,saveWhat,loadAddr);
2581
// SCR (Amstrad CPC)
2583
void Test_SCR(__attribute__((unused)) T_IO_Context * context)
2585
// Mmh... not sure what we could test. Any idea ?
2586
// The palette file can be tested, if it exists and have the right size it's
2587
// ok. But if it's not there the pixel data may still be valid. And we can't
2588
// use the filesize as this depends on the screen format.
2590
// An AMSDOS header would be a good indication but in some cases it may not
2594
void Load_SCR(__attribute__((unused)) T_IO_Context * context)
2596
// The Amstrad CPC screen memory is mapped in a weird mode, somewhere
2597
// between bitmap and textmode. Basically the only way to decode this is to
2598
// emulate the video chip and read the bytes as needed...
2599
// Moreover, the hardware allows the screen to have any size from 8x1 to
2600
// 800x273 pixels, and there is no indication of that in the file besides
2601
// its size. It can also use any of the 3 screen modes. Fortunately this
2602
// last bit of information is stored in the palette file.
2603
// Oh, and BTW, the picture can be offset, and it's even usual to do it,
2604
// because letting 128 pixels unused at the beginning of the file make it a
2605
// lot easier to handle screens using more than 16K of VRam.
2606
// The pixel encoding change with the video mode so we have to know that
2607
// before attempting to load anything...
2608
// As if this wasn't enough, Advanced OCP Art Studio, the reference tool on
2609
// Amstrad, can use RLE packing when saving files, meaning we also have to
2612
// All this mess enforces us to load (and unpack if needed) the file to a
2613
// temporary 32k buffer before actually decoding it.
2615
// 1) Seek for a palette
2616
// 2) If palette found get screenmode from there, else ask user
2617
// 3) ask user for screen size (or register values)
2618
// 4) Load color data from palette (if found)
2621
// 7) Run around the screen to untangle the pixeldata
2622
// 8) Close the file
2625
void Save_SCR(T_IO_Context * context)
2627
// TODO : Add possibility to set R9, R12, R13 values
2628
// TODO : Add OCP packing support
2629
// TODO : Add possibility to include AMSDOS header, with proper loading
2630
// address guessed from r12/r13 values.
2632
unsigned char* output;
2633
unsigned long outsize;
2637
char filename[MAX_PATH_CHARACTERS];
2639
Get_full_filename(filename, context->File_name, context->File_directory);
2657
output = raw2crtc(context->Width,context->Height,cpc_mode,7,&outsize,&r1,0,0);
2659
file = fopen(filename,"wb");
2660
Write_bytes(file, output, outsize);