~ubuntu-branches/ubuntu/maverick/grafx2/maverick

« back to all changes in this revision

Viewing changes to src/miscfileformats.c

  • Committer: Bazaar Package Importer
  • Author(s): Gürkan Sengün
  • Date: 2010-03-22 12:07:47 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20100322120747-g0jel6vf6mjkc53s
Tags: 2.2-1
* New upstream version, fixes FTBFS with binutils-gold. (Closes: #554742)
* Bump standards version to 3.8.4.
* debian/control: Add liblua5.1-0-dev and pkg-config to build depends.
* debian/rules: Drop dh_desktop call.
* debian/copyright: Update years.
* Switch to dpkg-source format version 3.0 (quilt).
* debian/watch: Added.
* Added patch to fix spelling errors in source code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* vim:expandtab:ts=2 sw=2:
 
2
*/
 
3
/*  Grafx2 - The Ultimate 256-color bitmap paint program
 
4
 
 
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)
 
10
 
 
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
 
14
    of the License.
 
15
 
 
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.
 
20
 
 
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/>
 
23
*/
 
24
 
 
25
///@file miscfileformats.c
 
26
/// Formats that aren't fully saving, either because of palette restrictions or other things
 
27
 
 
28
#include <stdlib.h>
 
29
#include <string.h>
 
30
 
 
31
#include "engine.h"
 
32
#include "errors.h"
 
33
#include "global.h"
 
34
#include "io.h"
 
35
#include "libraw2crtc.h"
 
36
#include "limits.h"
 
37
#include "loadsave.h"
 
38
#include "misc.h"
 
39
#include "sdlscreen.h"
 
40
#include "struct.h"
 
41
#include "windows.h"
 
42
 
 
43
//////////////////////////////////// PAL ////////////////////////////////////
 
44
//
 
45
 
 
46
// -- Tester si un fichier est au format PAL --------------------------------
 
47
void Test_PAL(T_IO_Context * context)
 
48
{
 
49
  FILE *file; // Fichier du fichier
 
50
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
51
  long file_size; // Taille du fichier
 
52
 
 
53
  Get_full_filename(filename, context->File_name, context->File_directory);
 
54
 
 
55
  File_error = 1;
 
56
 
 
57
  // Ouverture du fichier
 
58
  if ((file = fopen(filename, "rb")))
 
59
  {
 
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))
 
64
      File_error = 0;
 
65
    else {
 
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)
 
69
      {
 
70
        File_error = 0;
 
71
      }
 
72
    }
 
73
    fclose(file);
 
74
  }
 
75
}
 
76
 
 
77
 
 
78
// -- Lire un fichier au format PAL -----------------------------------------
 
79
void Load_PAL(T_IO_Context * context)
 
80
{
 
81
  FILE *file;              // Fichier du fichier
 
82
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
83
  //long  file_size;   // Taille du fichier
 
84
 
 
85
 
 
86
  Get_full_filename(filename, context->File_name, context->File_directory);
 
87
  File_error=0;
 
88
 
 
89
  // Ouverture du fichier
 
90
  if ((file=fopen(filename, "rb")))
 
91
  {
 
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))
 
95
    {
 
96
      T_Palette palette_64;
 
97
      // Pre_load(context, ?); // Pas possible... pas d'image...
 
98
 
 
99
      // Lecture du fichier dans context->Palette
 
100
      if (Read_bytes(file, palette_64, sizeof(T_Palette)))
 
101
      {
 
102
        Palette_64_to_256(palette_64);
 
103
        memcpy(context->Palette, palette_64, sizeof(T_Palette));
 
104
        Palette_loaded(context);
 
105
      }
 
106
      else
 
107
        File_error = 2;
 
108
    } else {
 
109
      fread(filename, 1, 8, file);
 
110
      if (strncmp(filename,"JASC-PAL",8) == 0)
 
111
      {
 
112
        int i, n, r, g, b;
 
113
        fscanf(file, "%d",&n);
 
114
        if(n != 100) 
 
115
        {
 
116
          File_error = 2;
 
117
          fclose(file);
 
118
          return;
 
119
        }
 
120
        // Read color count
 
121
        fscanf(file, "%d",&n);
 
122
        for (i = 0; i < n; i++)
 
123
        {
 
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;
 
128
        }
 
129
        Palette_loaded(context);
 
130
      } else File_error = 2;
 
131
    
 
132
    }
 
133
    
 
134
    // Fermeture du fichier
 
135
    fclose(file);
 
136
  }
 
137
  else
 
138
    // Si on n'a pas r�ussi � ouvrir le fichier, alors il y a eu une erreur
 
139
    File_error=1;
 
140
}
 
141
 
 
142
 
 
143
// -- Sauver un fichier au format PAL ---------------------------------------
 
144
void Save_PAL(T_IO_Context * context)
 
145
{
 
146
  FILE *file;
 
147
  char filename[MAX_PATH_CHARACTERS]; ///< full filename
 
148
 
 
149
  Get_full_filename(filename, context->File_name, context->File_directory);
 
150
 
 
151
  File_error=0;
 
152
 
 
153
  // Open output file
 
154
  if ((file=fopen(filename,"w")))
 
155
  {
 
156
    int i;
 
157
    if (fputs("JASC-PAL\n0100\n256\n", file)==EOF)
 
158
      File_error=1;
 
159
    for (i = 0; i < 256 && File_error==0; i++)
 
160
    {
 
161
      if (fprintf(file,"%d %d %d\n",context->Palette[i].R, context->Palette[i].G, context->Palette[i].B) <= 0)
 
162
        File_error=1;
 
163
    }
 
164
    
 
165
    fclose(file);
 
166
    
 
167
    if (File_error)
 
168
      remove(filename);
 
169
  }
 
170
  else
 
171
  {
 
172
    // unable to open output file, nothing saved.
 
173
    File_error=1;
 
174
  }
 
175
}
 
176
 
 
177
 
 
178
//////////////////////////////////// PKM ////////////////////////////////////
 
179
typedef struct
 
180
{
 
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
 
192
} T_PKM_Header;
 
193
 
 
194
// -- Tester si un fichier est au format PKM --------------------------------
 
195
void Test_PKM(T_IO_Context * context)
 
196
{
 
197
  FILE *file;             // Fichier du fichier
 
198
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
199
  T_PKM_Header header;
 
200
 
 
201
 
 
202
  Get_full_filename(filename, context->File_name, context->File_directory);
 
203
  
 
204
  File_error=1;
 
205
 
 
206
  // Ouverture du fichier
 
207
  if ((file=fopen(filename, "rb")))
 
208
  {
 
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))
 
218
    {
 
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)
 
223
        File_error=0;
 
224
    }
 
225
    fclose(file);
 
226
  }
 
227
}
 
228
 
 
229
 
 
230
// -- Lire un fichier au format PKM -----------------------------------------
 
231
void Load_PKM(T_IO_Context * context)
 
232
{
 
233
  FILE *file;             // Fichier du fichier
 
234
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
235
  T_PKM_Header header;
 
236
  byte  color;
 
237
  byte  temp_byte;
 
238
  word  len;
 
239
  word  index;
 
240
  dword Compteur_de_pixels;
 
241
  dword Compteur_de_donnees_packees;
 
242
  dword image_size;
 
243
  dword Taille_pack;
 
244
  long  file_size;
 
245
 
 
246
  Get_full_filename(filename, context->File_name, context->File_directory);
 
247
 
 
248
  File_error=0;
 
249
  
 
250
  if ((file=fopen(filename, "rb")))
 
251
  {
 
252
    file_size=File_length_file(file);
 
253
 
 
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))
 
262
    {
 
263
      context->Comment[0]='\0'; // On efface le commentaire
 
264
      if (header.Jump)
 
265
      {
 
266
        index=0;
 
267
        while ( (index<header.Jump) && (!File_error) )
 
268
        {
 
269
          if (Read_byte(file,&temp_byte))
 
270
          {
 
271
            index+=2; // On rajoute le "Field-id" et "le Field-size" pas encore lu
 
272
            switch (temp_byte)
 
273
            {
 
274
              case 0 : // Commentaire
 
275
                if (Read_byte(file,&temp_byte))
 
276
                {
 
277
                  if (temp_byte>COMMENT_SIZE)
 
278
                  {
 
279
                    color=temp_byte;              // On se sert de color comme
 
280
                    temp_byte=COMMENT_SIZE;   // variable temporaire
 
281
                    color-=COMMENT_SIZE;
 
282
                  }
 
283
                  else
 
284
                    color=0;
 
285
 
 
286
                  if (Read_bytes(file,context->Comment,temp_byte))
 
287
                  {
 
288
                    index+=temp_byte;
 
289
                    context->Comment[temp_byte]='\0';
 
290
                    if (color)
 
291
                      if (fseek(file,color,SEEK_CUR))
 
292
                        File_error=2;
 
293
                  }
 
294
                  else
 
295
                    File_error=2;
 
296
                }
 
297
                else
 
298
                  File_error=2;
 
299
                break;
 
300
 
 
301
              case 1 : // Dimensions de l'�cran d'origine
 
302
                if (Read_byte(file,&temp_byte))
 
303
                {
 
304
                  if (temp_byte==4)
 
305
                  {
 
306
                    index+=4;
 
307
                    if ( ! Read_word_le(file,(word *) &Original_screen_X)
 
308
                      || !Read_word_le(file,(word *) &Original_screen_Y) )
 
309
                      File_error=2;
 
310
                  }
 
311
                  else
 
312
                    File_error=2;
 
313
                }
 
314
                else
 
315
                  File_error=2;
 
316
                break;
 
317
 
 
318
              case 2 : // color de transparence
 
319
                if (Read_byte(file,&temp_byte))
 
320
                {
 
321
                  if (temp_byte==1)
 
322
                  {
 
323
                    index++;
 
324
                    if (! Read_byte(file,&Back_color))
 
325
                      File_error=2;
 
326
                  }
 
327
                  else
 
328
                    File_error=2;
 
329
                }
 
330
                else
 
331
                  File_error=2;
 
332
                break;
 
333
 
 
334
              default:
 
335
                if (Read_byte(file,&temp_byte))
 
336
                {
 
337
                  index+=temp_byte;
 
338
                  if (fseek(file,temp_byte,SEEK_CUR))
 
339
                    File_error=2;
 
340
                }
 
341
                else
 
342
                  File_error=2;
 
343
            }
 
344
          }
 
345
          else
 
346
            File_error=2;
 
347
        }
 
348
        if ( (!File_error) && (index!=header.Jump) )
 
349
          File_error=2;
 
350
      }
 
351
 
 
352
      /*Init_lecture();*/
 
353
 
 
354
      if (!File_error)
 
355
      {
 
356
        Pre_load(context, header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE,0);
 
357
        if (File_error==0)
 
358
        {
 
359
          
 
360
          context->Width=header.Width;
 
361
          context->Height=header.Height;
 
362
          image_size=(dword)(context->Width*context->Height);
 
363
          // Palette lue en 64
 
364
          memcpy(context->Palette,header.Palette,sizeof(T_Palette));
 
365
          Palette_64_to_256(context->Palette);
 
366
          Palette_loaded(context);
 
367
 
 
368
          Compteur_de_donnees_packees=0;
 
369
          Compteur_de_pixels=0;
 
370
          Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump;
 
371
 
 
372
          // Boucle de d�compression:
 
373
          while ( (Compteur_de_pixels<image_size) && (Compteur_de_donnees_packees<Taille_pack) && (!File_error) )
 
374
          {
 
375
            if(Read_byte(file, &temp_byte)!=1) 
 
376
            {
 
377
              File_error=2;
 
378
              break;
 
379
            }
 
380
 
 
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) )
 
383
            {
 
384
              Set_pixel(context, Compteur_de_pixels % context->Width,
 
385
                                  Compteur_de_pixels / context->Width,
 
386
                                  temp_byte);
 
387
              Compteur_de_donnees_packees++;
 
388
              Compteur_de_pixels++;
 
389
            }
 
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)
 
393
                {
 
394
                  if(Read_byte(file, &color)!=1)
 
395
                {
 
396
                    File_error=2;
 
397
                    break;
 
398
                }
 
399
                if(Read_byte(file, &temp_byte)!=1)
 
400
                {
 
401
                    File_error=2;
 
402
                    break;
 
403
                }
 
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,
 
407
                                      color);
 
408
                Compteur_de_pixels+=temp_byte;
 
409
                Compteur_de_donnees_packees+=3;
 
410
              }
 
411
              else // ... nombre de pixels tenant sur un word
 
412
              {
 
413
                if(Read_byte(file, &color)!=1)
 
414
                {
 
415
                    File_error=2;
 
416
                    break;
 
417
        }
 
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,
 
422
                                      color);
 
423
                Compteur_de_pixels+=len;
 
424
                Compteur_de_donnees_packees+=4;
 
425
              }
 
426
            }
 
427
          }
 
428
        }
 
429
      }
 
430
      /*Close_lecture();*/
 
431
    }
 
432
    else // Lecture header impossible: Error ne modifiant pas l'image
 
433
      File_error=1;
 
434
 
 
435
    fclose(file);
 
436
  }
 
437
  else // Ouv. fichier impossible: Error ne modifiant pas l'image
 
438
    File_error=1;
 
439
}
 
440
 
 
441
 
 
442
// -- Sauver un fichier au format PKM ---------------------------------------
 
443
 
 
444
  // Trouver quels sont les octets de reconnaissance
 
445
  void Find_recog(byte * recog1, byte * recog2)
 
446
  {
 
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
 
450
    word  index;
 
451
 
 
452
 
 
453
    // On commence par compter l'utilisation de chaque couleurs
 
454
    Count_used_colors(Find_recon);
 
455
 
 
456
    // Ensuite recog1 devient celle la moins utilis�e de celles-ci
 
457
    *recog1=0;
 
458
    best=1;
 
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)
 
462
      {
 
463
        best=index;
 
464
        NBest=Find_recon[index];
 
465
      }
 
466
    *recog1=best;
 
467
 
 
468
    // Enfin recog2 devient la 2�me moins utilis�e
 
469
    *recog2=0;
 
470
    best=0;
 
471
    NBest=INT_MAX;
 
472
    for (index=0;index<=255;index++)
 
473
      if ( (Find_recon[index]<NBest) && (index!=*recog1) )
 
474
      {
 
475
        best=index;
 
476
        NBest=Find_recon[index];
 
477
      }
 
478
    *recog2=best;
 
479
  }
 
480
 
 
481
 
 
482
void Save_PKM(T_IO_Context * context)
 
483
{
 
484
  char filename[MAX_PATH_CHARACTERS];
 
485
  FILE *file;
 
486
  T_PKM_Header header;
 
487
  dword Compteur_de_pixels;
 
488
  dword image_size;
 
489
  word  repetitions;
 
490
  byte  last_color;
 
491
  byte  pixel_value;
 
492
  byte  comment_size;
 
493
 
 
494
 
 
495
 
 
496
  // Construction du header
 
497
  memcpy(header.Ident,"PKM",3);
 
498
  header.Method=0;
 
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);
 
504
 
 
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);
 
508
  if (comment_size)
 
509
    header.Jump+=comment_size+2;
 
510
 
 
511
 
 
512
  Get_full_filename(filename, context->File_name, context->File_directory);
 
513
 
 
514
  File_error=0;
 
515
 
 
516
  // Ouverture du fichier
 
517
  if ((file=fopen(filename,"wb")))
 
518
  {
 
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))
 
528
    {
 
529
      Init_write_buffer();
 
530
 
 
531
      // Ecriture du commentaire
 
532
      // (Compteur_de_pixels est utilis� ici comme simple index de comptage)
 
533
      if (comment_size)
 
534
      {
 
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]);
 
539
      }
 
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);
 
551
 
 
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);
 
556
 
 
557
      while ( (Compteur_de_pixels<image_size) && (!File_error) )
 
558
      {
 
559
        Compteur_de_pixels++;
 
560
        repetitions=1;
 
561
        last_color=pixel_value;
 
562
        if(Compteur_de_pixels<image_size)
 
563
        {
 
564
          pixel_value=Get_pixel(context, Compteur_de_pixels % context->Width,Compteur_de_pixels / context->Width);
 
565
        }
 
566
        while ( (pixel_value==last_color)
 
567
             && (Compteur_de_pixels<image_size)
 
568
             && (repetitions<65535) )
 
569
        {
 
570
          Compteur_de_pixels++;
 
571
          repetitions++;
 
572
          if(Compteur_de_pixels>=image_size) break;
 
573
          pixel_value=Get_pixel(context, Compteur_de_pixels % context->Width,Compteur_de_pixels / context->Width);
 
574
        }
 
575
 
 
576
        if ( (last_color!=header.Recog1) && (last_color!=header.Recog2) )
 
577
        {
 
578
          if (repetitions==1)
 
579
            Write_one_byte(file,last_color);
 
580
          else
 
581
          if (repetitions==2)
 
582
          {
 
583
            Write_one_byte(file,last_color);
 
584
            Write_one_byte(file,last_color);
 
585
          }
 
586
          else
 
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);
 
592
          }
 
593
          else
 
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);
 
600
          }
 
601
        }
 
602
        else
 
603
        {
 
604
          if (repetitions<256)
 
605
          {
 
606
            Write_one_byte(file,header.Recog1);
 
607
            Write_one_byte(file,last_color);
 
608
            Write_one_byte(file,repetitions&0xFF);
 
609
          }
 
610
          else
 
611
          {
 
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);
 
616
          }
 
617
        }
 
618
      }
 
619
 
 
620
      End_write(file);
 
621
    }
 
622
    else
 
623
      File_error=1;
 
624
    fclose(file);
 
625
  }
 
626
  else
 
627
  {
 
628
    File_error=1;
 
629
    fclose(file);
 
630
  }
 
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.
 
633
  if (File_error)
 
634
    remove(filename);
 
635
}
 
636
 
 
637
 
 
638
//////////////////////////////////// CEL ////////////////////////////////////
 
639
#pragma pack(1)
 
640
typedef struct
 
641
{
 
642
  word Width;              // width de l'image
 
643
  word Height;             // height de l'image
 
644
} T_CEL_Header1;
 
645
 
 
646
typedef struct
 
647
{
 
648
  byte Signature[4];           // Signature du format
 
649
  byte Kind;               // Type de fichier ($10=PALette $20=BitMaP)
 
650
  byte Nb_bits;             // Nombre de bits
 
651
  word Filler1;            // ???
 
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];        // ???
 
657
} T_CEL_Header2;
 
658
#pragma pack()
 
659
 
 
660
// -- Tester si un fichier est au format CEL --------------------------------
 
661
 
 
662
void Test_CEL(T_IO_Context * context)
 
663
{
 
664
  char filename[MAX_PATH_CHARACTERS];
 
665
  int  size;
 
666
  FILE *file;
 
667
  T_CEL_Header1 header1;
 
668
  T_CEL_Header2 header2;
 
669
  int file_size;
 
670
 
 
671
  File_error=0;
 
672
  Get_full_filename(filename, context->File_name, context->File_directory);
 
673
  file_size=File_length(filename);
 
674
  if (file_size==0)
 
675
  {
 
676
    File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber
 
677
    return;
 
678
  }
 
679
  
 
680
  if (! (file=fopen(filename, "rb")))
 
681
  {
 
682
    File_error = 1;
 
683
    return;
 
684
  }
 
685
  if (Read_word_le(file,&header1.Width) &&
 
686
      Read_word_le(file,&header1.Height) )
 
687
  {
 
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.
 
690
      
 
691
      size=file_size-sizeof(T_CEL_Header1);
 
692
      if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) )
 
693
      {
 
694
        // Tentative de reconnaissance de la signature des nouveaux fichiers
 
695
 
 
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))
 
708
        {
 
709
          // ok
 
710
        }
 
711
        else
 
712
          File_error=1;
 
713
      }
 
714
      else
 
715
        File_error=1;
 
716
  }
 
717
  else
 
718
  {
 
719
    File_error=1;
 
720
  }
 
721
  fclose(file);    
 
722
}
 
723
 
 
724
 
 
725
// -- Lire un fichier au format CEL -----------------------------------------
 
726
 
 
727
void Load_CEL(T_IO_Context * context)
 
728
{
 
729
  char filename[MAX_PATH_CHARACTERS];
 
730
  FILE *file;
 
731
  T_CEL_Header1 header1;
 
732
  T_CEL_Header2 header2;
 
733
  short x_pos;
 
734
  short y_pos;
 
735
  byte  last_byte=0;
 
736
  long  file_size;
 
737
  const long int header_size = (long int)(sizeof(header1.Width)+sizeof(header1.Height));
 
738
 
 
739
  File_error=0;
 
740
  Get_full_filename(filename, context->File_name, context->File_directory);
 
741
  if ((file=fopen(filename, "rb")))
 
742
  {
 
743
    if (Read_word_le(file,&(header1.Width))
 
744
    &&  Read_word_le(file,&(header1.Height)))
 
745
    {
 
746
      file_size=File_length_file(file);
 
747
      if ( (file_size>header_size)
 
748
        && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-header_size) ) )
 
749
      {
 
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);
 
756
        if (File_error==0)
 
757
        {
 
758
          // Chargement de l'image
 
759
          /*Init_lecture();*/
 
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++)
 
762
              if ((x_pos & 1)==0)
 
763
              {
 
764
                if(Read_byte(file,&last_byte)!=1) File_error = 2;
 
765
                Set_pixel(context, x_pos,y_pos,(last_byte >> 4));
 
766
              }
 
767
              else
 
768
                Set_pixel(context, x_pos,y_pos,(last_byte & 15));
 
769
          /*Close_lecture();*/
 
770
        }
 
771
      }
 
772
      else
 
773
      {
 
774
        // On r�essaye avec le nouveau format
 
775
 
 
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))
 
786
        )
 
787
        {
 
788
          // Chargement d'un fichier CEL avec signature (nouveaux fichiers)
 
789
 
 
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);
 
795
          if (File_error==0)
 
796
          {
 
797
            // Chargement de l'image
 
798
            /*Init_lecture();*/
 
799
 
 
800
            if (!File_error)
 
801
            {
 
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);
 
809
 
 
810
              switch(header2.Nb_bits)
 
811
              {
 
812
                case 4:
 
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++)
 
815
                      if ((x_pos & 1)==0)
 
816
                      {
 
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));
 
819
                      }
 
820
                      else
 
821
                        Set_pixel(context, x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15));
 
822
                  break;
 
823
 
 
824
                case 8:
 
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++)
 
827
                    {
 
828
                      byte byte_read;
 
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);
 
831
                      }
 
832
                  break;
 
833
 
 
834
                default:
 
835
                  File_error=1;
 
836
              }
 
837
            }
 
838
            /*Close_lecture();*/
 
839
          }
 
840
        }
 
841
        else
 
842
          File_error=1;
 
843
      }
 
844
      fclose(file);
 
845
    }
 
846
    else
 
847
      File_error=1;
 
848
  }
 
849
  else
 
850
    File_error=1;
 
851
}
 
852
 
 
853
 
 
854
// -- Ecrire un fichier au format CEL ---------------------------------------
 
855
 
 
856
void Save_CEL(T_IO_Context * context)
 
857
{
 
858
  char filename[MAX_PATH_CHARACTERS];
 
859
  FILE *file;
 
860
  T_CEL_Header1 header1;
 
861
  T_CEL_Header2 header2;
 
862
  short x_pos;
 
863
  short y_pos;
 
864
  byte  last_byte=0;
 
865
  dword Utilisation[256]; // Table d'utilisation de couleurs
 
866
 
 
867
 
 
868
  // On commence par compter l'utilisation de chaque couleurs
 
869
  Count_used_colors(Utilisation);
 
870
 
 
871
  File_error=0;
 
872
  Get_full_filename(filename, context->File_name, context->File_directory);
 
873
  if ((file=fopen(filename,"wb")))
 
874
  {
 
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++);
 
877
 
 
878
    if (x_pos==256)
 
879
    {
 
880
      // Cas d'une image 16 couleurs (�criture � l'ancien format)
 
881
 
 
882
      header1.Width =context->Width;
 
883
      header1.Height=context->Height;
 
884
 
 
885
      if (Write_word_le(file,header1.Width)
 
886
      && Write_word_le(file,header1.Height)
 
887
      )
 
888
      {
 
889
        // Sauvegarde de l'image
 
890
        Init_write_buffer();
 
891
        for (y_pos=0;((y_pos<context->Height) && (!File_error));y_pos++)
 
892
        {
 
893
          for (x_pos=0;((x_pos<context->Width) && (!File_error));x_pos++)
 
894
            if ((x_pos & 1)==0)
 
895
              last_byte=(Get_pixel(context, x_pos,y_pos) << 4);
 
896
            else
 
897
            {
 
898
              last_byte=last_byte | (Get_pixel(context, x_pos,y_pos) & 15);
 
899
              Write_one_byte(file,last_byte);
 
900
            }
 
901
 
 
902
          if ((x_pos & 1)==1)
 
903
            Write_one_byte(file,last_byte);
 
904
        }
 
905
        End_write(file);
 
906
      }
 
907
      else
 
908
        File_error=1;
 
909
      fclose(file);
 
910
    }
 
911
    else
 
912
    {
 
913
      // Cas d'une image 256 couleurs (�criture au nouveau format)
 
914
 
 
915
      // Recherche du d�calage
 
916
      for (y_pos=0;y_pos<context->Height;y_pos++)
 
917
      {
 
918
        for (x_pos=0;x_pos<context->Width;x_pos++)
 
919
          if (Get_pixel(context, x_pos,y_pos)!=0)
 
920
            break;
 
921
        if (Get_pixel(context, x_pos,y_pos)!=0)
 
922
          break;
 
923
      }
 
924
      header2.Y_offset=y_pos;
 
925
      for (x_pos=0;x_pos<context->Width;x_pos++)
 
926
      {
 
927
        for (y_pos=0;y_pos<context->Height;y_pos++)
 
928
          if (Get_pixel(context, x_pos,y_pos)!=0)
 
929
            break;
 
930
        if (Get_pixel(context, x_pos,y_pos)!=0)
 
931
          break;
 
932
      }
 
933
      header2.X_offset=x_pos;
 
934
 
 
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;
 
943
 
 
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))
 
953
      )
 
954
      {
 
955
        // Sauvegarde de l'image
 
956
        Init_write_buffer();
 
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));
 
960
        End_write(file);
 
961
      }
 
962
      else
 
963
        File_error=1;
 
964
      fclose(file);
 
965
    }
 
966
 
 
967
    if (File_error)
 
968
      remove(filename);
 
969
  }
 
970
  else
 
971
    File_error=1;
 
972
}
 
973
 
 
974
 
 
975
//////////////////////////////////// KCF ////////////////////////////////////
 
976
#pragma pack(1)
 
977
typedef struct
 
978
{
 
979
  struct
 
980
  {
 
981
    struct
 
982
    {
 
983
      byte Byte1;
 
984
      byte Byte2;
 
985
    } color[16];
 
986
  } Palette[10];
 
987
} T_KCF_Header;
 
988
#pragma pack()
 
989
 
 
990
// -- Tester si un fichier est au format KCF --------------------------------
 
991
 
 
992
void Test_KCF(T_IO_Context * context)
 
993
{
 
994
  char filename[MAX_PATH_CHARACTERS];
 
995
  FILE *file;
 
996
  T_KCF_Header buffer;
 
997
  T_CEL_Header2 header2;
 
998
  int pal_index;
 
999
  int color_index;
 
1000
 
 
1001
  File_error=0;
 
1002
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1003
  if ((file=fopen(filename, "rb")))
 
1004
  {
 
1005
    if (File_length_file(file)==sizeof(T_KCF_Header))
 
1006
    {
 
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)
 
1012
            File_error=1;
 
1013
    }
 
1014
    else
 
1015
    {
 
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))
 
1025
        )
 
1026
      {
 
1027
        if (memcmp(header2.Signature,"KiSS",4)==0)
 
1028
        {
 
1029
          if (header2.Kind!=0x10)
 
1030
            File_error=1;
 
1031
        }
 
1032
        else
 
1033
          File_error=1;
 
1034
      }
 
1035
      else
 
1036
        File_error=1;
 
1037
    }
 
1038
    fclose(file);
 
1039
  }
 
1040
  else
 
1041
    File_error=1;
 
1042
}
 
1043
 
 
1044
 
 
1045
// -- Lire un fichier au format KCF -----------------------------------------
 
1046
 
 
1047
void Load_KCF(T_IO_Context * context)
 
1048
{
 
1049
  char filename[MAX_PATH_CHARACTERS];
 
1050
  FILE *file;
 
1051
  T_KCF_Header buffer;
 
1052
  T_CEL_Header2 header2;
 
1053
  byte bytes[3];
 
1054
  int pal_index;
 
1055
  int color_index;
 
1056
  int index;
 
1057
  long  file_size;
 
1058
 
 
1059
 
 
1060
  File_error=0;
 
1061
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1062
  if ((file=fopen(filename, "rb")))
 
1063
  {
 
1064
    file_size=File_length_file(file);
 
1065
    if (file_size==sizeof(T_KCF_Header))
 
1066
    {
 
1067
      // Fichier KCF � l'ancien format
 
1068
 
 
1069
      if (Read_bytes(file,&buffer,sizeof(T_KCF_Header)))
 
1070
      {
 
1071
        // Pre_load(context, ?); // Pas possible... pas d'image...
 
1072
 
 
1073
        if (Config.Clear_palette)
 
1074
          memset(context->Palette,0,sizeof(T_Palette));
 
1075
 
 
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++)
 
1079
          {
 
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);
 
1084
          }
 
1085
 
 
1086
        for (index=0;index<16;index++)
 
1087
        {
 
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;
 
1091
        }
 
1092
 
 
1093
        Palette_loaded(context);
 
1094
      }
 
1095
      else
 
1096
        File_error=1;
 
1097
    }
 
1098
    else
 
1099
    {
 
1100
      // Fichier KCF au nouveau format
 
1101
 
 
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))
 
1111
        )
 
1112
      {
 
1113
        // Pre_load(context, ?); // Pas possible... pas d'image...
 
1114
 
 
1115
        index=(header2.Nb_bits==12)?16:0;
 
1116
        for (pal_index=0;pal_index<header2.Height;pal_index++)
 
1117
        {
 
1118
           // Pour chaque palette
 
1119
 
 
1120
           for (color_index=0;color_index<header2.Width;color_index++)
 
1121
           {
 
1122
             // Pour chaque couleur
 
1123
 
 
1124
             switch(header2.Nb_bits)
 
1125
             {
 
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;
 
1131
                 break;
 
1132
 
 
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];
 
1138
             }
 
1139
 
 
1140
             index++;
 
1141
           }
 
1142
        }
 
1143
 
 
1144
        if (header2.Nb_bits==12)
 
1145
          for (index=0;index<16;index++)
 
1146
          {
 
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;
 
1150
          }
 
1151
 
 
1152
        Palette_loaded(context);
 
1153
      }
 
1154
      else
 
1155
        File_error=1;
 
1156
    }
 
1157
    fclose(file);
 
1158
  }
 
1159
  else
 
1160
    File_error=1;
 
1161
}
 
1162
 
 
1163
 
 
1164
// -- Ecrire un fichier au format KCF ---------------------------------------
 
1165
 
 
1166
void Save_KCF(T_IO_Context * context)
 
1167
{
 
1168
  char filename[MAX_PATH_CHARACTERS];
 
1169
  FILE *file;
 
1170
  T_KCF_Header buffer;
 
1171
  T_CEL_Header2 header2;
 
1172
  byte bytes[3];
 
1173
  int pal_index;
 
1174
  int color_index;
 
1175
  int index;
 
1176
  dword Utilisation[256]; // Table d'utilisation de couleurs
 
1177
 
 
1178
  // On commence par compter l'utilisation de chaque couleurs
 
1179
  Count_used_colors(Utilisation);
 
1180
 
 
1181
  File_error=0;
 
1182
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1183
  if ((file=fopen(filename,"wb")))
 
1184
  {
 
1185
    // Sauvegarde de la palette
 
1186
 
 
1187
    // On regarde si des couleurs >16 sont utilis�es dans l'image
 
1188
    for (index=16;((index<256) && (!Utilisation[index]));index++);
 
1189
 
 
1190
    if (index==256)
 
1191
    {
 
1192
      // Cas d'une image 16 couleurs (�criture � l'ancien format)
 
1193
 
 
1194
      for (pal_index=0;pal_index<10;pal_index++)
 
1195
        for (color_index=0;color_index<16;color_index++)
 
1196
        {
 
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;
 
1200
        }
 
1201
 
 
1202
      if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header)))
 
1203
        File_error=1;
 
1204
    }
 
1205
    else
 
1206
    {
 
1207
      // Cas d'une image 256 couleurs (�criture au nouveau format)
 
1208
 
 
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;
 
1219
 
 
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))
 
1229
      )
 
1230
        File_error=1;
 
1231
 
 
1232
      for (index=0;(index<256) && (!File_error);index++)
 
1233
      {
 
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))
 
1238
          File_error=1;
 
1239
      }
 
1240
    }
 
1241
 
 
1242
    fclose(file);
 
1243
 
 
1244
    if (File_error)
 
1245
      remove(filename);
 
1246
  }
 
1247
  else
 
1248
    File_error=1;
 
1249
}
 
1250
 
 
1251
 
 
1252
//////////////////////////////////// PI1 ////////////////////////////////////
 
1253
 
 
1254
//// DECODAGE d'une partie d'IMAGE ////
 
1255
 
 
1256
void PI1_8b_to_16p(byte * src,byte * dest)
 
1257
{
 
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
 
1261
 
 
1262
  byte_mask=0x8000;
 
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];
 
1267
  for (i=0;i<16;i++)
 
1268
  {
 
1269
    // Pour d�coder le pixel n�i, il faut traiter les 4 words sur leur bit
 
1270
    // correspondant � celui du masque
 
1271
 
 
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);
 
1276
    byte_mask>>=1;
 
1277
  }
 
1278
}
 
1279
 
 
1280
//// CODAGE d'une partie d'IMAGE ////
 
1281
 
 
1282
void PI1_16p_to_8b(byte * src,byte * dest)
 
1283
{
 
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
 
1287
 
 
1288
  byte_mask=0x8000;
 
1289
  w0=w1=w2=w3=0;
 
1290
  for (i=0;i<16;i++)
 
1291
  {
 
1292
    // Pour coder le pixel n�i, il faut modifier les 4 words sur leur bit
 
1293
    // correspondant � celui du masque
 
1294
 
 
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;
 
1299
    byte_mask>>=1;
 
1300
  }
 
1301
  dest[0]=w0 >> 8;
 
1302
  dest[1]=w0 & 0x00FF;
 
1303
  dest[2]=w1 >> 8;
 
1304
  dest[3]=w1 & 0x00FF;
 
1305
  dest[4]=w2 >> 8;
 
1306
  dest[5]=w2 & 0x00FF;
 
1307
  dest[6]=w3 >> 8;
 
1308
  dest[7]=w3 & 0x00FF;
 
1309
}
 
1310
 
 
1311
//// DECODAGE de la PALETTE ////
 
1312
 
 
1313
void PI1_decode_palette(byte * src,byte * palette)
 
1314
{
 
1315
  int i;  // Num�ro de la couleur trait�e
 
1316
  int ip; // index dans la palette
 
1317
  word w; // Word contenant le code
 
1318
 
 
1319
  // Sch�ma d'un word =
 
1320
  //
 
1321
  //    Low        High
 
1322
  // VVVV RRRR | 0000 BBBB
 
1323
  // 0321 0321 |      0321
 
1324
 
 
1325
  ip=0;
 
1326
  for (i=0;i<16;i++)
 
1327
  {
 
1328
    w=((word)src[(i*2)+1]<<8) | src[(i*2)+0];
 
1329
 
 
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;
 
1334
  }
 
1335
}
 
1336
 
 
1337
//// CODAGE de la PALETTE ////
 
1338
 
 
1339
void PI1_code_palette(byte * palette,byte * dest)
 
1340
{
 
1341
  int i;  // Num�ro de la couleur trait�e
 
1342
  int ip; // index dans la palette
 
1343
  word w; // Word contenant le code
 
1344
 
 
1345
  // Sch�ma d'un word =
 
1346
  //
 
1347
  //    Low        High
 
1348
  // VVVV RRRR | 0000 BBBB
 
1349
  // 0321 0321 |      0321
 
1350
 
 
1351
  ip=0;
 
1352
  for (i=0;i<16;i++)
 
1353
  {
 
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++;
 
1358
 
 
1359
    dest[(i*2)+0]=w & 0x00FF;
 
1360
    dest[(i*2)+1]=(w>>8);
 
1361
  }
 
1362
}
 
1363
 
 
1364
 
 
1365
// -- Tester si un fichier est au format PI1 --------------------------------
 
1366
void Test_PI1(T_IO_Context * context)
 
1367
{
 
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
 
1372
 
 
1373
 
 
1374
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1375
 
 
1376
  File_error=1;
 
1377
 
 
1378
  // Ouverture du fichier
 
1379
  if ((file=fopen(filename, "rb")))
 
1380
  {
 
1381
    // V�rification de la taille
 
1382
    size=File_length_file(file);
 
1383
    if ((size==32034) || (size==32066))
 
1384
    {
 
1385
      // Lecture et v�rification de la r�solution
 
1386
      if (Read_word_le(file,&resolution))
 
1387
      {
 
1388
        if (resolution==0x0000)
 
1389
          File_error=0;
 
1390
      }
 
1391
    }
 
1392
    // Fermeture du fichier
 
1393
    fclose(file);
 
1394
  }
 
1395
}
 
1396
 
 
1397
 
 
1398
// -- Lire un fichier au format PI1 -----------------------------------------
 
1399
void Load_PI1(T_IO_Context * context)
 
1400
{
 
1401
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
1402
  FILE *file;
 
1403
  word x_pos,y_pos;
 
1404
  byte * buffer;
 
1405
  byte * ptr;
 
1406
  byte pixels[320];
 
1407
 
 
1408
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1409
 
 
1410
  File_error=0;
 
1411
  if ((file=fopen(filename, "rb")))
 
1412
  {
 
1413
    // allocation d'un buffer m�moire
 
1414
    buffer=(byte *)malloc(32034);
 
1415
    if (buffer!=NULL)
 
1416
    {
 
1417
      // Lecture du fichier dans le buffer
 
1418
      if (Read_bytes(file,buffer,32034))
 
1419
      {
 
1420
        // Initialisation de la preview
 
1421
        Pre_load(context, 320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE,0);
 
1422
        if (File_error==0)
 
1423
        {
 
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);
 
1429
 
 
1430
          context->Width=320;
 
1431
          context->Height=200;
 
1432
 
 
1433
          // Chargement/d�compression de l'image
 
1434
          ptr=buffer+34;
 
1435
          for (y_pos=0;y_pos<200;y_pos++)
 
1436
          {
 
1437
            for (x_pos=0;x_pos<(320>>4);x_pos++)
 
1438
            {
 
1439
              PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
 
1440
              ptr+=8;
 
1441
            }
 
1442
            for (x_pos=0;x_pos<320;x_pos++)
 
1443
              Set_pixel(context, x_pos,y_pos,pixels[x_pos]);
 
1444
          }
 
1445
        }
 
1446
      }
 
1447
      else
 
1448
        File_error=1;
 
1449
      free(buffer);
 
1450
      buffer = NULL;
 
1451
    }
 
1452
    else
 
1453
      File_error=1;
 
1454
    fclose(file);
 
1455
  }
 
1456
  else
 
1457
    File_error=1;
 
1458
}
 
1459
 
 
1460
 
 
1461
// -- Sauver un fichier au format PI1 ---------------------------------------
 
1462
void Save_PI1(T_IO_Context * context)
 
1463
{
 
1464
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
1465
  FILE *file;
 
1466
  short x_pos,y_pos;
 
1467
  byte * buffer;
 
1468
  byte * ptr;
 
1469
  byte pixels[320];
 
1470
 
 
1471
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1472
 
 
1473
  File_error=0;
 
1474
  // Ouverture du fichier
 
1475
  if ((file=fopen(filename,"wb")))
 
1476
  {
 
1477
    // allocation d'un buffer m�moire
 
1478
    buffer=(byte *)malloc(32066);
 
1479
    // Codage de la r�solution
 
1480
    buffer[0]=0x00;
 
1481
    buffer[1]=0x00;
 
1482
    // Codage de la palette
 
1483
    PI1_code_palette((byte *)context->Palette,buffer+2);
 
1484
    // Codage de l'image
 
1485
    ptr=buffer+34;
 
1486
    for (y_pos=0;y_pos<200;y_pos++)
 
1487
    {
 
1488
      // Codage de la ligne
 
1489
      memset(pixels,0,320);
 
1490
      if (y_pos<context->Height)
 
1491
      {
 
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);
 
1494
      }
 
1495
 
 
1496
      for (x_pos=0;x_pos<(320>>4);x_pos++)
 
1497
      {
 
1498
        PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
 
1499
        ptr+=8;
 
1500
      }
 
1501
    }
 
1502
 
 
1503
    memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy
 
1504
 
 
1505
    if (Write_bytes(file,buffer,32066))
 
1506
    {
 
1507
      fclose(file);
 
1508
    }
 
1509
    else // Error d'�criture (disque plein ou prot�g�)
 
1510
    {
 
1511
      fclose(file);
 
1512
      remove(filename);
 
1513
      File_error=1;
 
1514
    }
 
1515
    // Lib�ration du buffer m�moire
 
1516
    free(buffer);
 
1517
    buffer = NULL;
 
1518
  }
 
1519
  else
 
1520
  {
 
1521
    fclose(file);
 
1522
    remove(filename);
 
1523
    File_error=1;
 
1524
  }
 
1525
}
 
1526
 
 
1527
 
 
1528
//////////////////////////////////// PC1 ////////////////////////////////////
 
1529
 
 
1530
//// DECOMPRESSION d'un buffer selon la m�thode PACKBITS ////
 
1531
 
 
1532
void PC1_uncompress_packbits(byte * src,byte * dest)
 
1533
{
 
1534
  int is,id; // Les indices de parcour des buffers
 
1535
  int n;     // Octet de contr�le
 
1536
 
 
1537
  for (is=id=0;id<32000;)
 
1538
  {
 
1539
    n=src[is++];
 
1540
 
 
1541
    if (n & 0x80)
 
1542
    {
 
1543
      // Recopier src[is] -n+1 fois
 
1544
      n=257-n;
 
1545
      for (;(n>0) && (id<32000);n--)
 
1546
        dest[id++]=src[is];
 
1547
      is++;
 
1548
    }
 
1549
    else
 
1550
    {
 
1551
      // Recopier n+1 octets litt�ralement
 
1552
      n=n+1;
 
1553
      for (;(n>0) && (id<32000);n--)
 
1554
        dest[id++]=src[is++];
 
1555
    }
 
1556
 
 
1557
    // Contr�le des erreurs
 
1558
    if (n>0)
 
1559
      File_error=1;
 
1560
  }
 
1561
}
 
1562
 
 
1563
//// COMPRESSION d'un buffer selon la m�thode PACKBITS ////
 
1564
 
 
1565
void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size)
 
1566
{
 
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"
 
1572
 
 
1573
  for (is=id=0;is<source_size;)
 
1574
  {
 
1575
    // On recherche le 1er endroit o� il y a r�p�tition d'au moins 3 valeurs
 
1576
    // identiques
 
1577
 
 
1578
    repet=0;
 
1579
    for (ir=is;ir<source_size-2;ir++)
 
1580
    {
 
1581
      if ((src[ir]==src[ir+1]) && (src[ir+1]==src[ir+2]))
 
1582
      {
 
1583
        repet=1;
 
1584
        break;
 
1585
      }
 
1586
      if ((ir-is)+1==40)
 
1587
        break;
 
1588
    }
 
1589
 
 
1590
    // On code la partie sans r�p�titions
 
1591
    if (ir!=is)
 
1592
    {
 
1593
      n=(ir-is)+1;
 
1594
      dest[id++]=n-1;
 
1595
      for (;n>0;n--)
 
1596
        dest[id++]=src[is++];
 
1597
    }
 
1598
 
 
1599
    // On code la partie sans r�p�titions
 
1600
    if (repet)
 
1601
    {
 
1602
      // On compte la quantit� de fois qu'il faut r�p�ter la valeur
 
1603
      for (ir+=3;ir<source_size;ir++)
 
1604
      {
 
1605
        if (src[ir]!=src[is])
 
1606
          break;
 
1607
        if ((ir-is)+1==40)
 
1608
          break;
 
1609
      }
 
1610
      n=(ir-is);
 
1611
      dest[id++]=257-n;
 
1612
      dest[id++]=src[is];
 
1613
      is=ir;
 
1614
    }
 
1615
  }
 
1616
 
 
1617
  // On renseigne la taille du buffer compress�
 
1618
  *dest_size=id;
 
1619
}
 
1620
 
 
1621
//// DECODAGE d'une partie d'IMAGE ////
 
1622
 
 
1623
// Transformation de 4 plans de bits en 1 ligne de pixels
 
1624
 
 
1625
void PC1_4bp_to_1line(byte * src0,byte * src1,byte * src2,byte * src3,byte * dest)
 
1626
{
 
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
 
1631
 
 
1632
  ip=0;
 
1633
  // Pour chacun des 40 octets des plans de bits
 
1634
  for (i=0;i<40;i++)
 
1635
  {
 
1636
    b0=src0[i];
 
1637
    b1=src1[i];
 
1638
    b2=src2[i];
 
1639
    b3=src3[i];
 
1640
    // Pour chacun des 8 bits des octets
 
1641
    byte_mask=0x80;
 
1642
    for (j=0;j<8;j++)
 
1643
    {
 
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);
 
1648
      byte_mask>>=1;
 
1649
    }
 
1650
  }
 
1651
}
 
1652
 
 
1653
//// CODAGE d'une partie d'IMAGE ////
 
1654
 
 
1655
// Transformation d'1 ligne de pixels en 4 plans de bits
 
1656
 
 
1657
void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3)
 
1658
{
 
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
 
1663
 
 
1664
  ip=0;
 
1665
  // Pour chacun des 40 octets des plans de bits
 
1666
  for (i=0;i<40;i++)
 
1667
  {
 
1668
    // Pour chacun des 8 bits des octets
 
1669
    byte_mask=0x80;
 
1670
    b0=b1=b2=b3=0;
 
1671
    for (j=0;j<8;j++)
 
1672
    {
 
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;
 
1677
      ip++;
 
1678
      byte_mask>>=1;
 
1679
    }
 
1680
    dst0[i]=b0;
 
1681
    dst1[i]=b1;
 
1682
    dst2[i]=b2;
 
1683
    dst3[i]=b3;
 
1684
  }
 
1685
}
 
1686
 
 
1687
 
 
1688
// -- Tester si un fichier est au format PC1 --------------------------------
 
1689
void Test_PC1(T_IO_Context * context)
 
1690
{
 
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
 
1695
 
 
1696
 
 
1697
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1698
 
 
1699
  File_error=1;
 
1700
 
 
1701
  // Ouverture du fichier
 
1702
  if ((file=fopen(filename, "rb")))
 
1703
  {
 
1704
    // V�rification de la taille
 
1705
    size=File_length_file(file);
 
1706
    if ((size<=32066))
 
1707
    {
 
1708
      // Lecture et v�rification de la r�solution
 
1709
      if (Read_word_le(file,&resolution))
 
1710
      {
 
1711
        if (resolution==0x0080)
 
1712
          File_error=0;
 
1713
      }
 
1714
    }
 
1715
    // Fermeture du fichier
 
1716
    fclose(file);
 
1717
  }
 
1718
}
 
1719
 
 
1720
 
 
1721
// -- Lire un fichier au format PC1 -----------------------------------------
 
1722
void Load_PC1(T_IO_Context * context)
 
1723
{
 
1724
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
1725
  FILE *file;
 
1726
  int  size;
 
1727
  word x_pos,y_pos;
 
1728
  byte * buffercomp;
 
1729
  byte * bufferdecomp;
 
1730
  byte * ptr;
 
1731
  byte pixels[320];
 
1732
 
 
1733
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1734
 
 
1735
  File_error=0;
 
1736
  if ((file=fopen(filename, "rb")))
 
1737
  {
 
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) )
 
1743
    {
 
1744
      // Lecture du fichier dans le buffer
 
1745
      if (Read_bytes(file,buffercomp,size))
 
1746
      {
 
1747
        // Initialisation de la preview
 
1748
        Pre_load(context, 320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE,0);
 
1749
        if (File_error==0)
 
1750
        {
 
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);
 
1756
 
 
1757
          context->Width=320;
 
1758
          context->Height=200;
 
1759
 
 
1760
          // D�compression du buffer
 
1761
          PC1_uncompress_packbits(buffercomp+34,bufferdecomp);
 
1762
 
 
1763
          // D�codage de l'image
 
1764
          ptr=bufferdecomp;
 
1765
          for (y_pos=0;y_pos<200;y_pos++)
 
1766
          {
 
1767
            // D�codage de la scanline
 
1768
            PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels);
 
1769
            ptr+=160;
 
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]);
 
1773
          }
 
1774
        }
 
1775
      }
 
1776
      else
 
1777
        File_error=1;
 
1778
      free(bufferdecomp);
 
1779
      free(buffercomp);
 
1780
      buffercomp = bufferdecomp = NULL;
 
1781
    }
 
1782
    else
 
1783
    {
 
1784
      File_error=1;
 
1785
      free(bufferdecomp);
 
1786
      free(buffercomp);
 
1787
      buffercomp = bufferdecomp = NULL;
 
1788
    }
 
1789
    fclose(file);
 
1790
  }
 
1791
  else
 
1792
    File_error=1;
 
1793
}
 
1794
 
 
1795
 
 
1796
// -- Sauver un fichier au format PC1 ---------------------------------------
 
1797
void Save_PC1(T_IO_Context * context)
 
1798
{
 
1799
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
1800
  FILE *file;
 
1801
  int   size;
 
1802
  short x_pos,y_pos;
 
1803
  byte * buffercomp;
 
1804
  byte * bufferdecomp;
 
1805
  byte * ptr;
 
1806
  byte pixels[320];
 
1807
 
 
1808
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1809
 
 
1810
  File_error=0;
 
1811
  // Ouverture du fichier
 
1812
  if ((file=fopen(filename,"wb")))
 
1813
  {
 
1814
    // Allocation des buffers m�moire
 
1815
    bufferdecomp=(byte *)malloc(32000);
 
1816
    buffercomp  =(byte *)malloc(64066);
 
1817
    // Codage de la r�solution
 
1818
    buffercomp[0]=0x80;
 
1819
    buffercomp[1]=0x00;
 
1820
    // Codage de la palette
 
1821
    PI1_code_palette((byte *)context->Palette,buffercomp+2);
 
1822
    // Codage de l'image
 
1823
    ptr=bufferdecomp;
 
1824
    for (y_pos=0;y_pos<200;y_pos++)
 
1825
    {
 
1826
      // Codage de la ligne
 
1827
      memset(pixels,0,320);
 
1828
      if (y_pos<context->Height)
 
1829
      {
 
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);
 
1832
      }
 
1833
 
 
1834
      // Encodage de la scanline
 
1835
      PC1_1line_to_4bp(pixels,ptr,ptr+40,ptr+80,ptr+120);
 
1836
      ptr+=160;
 
1837
    }
 
1838
 
 
1839
    // Compression du buffer
 
1840
    PC1_compress_packbits(bufferdecomp,buffercomp+34,32000,&size);
 
1841
    size+=34;
 
1842
    for (x_pos=0;x_pos<16;x_pos++)
 
1843
      buffercomp[size++]=0;
 
1844
 
 
1845
    if (Write_bytes(file,buffercomp,size))
 
1846
    {
 
1847
      fclose(file);
 
1848
    }
 
1849
    else // Error d'�criture (disque plein ou prot�g�)
 
1850
    {
 
1851
      fclose(file);
 
1852
      remove(filename);
 
1853
      File_error=1;
 
1854
    }
 
1855
    // Lib�ration des buffers m�moire
 
1856
    free(bufferdecomp);
 
1857
    free(buffercomp);
 
1858
    buffercomp = bufferdecomp = NULL;
 
1859
  }
 
1860
  else
 
1861
  {
 
1862
    fclose(file);
 
1863
    remove(filename);
 
1864
    File_error=1;
 
1865
  }
 
1866
}
 
1867
 
 
1868
 
 
1869
//////////////////////////////////// NEO ////////////////////////////////////
 
1870
 
 
1871
void Test_NEO(T_IO_Context * context)
 
1872
{
 
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
 
1877
 
 
1878
 
 
1879
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1880
 
 
1881
  File_error=1;
 
1882
 
 
1883
  // Ouverture du fichier
 
1884
  if ((file=fopen(filename, "rb")))
 
1885
  {
 
1886
    // V�rification de la taille
 
1887
    size=File_length_file(file);
 
1888
    if ((size==32128))
 
1889
    {
 
1890
      // Flag word : toujours 0
 
1891
      if (Read_word_le(file,&resolution))
 
1892
      {
 
1893
        if (resolution == 0)
 
1894
          File_error = 0;
 
1895
      }
 
1896
 
 
1897
      // Lecture et v�rification de la r�solution
 
1898
      if (Read_word_le(file,&resolution))
 
1899
      {
 
1900
        if (resolution==0 || resolution==1 || resolution==2)
 
1901
          File_error |= 0;
 
1902
      }
 
1903
    }
 
1904
    // Fermeture du fichier
 
1905
    fclose(file);
 
1906
  }
 
1907
 
 
1908
}
 
1909
 
 
1910
void Load_NEO(T_IO_Context * context)
 
1911
{
 
1912
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
1913
  FILE *file;
 
1914
  word x_pos,y_pos;
 
1915
  byte * buffer;
 
1916
  byte * ptr;
 
1917
  byte pixels[320];
 
1918
 
 
1919
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1920
 
 
1921
  File_error=0;
 
1922
  if ((file=fopen(filename, "rb")))
 
1923
  {
 
1924
    // allocation d'un buffer m�moire
 
1925
    buffer=(byte *)malloc(32128);
 
1926
    if (buffer!=NULL)
 
1927
    {
 
1928
      // Lecture du fichier dans le buffer
 
1929
      if (Read_bytes(file,buffer,32128))
 
1930
      {
 
1931
        // Initialisation de la preview
 
1932
        Pre_load(context, 320,200,File_length_file(file),FORMAT_NEO,PIXEL_SIMPLE,0);
 
1933
        if (File_error==0)
 
1934
        {
 
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);
 
1941
 
 
1942
          context->Width=320;
 
1943
          context->Height=200;
 
1944
 
 
1945
          // Chargement/d�compression de l'image
 
1946
          ptr=buffer+128;
 
1947
          for (y_pos=0;y_pos<200;y_pos++)
 
1948
          {
 
1949
            for (x_pos=0;x_pos<(320>>4);x_pos++)
 
1950
            {
 
1951
              PI1_8b_to_16p(ptr,pixels+(x_pos<<4));
 
1952
              ptr+=8;
 
1953
            }
 
1954
            for (x_pos=0;x_pos<320;x_pos++)
 
1955
              Set_pixel(context, x_pos,y_pos,pixels[x_pos]);
 
1956
          }
 
1957
        }
 
1958
      }
 
1959
      else
 
1960
        File_error=1;
 
1961
      free(buffer);
 
1962
      buffer = NULL;
 
1963
    }
 
1964
    else
 
1965
      File_error=1;
 
1966
    fclose(file);
 
1967
  }
 
1968
  else
 
1969
    File_error=1;
 
1970
}
 
1971
 
 
1972
void Save_NEO(T_IO_Context * context)
 
1973
{
 
1974
  char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
 
1975
  FILE *file;
 
1976
  short x_pos,y_pos;
 
1977
  byte * buffer;
 
1978
  byte * ptr;
 
1979
  byte pixels[320];
 
1980
 
 
1981
  Get_full_filename(filename, context->File_name, context->File_directory);
 
1982
 
 
1983
  File_error=0;
 
1984
  // Ouverture du fichier
 
1985
  if ((file=fopen(filename,"wb")))
 
1986
  {
 
1987
    // allocation d'un buffer m�moire
 
1988
    buffer=(byte *)malloc(32128);
 
1989
    // Codage de la r�solution
 
1990
    buffer[0]=0x00;
 
1991
    buffer[1]=0x00;
 
1992
    buffer[2]=0x00;
 
1993
    buffer[3]=0x00;
 
1994
    // Codage de la palette
 
1995
    PI1_code_palette((byte *)context->Palette,buffer+4);
 
1996
    // Codage de l'image
 
1997
    ptr=buffer+128;
 
1998
    for (y_pos=0;y_pos<200;y_pos++)
 
1999
    {
 
2000
      // Codage de la ligne
 
2001
      memset(pixels,0,320);
 
2002
      if (y_pos<context->Height)
 
2003
      {
 
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);
 
2006
      }
 
2007
 
 
2008
      for (x_pos=0;x_pos<(320>>4);x_pos++)
 
2009
      {
 
2010
        PI1_16p_to_8b(pixels+(x_pos<<4),ptr);
 
2011
        ptr+=8;
 
2012
      }
 
2013
    }
 
2014
 
 
2015
    if (Write_bytes(file,buffer,32128))
 
2016
    {
 
2017
      fclose(file);
 
2018
    }
 
2019
    else // Error d'�criture (disque plein ou prot�g�)
 
2020
    {
 
2021
      fclose(file);
 
2022
      remove(filename);
 
2023
      File_error=1;
 
2024
    }
 
2025
    // Lib�ration du buffer m�moire
 
2026
    free(buffer);
 
2027
    buffer = NULL;
 
2028
  }
 
2029
  else
 
2030
  {
 
2031
    fclose(file);
 
2032
    remove(filename);
 
2033
    File_error=1;
 
2034
  }
 
2035
}
 
2036
 
 
2037
//////////////////////////////////// C64 ////////////////////////////////////
 
2038
void Test_C64(T_IO_Context * context)
 
2039
{  
 
2040
    FILE* file;
 
2041
    char filename[MAX_PATH_CHARACTERS];
 
2042
    long file_size;
 
2043
  
 
2044
    Get_full_filename(filename, context->File_name, context->File_directory);
 
2045
  
 
2046
    file = fopen(filename,"rb");
 
2047
  
 
2048
    if (file)
 
2049
    {
 
2050
        file_size = File_length_file(file);
 
2051
        switch (file_size)
 
2052
        {
 
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
 
2061
                File_error = 0;
 
2062
                break;
 
2063
            default: // then we don't know for now.
 
2064
            File_error = 1;
 
2065
        }
 
2066
        fclose (file);
 
2067
    }
 
2068
    else
 
2069
    {
 
2070
        File_error = 1;
 
2071
    }
 
2072
}
 
2073
 
 
2074
void Load_C64_hires(T_IO_Context *context, byte *bitmap, byte *colors)
 
2075
{
 
2076
    int cx,cy,x,y,c[4],pixel,color;
 
2077
  
 
2078
    for(cy=0; cy<25; cy++)
 
2079
    {
 
2080
        for(cx=0; cx<40; cx++)
 
2081
        {
 
2082
            c[0]=colors[cy*40+cx]&15;
 
2083
            c[1]=colors[cy*40+cx]>>4;
 
2084
            for(y=0; y<8; y++)
 
2085
            {
 
2086
                pixel=bitmap[cy*320+cx*8+y];
 
2087
                for(x=0; x<8; x++)
 
2088
                {
 
2089
                    color=c[pixel&(1<<(7-x))?1:0];
 
2090
                    Set_pixel(context, cx*8+x,cy*8+y,color);
 
2091
                }
 
2092
            }
 
2093
        }
 
2094
    }
 
2095
}
 
2096
 
 
2097
void Load_C64_multi(T_IO_Context *context, byte *bitmap, byte *colors, byte *nybble, byte background)
 
2098
{
 
2099
    int cx,cy,x,y,c[4],pixel,color;
 
2100
    c[0]=background&15;
 
2101
    for(cy=0; cy<25; cy++)
 
2102
    {
 
2103
        for(cx=0; cx<40; cx++)
 
2104
        {
 
2105
            c[1]=colors[cy*40+cx]>>4;
 
2106
            c[2]=colors[cy*40+cx]&15;
 
2107
            c[3]=nybble[cy*40+cx]&15;
 
2108
                
 
2109
            for(y=0; y<8; y++)
 
2110
            {
 
2111
                pixel=bitmap[cy*320+cx*8+y];
 
2112
                for(x=0; x<4; x++)
 
2113
                {
 
2114
                    color=c[(pixel&3)];
 
2115
                    pixel>>=2;
 
2116
                    Set_pixel(context, cx*4+(3-x),cy*8+y,color);
 
2117
                }
 
2118
            }
 
2119
        }
 
2120
    }
 
2121
}
 
2122
 
 
2123
void Load_C64(T_IO_Context * context)
 
2124
{    
 
2125
    FILE* file;
 
2126
    char filename[MAX_PATH_CHARACTERS];
 
2127
    long file_size;
 
2128
    int i;
 
2129
    byte background,hasLoadAddr=0;
 
2130
    int loadFormat=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"};
 
2133
    
 
2134
    // Palette from http://www.pepto.de/projects/colorvic/
 
2135
    byte pal[48]={
 
2136
      0x00, 0x00, 0x00, 
 
2137
      0xFF, 0xFF, 0xFF, 
 
2138
      0x68, 0x37, 0x2B, 
 
2139
      0x70, 0xA4, 0xB2, 
 
2140
      0x6F, 0x3D, 0x86, 
 
2141
      0x58, 0x8D, 0x43, 
 
2142
      0x35, 0x28, 0x79, 
 
2143
      0xB8, 0xC7, 0x6F, 
 
2144
      0x6F, 0x4F, 0x25, 
 
2145
      0x43, 0x39, 0x00, 
 
2146
      0x9A, 0x67, 0x59, 
 
2147
      0x44, 0x44, 0x44, 
 
2148
      0x6C, 0x6C, 0x6C, 
 
2149
      0x9A, 0xD2, 0x84, 
 
2150
      0x6C, 0x5E, 0xB5, 
 
2151
      0x95, 0x95, 0x95};
 
2152
  
 
2153
    byte bitmap[8000],colors[1000],nybble[1000];
 
2154
    word width=320, height=200;
 
2155
    
 
2156
    Get_full_filename(filename, context->File_name, context->File_directory);
 
2157
    file = fopen(filename,"rb");
 
2158
  
 
2159
    if (file)
 
2160
    {
 
2161
    File_error=0;
 
2162
    file_size = File_length_file(file);
 
2163
 
 
2164
    switch (file_size)
 
2165
        {
 
2166
            case 1000: // screen or color
 
2167
                hasLoadAddr=0;
 
2168
                loadFormat=F_screen;
 
2169
                break;
 
2170
                
 
2171
            case 1002: // (screen or color) + loadaddr
 
2172
                hasLoadAddr=1;
 
2173
                loadFormat=F_screen;
 
2174
                break;
 
2175
                    
 
2176
            case 8000: // raw bitmap
 
2177
                hasLoadAddr=0;
 
2178
                loadFormat=F_bitmap;
 
2179
                break;
 
2180
                    
 
2181
            case 8002: // raw bitmap with loadaddr
 
2182
                hasLoadAddr=1;
 
2183
                loadFormat=F_bitmap;
 
2184
                break;
 
2185
                    
 
2186
            case 9000: // bitmap + screen
 
2187
                hasLoadAddr=0;
 
2188
                loadFormat=F_hires;
 
2189
                break;
 
2190
                    
 
2191
            case 9002: // bitmap + screen + loadaddr
 
2192
                hasLoadAddr=1;
 
2193
                loadFormat=F_hires;
 
2194
                break;
 
2195
                    
 
2196
            case 10001: // multicolor
 
2197
                hasLoadAddr=0;
 
2198
                loadFormat=F_multi;
 
2199
                break;
 
2200
                    
 
2201
            case 10003: // multicolor + loadaddr
 
2202
                hasLoadAddr=1;
 
2203
                loadFormat=F_multi;
 
2204
                break;
 
2205
                    
 
2206
            default: // then we don't know what it is.
 
2207
                File_error = 1;
 
2208
 
 
2209
        }
 
2210
        
 
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
 
2213
                
 
2214
    if (file_size>9002)
 
2215
        width=160;
 
2216
                
 
2217
    if (hasLoadAddr)
 
2218
    {
 
2219
        // get load address
 
2220
        Read_byte(file,&background);
 
2221
        Read_byte(file,&background);
 
2222
        sprintf(filename,"load at $%02x00",background);
 
2223
    }
 
2224
    else
 
2225
    {
 
2226
        sprintf(filename,"no addr");
 
2227
    }
 
2228
       
 
2229
        if(file_size>9002)
 
2230
        {
 
2231
            context->Ratio = PIXEL_WIDE;
 
2232
        }
 
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
 
2236
                     
 
2237
        context->Width = width ;                
 
2238
        context->Height = height;
 
2239
                
 
2240
        Read_bytes(file,bitmap,8000);
 
2241
 
 
2242
        if (file_size>8002) 
 
2243
            Read_bytes(file,colors,1000);
 
2244
        else
 
2245
        {
 
2246
            for(i=0;i<1000;i++)
 
2247
            {
 
2248
                colors[i]=1;
 
2249
            }
 
2250
        }
 
2251
 
 
2252
        if(width==160)
 
2253
        {
 
2254
            Read_bytes(file,nybble,1000);
 
2255
            Read_byte(file,&background);
 
2256
            Load_C64_multi(context,bitmap,colors,nybble,background);
 
2257
        }
 
2258
        else
 
2259
        {
 
2260
            Load_C64_hires(context,bitmap,colors);
 
2261
        }
 
2262
        
 
2263
        File_error = 0;
 
2264
        fclose(file);
 
2265
    }
 
2266
    else
 
2267
        File_error = 1;
 
2268
}
 
2269
 
 
2270
int Save_C64_window(byte *saveWhat, byte *loadAddr)
 
2271
{
 
2272
    int button;
 
2273
    unsigned int i;
 
2274
    T_Dropdown_button *what, *addr;
 
2275
    char * what_label[] = {
 
2276
        "All",
 
2277
        "Bitmap",
 
2278
        "Screen",
 
2279
        "Color"
 
2280
    };
 
2281
    char * address_label[] = {
 
2282
        "None",
 
2283
        "$2000",
 
2284
        "$4000",
 
2285
        "$6000",
 
2286
        "$8000",
 
2287
        "$A000",
 
2288
        "$C000",
 
2289
        "$E000"
 
2290
    };
 
2291
       
 
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);
 
2295
    
 
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]);
 
2301
    
 
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]); 
 
2307
    
 
2308
    Update_window_area(0,0,Window_width,Window_height); 
 
2309
    Display_cursor();
 
2310
 
 
2311
    do
 
2312
    {
 
2313
        button = Window_clicked_button();
 
2314
        switch(button)
 
2315
        {
 
2316
            case 3: // Save what
 
2317
                *saveWhat=Window_attribute2;
 
2318
                //printf("what=%d\n",Window_attribute2);
 
2319
                break;
 
2320
            
 
2321
            case 4: // Load addr
 
2322
                *loadAddr=Window_attribute2*32;
 
2323
                //printf("addr=$%02x00 (%d)\n",loadAddr,Window_attribute2);
 
2324
                break;
 
2325
            
 
2326
            case 0: break;
 
2327
        }
 
2328
    }while(button!=1 && button!=2);
 
2329
    
 
2330
    Close_window();
 
2331
    Display_cursor();
 
2332
    return button==1;
 
2333
}
 
2334
 
 
2335
int Save_C64_hires(T_IO_Context *context, char *filename, byte saveWhat, byte loadAddr)
 
2336
{
 
2337
    int cx,cy,x,y,c1,c2=0,i,pixel,bits,pos=0;
 
2338
    word numcolors;
 
2339
    dword cusage[256];
 
2340
    byte colors[1000],bitmap[8000];
 
2341
    FILE *file;
 
2342
    
 
2343
    for(x=0;x<1000;x++)colors[x]=1; // init colormem to black/white
 
2344
  
 
2345
    for(cy=0; cy<25; cy++) // Character line, 25 lines
 
2346
    {
 
2347
        for(cx=0; cx<40; cx++) // Character column, 40 columns
 
2348
        {
 
2349
            for(i=0;i<256;i++)
 
2350
                cusage[i]=0;
 
2351
            
 
2352
            numcolors=Count_used_colors_area(cusage,cx*8,cy*8,8,8);
 
2353
            if (numcolors>2)
 
2354
            {
 
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);
 
2358
                return 1;
 
2359
            }
 
2360
            c1 = 0; c2 = 0;
 
2361
            for(i=0;i<16;i++)
 
2362
            {
 
2363
                if(cusage[i])
 
2364
                {
 
2365
                    c2=i;
 
2366
                    break;
 
2367
                }
 
2368
            }
 
2369
            c1=c2+1;
 
2370
            for(i=c2;i<16;i++)
 
2371
            {
 
2372
                if(cusage[i])
 
2373
                {
 
2374
                  c1=i;
 
2375
                }
 
2376
            }            
 
2377
            colors[cx+cy*40]=(c2<<4)|c1;
 
2378
      
 
2379
            for(y=0; y<8; y++)
 
2380
            {
 
2381
                bits=0;
 
2382
                for(x=0; x<8; x++)
 
2383
                {
 
2384
                    pixel=Get_pixel(context, x+cx*8,y+cy*8);
 
2385
                    if(pixel>15) 
 
2386
                    { 
 
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
 
2391
                        return 1;
 
2392
                    }
 
2393
                    bits=bits<<1;
 
2394
                    if (pixel==c2) bits|=1;
 
2395
                }
 
2396
                bitmap[pos++]=bits;
 
2397
                //Write_byte(file,bits&255);
 
2398
            }
 
2399
        }
 
2400
    }
 
2401
  
 
2402
    file = fopen(filename,"wb");
 
2403
  
 
2404
    if(!file)
 
2405
    {
 
2406
        Warning_message("File open failed");
 
2407
        File_error = 1;
 
2408
        return 1;
 
2409
    }
 
2410
    
 
2411
    if (loadAddr)
 
2412
    {
 
2413
        Write_byte(file,0);
 
2414
        Write_byte(file,loadAddr);
 
2415
    }
 
2416
    if (saveWhat==0 || saveWhat==1)
 
2417
        Write_bytes(file,bitmap,8000);
 
2418
    if (saveWhat==0 || saveWhat==2)
 
2419
        Write_bytes(file,colors,1000);
 
2420
    
 
2421
    fclose(file);
 
2422
    return 0;
 
2423
}
 
2424
 
 
2425
int Save_C64_multi(T_IO_Context *context, char *filename, byte saveWhat, byte loadAddr)
 
2426
{
 
2427
    /* 
 
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)
 
2433
    */
 
2434
 
 
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;
 
2438
    dword cusage[256];
 
2439
    byte i,background=0;
 
2440
    FILE *file;
 
2441
    
 
2442
    numcolors=Count_used_colors(cusage);
 
2443
  
 
2444
    count=0;
 
2445
    for(x=0;x<16;x++)
 
2446
    {
 
2447
        //printf("color %d, pixels %d\n",x,cusage[x]);
 
2448
        if(cusage[x]>count)
 
2449
        {
 
2450
            count=cusage[x];
 
2451
            background=x;
 
2452
        }
 
2453
    }
 
2454
  
 
2455
    for(cy=0; cy<25; cy++)
 
2456
    {
 
2457
        //printf("\ny:%2d ",cy);
 
2458
        for(cx=0; cx<40; cx++)
 
2459
        {
 
2460
            numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8);
 
2461
            if(numcolors>4)
 
2462
            {
 
2463
                Warning_message("More than 4 colors in 4x8");
 
2464
                // TODO hilite offending block
 
2465
                return 1;
 
2466
            }
 
2467
            color=1;
 
2468
            c[0]=background;
 
2469
            for(i=0; i<16; i++)
 
2470
            {
 
2471
                lut[i]=0;
 
2472
                if(cusage[i])
 
2473
                {
 
2474
                    if(i!=background)
 
2475
                    {
 
2476
                        lut[i]=color;
 
2477
                        c[color]=i;
 
2478
                        color++;
 
2479
                    }
 
2480
                    else
 
2481
                    {
 
2482
                        lut[i]=0;
 
2483
                    }
 
2484
                }
 
2485
            }
 
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]);
 
2490
            for(y=0;y<8;y++)
 
2491
            {
 
2492
                bits=0;
 
2493
                for(x=0;x<4;x++)
 
2494
                {                    
 
2495
                    pixel=Get_pixel(context, cx*4+x,cy*8+y);
 
2496
                    if(pixel>15) 
 
2497
                    { 
 
2498
                        Warning_message("Color above 15 used"); 
 
2499
                        // TODO hilite as in hires, you should stay to 
 
2500
                        // the fixed 16 color palette
 
2501
                        return 1;
 
2502
                    }
 
2503
                    bits=bits<<2;
 
2504
                    bits|=lut[pixel];
 
2505
        
 
2506
                }
 
2507
                //Write_byte(file,bits&255);
 
2508
                bitmap[pos++]=bits;
 
2509
            }
 
2510
        }
 
2511
    }
 
2512
  
 
2513
    file = fopen(filename,"wb");
 
2514
    
 
2515
    if(!file)
 
2516
    {
 
2517
        Warning_message("File open failed");
 
2518
        File_error = 1;
 
2519
        return 1;
 
2520
    }
 
2521
 
 
2522
    if (loadAddr)
 
2523
    {
 
2524
        Write_byte(file,0);
 
2525
        Write_byte(file,loadAddr);
 
2526
    }
 
2527
 
 
2528
    if (saveWhat==0 || saveWhat==1)
 
2529
        Write_bytes(file,bitmap,8000);
 
2530
        
 
2531
    if (saveWhat==0 || saveWhat==2)
 
2532
        Write_bytes(file,screen,1000);
 
2533
        
 
2534
    if (saveWhat==0 || saveWhat==3)
 
2535
        Write_bytes(file,nybble,1000);
 
2536
        
 
2537
    if (saveWhat==0)
 
2538
        Write_byte(file,background);
 
2539
    
 
2540
    fclose(file);
 
2541
    //printf("\nbg:%d\n",background);
 
2542
    return 0;
 
2543
}
 
2544
 
 
2545
void Save_C64(T_IO_Context * context)
 
2546
{
 
2547
    char filename[MAX_PATH_CHARACTERS];
 
2548
    static byte saveWhat=0, loadAddr=0;
 
2549
    dword numcolors,cusage[256];
 
2550
    numcolors=Count_used_colors(cusage);
 
2551
  
 
2552
    Get_full_filename(filename, context->File_name, context->File_directory);
 
2553
  
 
2554
    if (numcolors>16)
 
2555
    {
 
2556
        Warning_message("Error: Max 16 colors");
 
2557
        File_error = 1;
 
2558
        return;
 
2559
    }
 
2560
    if (((context->Width!=320) && (context->Width!=160)) || context->Height!=200)
 
2561
    {
 
2562
        Warning_message("must be 320x200 or 160x200");
 
2563
        File_error = 1;
 
2564
        return;
 
2565
    } 
 
2566
    
 
2567
    if(!Save_C64_window(&saveWhat,&loadAddr))
 
2568
    {
 
2569
        File_error = 1;
 
2570
        return;
 
2571
    }
 
2572
    //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr);
 
2573
    
 
2574
    if (context->Width==320)
 
2575
        File_error = Save_C64_hires(context,filename,saveWhat,loadAddr);
 
2576
    else
 
2577
        File_error = Save_C64_multi(context,filename,saveWhat,loadAddr);
 
2578
}
 
2579
 
 
2580
 
 
2581
// SCR (Amstrad CPC)
 
2582
 
 
2583
void Test_SCR(__attribute__((unused)) T_IO_Context * context)
 
2584
{
 
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.
 
2589
    
 
2590
    // An AMSDOS header would be a good indication but in some cases it may not
 
2591
    // be there
 
2592
}
 
2593
 
 
2594
void Load_SCR(__attribute__((unused)) T_IO_Context * context)
 
2595
{
 
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
 
2610
    // handle that.
 
2611
    
 
2612
    // All this mess enforces us to load (and unpack if needed) the file to a
 
2613
    // temporary 32k buffer before actually decoding it.
 
2614
    
 
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)
 
2619
    // 5) Close palette
 
2620
    // 6) Open the file
 
2621
    // 7) Run around the screen to untangle the pixeldata
 
2622
    // 8) Close the file
 
2623
}
 
2624
 
 
2625
void Save_SCR(T_IO_Context * context)
 
2626
{
 
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.
 
2631
    
 
2632
    unsigned char* output;
 
2633
    unsigned long outsize;
 
2634
    unsigned char r1;
 
2635
    int cpc_mode;
 
2636
    FILE* file;
 
2637
    char filename[MAX_PATH_CHARACTERS];
 
2638
 
 
2639
    Get_full_filename(filename, context->File_name, context->File_directory);
 
2640
 
 
2641
 
 
2642
    switch(Pixel_ratio)
 
2643
    {
 
2644
        case PIXEL_WIDE:
 
2645
        case PIXEL_WIDE2:
 
2646
            cpc_mode = 0;
 
2647
            break;
 
2648
        case PIXEL_TALL:
 
2649
        case PIXEL_TALL2:
 
2650
            cpc_mode = 2;
 
2651
            break;
 
2652
        default:
 
2653
            cpc_mode = 1;
 
2654
            break;
 
2655
    }
 
2656
 
 
2657
    output = raw2crtc(context->Width,context->Height,cpc_mode,7,&outsize,&r1,0,0);
 
2658
 
 
2659
    file = fopen(filename,"wb");
 
2660
    Write_bytes(file, output, outsize);
 
2661
    fclose(file);
 
2662
 
 
2663
    free (output);
 
2664
  output = NULL;
 
2665
 
 
2666
    File_error = 0;
 
2667
}