rnd-19981026-1
[rocksndiamonds.git] / src / files.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  files.h                                                 *
12 ***********************************************************/
13
14 #include <ctype.h>
15
16 #include "files.h"
17 #include "tools.h"
18 #include "misc.h"
19 #include "tape.h"
20 #include "joystick.h"
21
22 boolean CreateNewScoreFile()
23 {
24   int i,j,k;
25   char filename[MAX_FILENAME_LEN];
26   char empty_alias[MAX_NAMELEN];
27   FILE *file;
28
29   sprintf(filename,"%s/%s/%s",
30           level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
31
32   if (!(file=fopen(filename,"w")))
33     return(FALSE);
34
35   for(i=0;i<MAX_NAMELEN;i++)
36     empty_alias[i] = 0;
37   strncpy(empty_alias,EMPTY_ALIAS,MAX_NAMELEN-1);
38
39   fputs(SCORE_COOKIE,file);             /* Formatkennung */
40   for(i=0;i<leveldir[leveldir_nr].levels;i++)
41   {
42     for(j=0;j<MAX_SCORE_ENTRIES;j++)
43     {
44       for(k=0;k<MAX_NAMELEN;k++)
45         fputc(empty_alias[k],file);
46       fputc(0,file);
47       fputc(0,file);
48     }
49   }
50   fclose(file);
51
52   chmod(filename, SCORE_PERMS);
53   return(TRUE);
54 }
55
56
57
58 #if 0
59
60 boolean CreateNewNamesFile(int mode)
61 {
62   char filename[MAX_FILENAME_LEN];
63   FILE *file;
64
65   if (mode==PLAYER_LEVEL)
66     sprintf(filename,"%s/%s/%s",
67             level_directory,leveldir[leveldir_nr].filename,NAMES_FILENAME);
68   else
69     sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
70
71   if (!(file=fopen(filename,"w")))
72     return(FALSE);
73
74   fputs(NAMES_COOKIE,file);             /* Formatkennung */
75   fclose(file);
76
77   chmod(filename, NAMES_PERMS);
78   return(TRUE);
79 }
80
81 #endif
82
83
84 boolean LoadLevelInfo()
85 {
86   int i;
87   char filename[MAX_FILENAME_LEN];
88   char cookie[MAX_FILENAME_LEN];
89   FILE *file;
90
91   sprintf(filename,"%s/%s",level_directory,LEVDIR_FILENAME);
92
93   if (!(file=fopen(filename,"r")))
94   {
95     Error(ERR_WARN, "cannot read level info '%s'", filename);
96     return(FALSE);
97   }
98
99   fscanf(file,"%s\n",cookie);
100   if (strcmp(cookie,LEVELDIR_COOKIE))   /* ungültiges Format? */
101   {
102     Error(ERR_WARN, "wrong format of level info file");
103     fclose(file);
104     return(FALSE);
105   }
106
107   num_leveldirs = 0;
108   leveldir_nr = 0;
109   for(i=0;i<MAX_LEVDIR_ENTRIES;i++)
110   {
111     fscanf(file,"%s",leveldir[i].filename);
112     fscanf(file,"%s",leveldir[i].name);
113     fscanf(file,"%d",&leveldir[i].levels);
114     fscanf(file,"%d",&leveldir[i].readonly);
115     if (feof(file))
116       break;
117
118     num_leveldirs++;
119   }
120
121   if (!num_leveldirs)
122   {
123     Error(ERR_WARN, "empty level info '%s'", filename);
124     return(FALSE);
125   }
126
127   return(TRUE);
128 }
129
130 void LoadLevel(int level_nr)
131 {
132   int i,x,y;
133   char filename[MAX_FILENAME_LEN];
134   char cookie[MAX_FILENAME_LEN];
135   FILE *file;
136
137   sprintf(filename,"%s/%s/%d",
138           level_directory,leveldir[leveldir_nr].filename,level_nr);
139
140   if (!(file = fopen(filename,"r")))
141     Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
142   else
143   {
144     fgets(cookie,LEVEL_COOKIE_LEN,file);
145     fgetc(file);
146
147     if (strcmp(cookie,LEVEL_COOKIE))    /* ungültiges Format? */
148     {
149       Error(ERR_WARN, "wrong format of level file '%s'", filename);
150       fclose(file);
151       file = NULL;
152     }
153   }
154
155   if (file)
156   {
157     lev_fieldx = level.fieldx = fgetc(file);
158     lev_fieldy = level.fieldy = fgetc(file);
159
160     level.time          = (fgetc(file)<<8) | fgetc(file);
161     level.edelsteine    = (fgetc(file)<<8) | fgetc(file);
162     for(i=0;i<MAX_LEVNAMLEN;i++)
163       level.name[i]     = fgetc(file);
164     level.name[MAX_LEVNAMLEN-1] = 0;
165     for(i=0;i<MAX_LEVSCORE_ENTRIES;i++)
166       level.score[i]    = fgetc(file);
167     for(i=0;i<4;i++)
168       for(y=0;y<3;y++)
169         for(x=0;x<3;x++)
170           level.mampfer_inhalt[i][x][y] = fgetc(file);
171     level.tempo_amoebe  = fgetc(file);
172     level.dauer_sieb    = fgetc(file);
173     level.dauer_ablenk  = fgetc(file);
174     level.amoebe_inhalt = fgetc(file);
175
176     for(i=0;i<NUM_FREE_LVHD_BYTES;i++)  /* Rest frei / Headergröße 80 Bytes */
177       fgetc(file);
178
179     for(y=0;y<MAX_LEV_FIELDY;y++) 
180       for(x=0;x<MAX_LEV_FIELDX;x++) 
181         Feld[x][y] = Ur[x][y] = EL_ERDREICH;
182
183     for(y=0;y<lev_fieldy;y++) 
184       for(x=0;x<lev_fieldx;x++) 
185         Feld[x][y] = Ur[x][y] = fgetc(file);
186
187     fclose(file);
188
189     if (level.time<=10) /* Mindestspieldauer */
190       level.time = 10;
191   }
192   else
193   {
194     lev_fieldx = level.fieldx = STD_LEV_FIELDX;
195     lev_fieldy = level.fieldy = STD_LEV_FIELDY;
196
197     level.time          = 100;
198     level.edelsteine    = 0;
199     strncpy(level.name,"Nameless Level",MAX_LEVNAMLEN-1);
200     for(i=0;i<MAX_LEVSCORE_ENTRIES;i++)
201       level.score[i]    = 10;
202     for(i=0;i<4;i++)
203       for(y=0;y<3;y++)
204         for(x=0;x<3;x++)
205           level.mampfer_inhalt[i][x][y] = EL_FELSBROCKEN;
206     level.tempo_amoebe  = 10;
207     level.dauer_sieb    = 10;
208     level.dauer_ablenk  = 10;
209     level.amoebe_inhalt = EL_DIAMANT;
210
211     for(y=0;y<STD_LEV_FIELDY;y++) 
212       for(x=0;x<STD_LEV_FIELDX;x++) 
213         Feld[x][y] = Ur[x][y] = EL_ERDREICH;
214     Feld[0][0] = Ur[0][0] = EL_SPIELFIGUR;
215     Feld[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] =
216       Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_AUSGANG_ZU;
217   }
218 }
219
220 void LoadLevelTape(int level_nr)
221 {
222   int i;
223   char filename[MAX_FILENAME_LEN];
224   char cookie[MAX_FILENAME_LEN];
225   FILE *file;
226   boolean levelrec_10 = FALSE;
227
228 #ifndef MSDOS
229   sprintf(filename,"%s/%s/%d.tape",
230           level_directory,leveldir[leveldir_nr].filename,level_nr);
231 #else
232   sprintf(filename,"%s/%s/%d.tap",
233           level_directory,leveldir[leveldir_nr].filename,level_nr);
234 #endif
235
236   if ((file=fopen(filename,"r")))
237   {
238     fgets(cookie,LEVELREC_COOKIE_LEN,file);
239     fgetc(file);
240     if (!strcmp(cookie,LEVELREC_COOKIE_10))     /* old 1.0 tape format */
241       levelrec_10 = TRUE;
242     else if (strcmp(cookie,LEVELREC_COOKIE))    /* unknown tape format */
243     {
244       Error(ERR_WARN, "wrong format of level recording file '%s'", filename);
245       fclose(file);
246       file = NULL;
247     }
248   }
249
250   if (!file)
251     return;
252
253   tape.random_seed =
254     (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
255   tape.date =
256     (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
257   tape.length =
258     (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
259
260   tape.level_nr = level_nr;
261   tape.counter = 0;
262   tape.changed = FALSE;
263
264   tape.recording = FALSE;
265   tape.playing = FALSE;
266   tape.pausing = FALSE;
267
268   for(i=0;i<tape.length;i++)
269   {
270     int j;
271
272     if (i >= MAX_TAPELEN)
273       break;
274
275     for(j=0; j<MAX_PLAYERS; j++)
276     {
277       if (levelrec_10 && j>0)
278       {
279         tape.pos[i].action[j] = MV_NO_MOVING;
280         continue;
281       }
282       tape.pos[i].action[j] = fgetc(file);
283     }
284
285     tape.pos[i].delay = fgetc(file);
286
287     if (feof(file))
288       break;
289   }
290
291   fclose(file);
292
293   if (i != tape.length)
294     Error(ERR_WARN, "level recording file '%s' corrupted", filename);
295
296   tape.length_seconds = GetTapeLength();
297 }
298
299 void LoadScore(int level_nr)
300 {
301   int i,j;
302   char filename[MAX_FILENAME_LEN];
303   char cookie[MAX_FILENAME_LEN];
304   FILE *file;
305
306   sprintf(filename,"%s/%s/%s",
307           level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
308
309   if (!(file = fopen(filename,"r")))
310   {
311     if (!CreateNewScoreFile())
312       Error(ERR_WARN, "cannot create score file '%s'", filename);
313     else if (!(file = fopen(filename,"r"))) 
314       Error(ERR_WARN, "cannot read score for level %d", level_nr);
315   }
316
317   if (file)
318   {
319     fgets(cookie,SCORE_COOKIE_LEN,file);
320     if (strcmp(cookie,SCORE_COOKIE))    /* ungültiges Format? */
321     {
322       Error(ERR_WARN, "wrong format of score file '%s'", filename);
323       fclose(file);
324       file = NULL;
325     }
326   }
327
328   if (file)
329   {
330     fseek(file,
331           SCORE_COOKIE_LEN-1+level_nr*(MAX_SCORE_ENTRIES*(MAX_NAMELEN+2)),
332           SEEK_SET);
333     for(i=0;i<MAX_SCORE_ENTRIES;i++)
334     {
335       for(j=0;j<MAX_NAMELEN;j++)
336         highscore[i].Name[j] = fgetc(file);
337       highscore[i].Score = (fgetc(file)<<8) | fgetc(file);
338     }
339     fclose(file);
340   }
341   else
342   {
343     for(i=0;i<MAX_SCORE_ENTRIES;i++)
344     {
345       strcpy(highscore[i].Name,EMPTY_ALIAS);
346       highscore[i].Score = 0;
347     }
348   }
349 }
350
351
352
353 #if 0
354
355 void LoadPlayerInfo(int mode)
356 {
357   int i;
358   char filename[MAX_FILENAME_LEN];
359   char cookie[MAX_FILENAME_LEN];
360   FILE *file;
361   char *login_name = GetLoginName();
362   struct PlayerInfo default_player, new_player;
363   int version_10_file = FALSE;
364
365
366
367   if (mode == PLAYER_SETUP)
368     LoadSetup();
369   else if (mode == PLAYER_LEVEL)
370     LoadLevelSetup();
371
372
373
374   if (mode==PLAYER_LEVEL)
375     sprintf(filename,"%s/%s/%s",
376             level_directory,leveldir[leveldir_nr].filename,NAMES_FILENAME);
377   else
378     sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
379
380   for(i=0;i<MAX_NAMELEN;i++)
381     default_player.login_name[i] = default_player.alias_name[i] = 0;
382   strncpy(default_player.login_name,login_name,MAX_NAMELEN-1);
383   strncpy(default_player.alias_name,login_name,MAX_NAMELEN-1);
384   default_player.handicap = 0;
385   default_player.setup = DEFAULT_SETUP;
386   default_player.leveldir_nr = 0;
387   default_player.level_nr = 0;
388
389   new_player = default_player;
390
391   if (!(file = fopen(filename,"r")))
392   {
393     if (!CreateNewNamesFile(mode))
394       Error(ERR_WARN, "cannot create names file '%s'", filename);
395     else if (!(file = fopen(filename,"r"))) 
396       Error(ERR_WARN, "cannot read player information file '%s'", filename);
397   }
398
399   if (file)
400   {
401     fgets(cookie,NAMES_COOKIE_LEN,file);
402     if (!strcmp(cookie,NAMES_COOKIE_10))        /* altes Format? */
403       version_10_file = TRUE;
404     else if (strcmp(cookie,NAMES_COOKIE))       /* ungültiges Format? */
405     {
406       Error(ERR_WARN, "wrong format of names file '%s'", filename);
407       fclose(file);
408       file = NULL;
409     }
410   }
411
412   if (!file)
413   {
414     *local_player = default_player;
415     level_nr = default_player.level_nr;
416     return;
417   }
418
419   while(1)
420   {
421     for(i=0;i<MAX_NAMELEN;i++)
422       new_player.login_name[i] = fgetc(file);
423     for(i=0;i<MAX_NAMELEN;i++)
424       new_player.alias_name[i] = fgetc(file);
425     new_player.handicap = fgetc(file);
426     new_player.setup = (fgetc(file)<<8) | fgetc(file);
427     new_player.leveldir_nr = fgetc(file);
428     if (!version_10_file)
429     {
430       new_player.level_nr = fgetc(file);
431       for(i=0;i<10;i++)         /* currently unused bytes */
432         fgetc(file);
433     }
434     else
435       new_player.level_nr = new_player.handicap;
436
437     if (feof(file))             /* Spieler noch nicht in Liste enthalten */
438     {
439       new_player = default_player;
440
441       fclose(file);
442       if (!(file = fopen(filename,"a")))
443         Error(ERR_WARN, "cannot append new player to names file '%s'",
444               filename);
445       else
446       {
447         for(i=0;i<MAX_NAMELEN;i++)
448           fputc(new_player.login_name[i],file);
449         for(i=0;i<MAX_NAMELEN;i++)
450           fputc(new_player.alias_name[i],file);
451         fputc(new_player.handicap,file);
452         fputc(new_player.setup / 256,file);
453         fputc(new_player.setup % 256,file);
454         fputc(new_player.leveldir_nr,file);
455         if (!version_10_file)
456         {
457           fputc(new_player.level_nr,file);
458           for(i=0;i<10;i++)     /* currently unused bytes */
459             fputc(0,file);
460         }
461       }
462       break;
463     }
464     else                        /* prüfen, ob Spieler in Liste enthalten */
465       if (!strncmp(new_player.login_name,login_name,MAX_NAMELEN-1))
466         break;
467   }
468
469   if (mode==PLAYER_SETUP)
470   {
471     *local_player = new_player;
472     if (local_player->leveldir_nr < num_leveldirs)
473       leveldir_nr = local_player->leveldir_nr;
474     else
475       leveldir_nr = 0;
476   }
477   else
478   {
479     local_player->handicap = new_player.handicap;
480     local_player->level_nr = new_player.level_nr;
481   }
482
483   level_nr = local_player->level_nr;
484
485   if (file)
486     fclose(file);
487 }
488
489 #endif
490
491
492
493 void SaveLevel(int level_nr)
494 {
495   int i,x,y;
496   char filename[MAX_FILENAME_LEN];
497   FILE *file;
498
499   sprintf(filename,"%s/%s/%d",
500           level_directory,leveldir[leveldir_nr].filename,level_nr);
501
502   if (!(file=fopen(filename,"w")))
503   {
504     Error(ERR_WARN, "cannot save level file '%s'", filename);
505     return;
506   }
507
508   fputs(LEVEL_COOKIE,file);             /* Formatkennung */
509   fputc(0x0a,file);
510
511   fputc(level.fieldx,file);
512   fputc(level.fieldy,file);
513   fputc(level.time / 256,file);
514   fputc(level.time % 256,file);
515   fputc(level.edelsteine / 256,file);
516   fputc(level.edelsteine % 256,file);
517
518   for(i=0;i<MAX_LEVNAMLEN;i++)
519     fputc(level.name[i],file);
520   for(i=0;i<MAX_LEVSCORE_ENTRIES;i++)
521     fputc(level.score[i],file);
522   for(i=0;i<4;i++)
523     for(y=0;y<3;y++)
524       for(x=0;x<3;x++)
525         fputc(level.mampfer_inhalt[i][x][y],file);
526   fputc(level.tempo_amoebe,file);
527   fputc(level.dauer_sieb,file);
528   fputc(level.dauer_ablenk,file);
529   fputc(level.amoebe_inhalt,file);
530
531   for(i=0;i<NUM_FREE_LVHD_BYTES;i++)    /* Rest frei / Headergröße 80 Bytes */
532     fputc(0,file);
533
534   for(y=0;y<lev_fieldy;y++) 
535     for(x=0;x<lev_fieldx;x++) 
536       fputc(Ur[x][y],file);
537
538   fclose(file);
539
540   chmod(filename, LEVEL_PERMS);
541 }
542
543 void SaveLevelTape(int level_nr)
544 {
545   int i;
546   char filename[MAX_FILENAME_LEN];
547   FILE *file;
548   boolean new_tape = TRUE;
549
550 #ifndef MSDOS
551   sprintf(filename,"%s/%s/%d.tape",
552           level_directory,leveldir[leveldir_nr].filename,level_nr);
553 #else
554   sprintf(filename,"%s/%s/%d.tap",
555           level_directory,leveldir[leveldir_nr].filename,level_nr);
556 #endif
557
558   /* Testen, ob bereits eine Aufnahme existiert */
559   if ((file=fopen(filename,"r")))
560   {
561     new_tape = FALSE;
562     fclose(file);
563
564     if (!Request("Replace old tape ?",REQ_ASK))
565       return;
566   }
567
568   if (!(file=fopen(filename,"w")))
569   {
570     Error(ERR_WARN, "cannot save level recording file '%s'", filename);
571     return;
572   }
573
574   fputs(LEVELREC_COOKIE,file);          /* Formatkennung */
575   fputc(0x0a,file);
576
577   fputc((tape.random_seed >> 24) & 0xff,file);
578   fputc((tape.random_seed >> 16) & 0xff,file);
579   fputc((tape.random_seed >>  8) & 0xff,file);
580   fputc((tape.random_seed >>  0) & 0xff,file);
581
582   fputc((tape.date >>  24) & 0xff,file);
583   fputc((tape.date >>  16) & 0xff,file);
584   fputc((tape.date >>   8) & 0xff,file);
585   fputc((tape.date >>   0) & 0xff,file);
586
587   fputc((tape.length >>  24) & 0xff,file);
588   fputc((tape.length >>  16) & 0xff,file);
589   fputc((tape.length >>   8) & 0xff,file);
590   fputc((tape.length >>   0) & 0xff,file);
591
592   for(i=0;i<tape.length;i++)
593   {
594     int j;
595
596     for(j=0; j<MAX_PLAYERS; j++)
597       fputc(tape.pos[i].action[j],file);
598
599     fputc(tape.pos[i].delay,file);
600   }
601
602   fclose(file);
603
604   chmod(filename, LEVREC_PERMS);
605
606   tape.changed = FALSE;
607
608   if (new_tape)
609     Request("tape saved !",REQ_CONFIRM);
610 }
611
612 void SaveScore(int level_nr)
613 {
614   int i,j;
615   char filename[MAX_FILENAME_LEN];
616   FILE *file;
617
618   sprintf(filename,"%s/%s/%s",
619           level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
620
621   if (!(file=fopen(filename,"r+")))
622   {
623     Error(ERR_WARN, "cannot save score for level %d", level_nr);
624     return;
625   }
626
627   fseek(file,
628         SCORE_COOKIE_LEN-1+level_nr*(MAX_SCORE_ENTRIES*(MAX_NAMELEN+2)),
629         SEEK_SET);
630   for(i=0;i<MAX_SCORE_ENTRIES;i++)
631   {
632     for(j=0;j<MAX_NAMELEN;j++)
633       fputc(highscore[i].Name[j],file);
634     fputc(highscore[i].Score / 256,file);
635     fputc(highscore[i].Score % 256,file);
636   }
637   fclose(file);
638 }
639
640
641
642 #if 0
643
644 void SavePlayerInfo(int mode)
645 {
646   int i;
647   char filename[MAX_FILENAME_LEN];
648   char cookie[MAX_FILENAME_LEN];
649   FILE *file;
650   struct PlayerInfo default_player;
651   int version_10_file = FALSE;
652
653
654
655   if (mode == PLAYER_SETUP)
656     SaveSetup();
657   else if (mode == PLAYER_LEVEL)
658     SaveLevelSetup();
659
660
661
662   if (mode == PLAYER_LEVEL)
663     sprintf(filename,"%s/%s/%s",
664             level_directory,leveldir[leveldir_nr].filename,NAMES_FILENAME);
665   else
666     sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
667
668   if (!(file = fopen(filename,"r+")))
669   {
670     Error(ERR_WARN, "cannot save player information to file '%s'", filename);
671     return;
672   }
673
674   fgets(cookie,NAMES_COOKIE_LEN,file);
675   if (!strcmp(cookie,NAMES_COOKIE_10))  /* altes Format? */
676     version_10_file = TRUE;
677   else if (strcmp(cookie,NAMES_COOKIE)) /* ungültiges Format? */
678   {
679     Error(ERR_WARN, "wrong format of names file '%s'", filename);
680     fclose(file);
681     return;
682   }
683
684   while(1)
685   {
686     for(i=0;i<MAX_NAMELEN;i++)
687       default_player.login_name[i] = fgetc(file);
688     for(i=0;i<MAX_NAMELEN;i++)
689       default_player.alias_name[i] = fgetc(file);
690     default_player.handicap = fgetc(file);
691     default_player.setup = (fgetc(file)<<8) | fgetc(file);
692     default_player.leveldir_nr = fgetc(file);
693     if (!version_10_file)
694     {
695       default_player.level_nr = fgetc(file);
696       for(i=0;i<10;i++)         /* currently unused bytes */
697         fgetc(file);
698     }
699     else
700       default_player.level_nr = default_player.handicap;
701
702     if (feof(file))             /* Spieler noch nicht in Liste enthalten */
703       break;
704     else                        /* prüfen, ob Spieler in Liste enthalten */
705       if (!strncmp(default_player.login_name,
706                    local_player->login_name, MAX_NAMELEN-1))
707       {
708         fseek(file,-(2*MAX_NAMELEN+1+2+1+(version_10_file ? 0 : 11)),SEEK_CUR);
709         break;
710       }
711   }
712
713   local_player->level_nr = level_nr;
714
715   for(i=0;i<MAX_NAMELEN;i++)
716     fputc(local_player->login_name[i],file);
717   for(i=0;i<MAX_NAMELEN;i++)
718     fputc(local_player->alias_name[i],file);
719   fputc(local_player->handicap,file);
720   fputc(local_player->setup / 256,file);
721   fputc(local_player->setup % 256,file);
722   fputc(local_player->leveldir_nr,file);
723   if (!version_10_file)
724   {
725     fputc(local_player->level_nr,file);
726     for(i=0;i<10;i++)           /* currently unused bytes */
727       fputc(0,file);
728   }
729
730   fclose(file);
731 }
732
733 #endif
734
735
736
737 void LoadJoystickData()
738 {
739   int i;
740   char cookie[256];
741   FILE *file;
742
743   if (joystick_status==JOYSTICK_OFF)
744     return;
745
746 #ifndef MSDOS
747   if (!(file=fopen(JOYDAT_FILE,"r")))
748     return;
749
750   fscanf(file,"%s",cookie);
751   if (strcmp(cookie,JOYSTICK_COOKIE))   /* ungültiges Format? */
752   {
753     Error(ERR_WARN, "wrong format of joystick file '%s'", JOYDAT_FILE);
754     fclose(file);
755     return;
756   }
757
758   for(i=0;i<2;i++)
759   {
760     fscanf(file,"%s",cookie);
761     fscanf(file, "%d %d %d \n",
762            &joystick[i].xleft, &joystick[i].xmiddle, &joystick[i].xright);
763     fscanf(file, "%d %d %d \n",
764            &joystick[i].yupper, &joystick[i].ymiddle, &joystick[i].ylower);
765   }
766   fclose(file);
767
768   CheckJoystickData();
769 #else
770   load_joystick_data(JOYDAT_FILE);
771 #endif
772 }
773
774 void SaveJoystickData()
775 {
776   int i;
777   FILE *file;
778
779   if (joystick_status==JOYSTICK_OFF)
780     return;
781
782 #ifndef MSDOS
783   CheckJoystickData();
784
785   if (!(file=fopen(JOYDAT_FILE,"w")))
786   {
787     Error(ERR_WARN, "cannot save joystick calibration data to file '%s'",
788           JOYDAT_FILE);
789     return;
790   }
791
792   fprintf(file,"%s\n",JOYSTICK_COOKIE); /* Formatkennung */
793   for(i=0;i<2;i++)
794   {
795     fprintf(file,"JOYSTICK_%d_DATA\n",i);
796     fprintf(file, "%d %d %d \n",
797             joystick[i].xleft, joystick[i].xmiddle, joystick[i].xright);
798     fprintf(file, "%d %d %d \n",
799             joystick[i].yupper, joystick[i].ymiddle, joystick[i].ylower);
800   }
801   fclose(file);
802
803   chmod(JOYDAT_FILE, JOYDAT_PERMS);
804 #else
805   save_joystick_data(JOYDAT_FILE);
806 #endif
807
808 }
809
810 /* ------------------------------------------------------------------------- */
811 /* new setup functions                                                       */
812 /* ------------------------------------------------------------------------- */
813
814 #define TOKEN_STR_FILE_IDENTIFIER       "file_identifier"
815 #define TOKEN_STR_LAST_LEVEL_SERIES     "last_level_series"
816 #define TOKEN_STR_ALIAS_NAME            "alias_name"
817
818 #define TOKEN_STR_PLAYER_PREFIX         "player_"
819 #define TOKEN_VALUE_POSITION            30
820 #define TOKEN_INVALID                   -1
821 #define TOKEN_IGNORE                    -99
822
823 #define SETUP_TOKEN_ALIAS_NAME          100
824
825 #define SETUP_TOKEN_SOUND               0
826 #define SETUP_TOKEN_SOUND_LOOPS         1
827 #define SETUP_TOKEN_SOUND_MUSIC         2
828 #define SETUP_TOKEN_SOUND_SIMPLE        3
829 #define SETUP_TOKEN_TOONS               4
830 #define SETUP_TOKEN_DIRECT_DRAW         5
831 #define SETUP_TOKEN_SCROLL_DELAY        6
832 #define SETUP_TOKEN_SOFT_SCROLLING      7
833 #define SETUP_TOKEN_FADING              8
834 #define SETUP_TOKEN_AUTORECORD          9
835 #define SETUP_TOKEN_QUICK_DOORS         10
836 #define SETUP_TOKEN_USE_JOYSTICK        11
837 #define SETUP_TOKEN_JOYSTICK_NR         12
838 #define SETUP_TOKEN_JOY_SNAP            13
839 #define SETUP_TOKEN_JOY_BOMB            14
840 #define SETUP_TOKEN_KEY_LEFT            15
841 #define SETUP_TOKEN_KEY_RIGHT           16
842 #define SETUP_TOKEN_KEY_UP              17
843 #define SETUP_TOKEN_KEY_DOWN            18
844 #define SETUP_TOKEN_KEY_SNAP            19
845 #define SETUP_TOKEN_KEY_BOMB            20
846
847 #define NUM_SETUP_TOKENS                21
848
849 static struct
850 {
851   char *token, *value_true, *value_false;
852 } setup_info[] =
853 {
854   { "sound",                    "on", "off" },
855   { "repeating_sound_loops",    "on", "off" },
856   { "background_music",         "on", "off" },
857   { "simple_sound_effects",     "on", "off" },
858   { "toons",                    "on", "off" },
859   { "double_buffering",         "off", "on" },
860   { "scroll_delay",             "on", "off" },
861   { "soft_scrolling",           "on", "off" },
862   { "screen_fading",            "on", "off" },
863   { "automatic_tape_recording", "on", "off" },
864   { "quick_doors",              "on", "off" },
865
866   /* for each player: */
867   { ".use_joystick",            "true", "false" },
868   { ".joystick_device",         "second", "first" },
869   { ".joy.snap_field",          "", "" },
870   { ".joy.place_bomb",          "", "" },
871   { ".key.move_left",           "", "" },
872   { ".key.move_right",          "", "" },
873   { ".key.move_up",             "", "" },
874   { ".key.move_down",           "", "" },
875   { ".key.snap_field",          "", "" },
876   { ".key.place_bomb",          "", "" }
877 };
878
879 static char *string_tolower(char *s)
880 {
881   static char s_lower[100];
882   int i;
883
884   if (strlen(s) >= 100)
885     return s;
886
887   strcpy(s_lower, s);
888
889   for (i=0; i<strlen(s_lower); i++)
890     s_lower[i] = tolower(s_lower[i]);
891
892   return s_lower;
893 }
894
895 static int get_string_integer_value(char *s)
896 {
897   static char *number_text[][3] =
898   {
899     { "0", "zero", "null", },
900     { "1", "one", "first" },
901     { "2", "two", "second" },
902     { "3", "three", "third" },
903     { "4", "four", "fourth" },
904     { "5", "five", "fifth" },
905     { "6", "six", "sixth" },
906     { "7", "seven", "seventh" },
907     { "8", "eight", "eighth" },
908     { "9", "nine", "ninth" },
909     { "10", "ten", "tenth" },
910     { "11", "eleven", "eleventh" },
911     { "12", "twelve", "twelfth" },
912   };
913
914   int i, j;
915
916   for (i=0; i<13; i++)
917     for (j=0; j<3; j++)
918       if (strcmp(string_tolower(s), number_text[i][j]) == 0)
919         return i;
920
921   return -1;
922 }
923
924 static boolean get_string_boolean_value(char *s)
925 {
926   if (strcmp(string_tolower(s), "true") == 0 ||
927       strcmp(string_tolower(s), "yes") == 0 ||
928       strcmp(string_tolower(s), "on") == 0 ||
929       get_string_integer_value(s) == 1)
930     return TRUE;
931   else
932     return FALSE;
933 }
934
935 static char *getSetupToken(int token_nr)
936 {
937   return setup_info[token_nr].token;
938 }
939
940 static char *getSetupValue(int token_nr, boolean token_value)
941 {
942   if (token_value == TRUE)
943     return setup_info[token_nr].value_true;
944   else
945     return setup_info[token_nr].value_false;
946 }
947
948 static char *getFormattedSetupEntry(char *token, char *value)
949 {
950   int i;
951   static char entry[MAX_LINE_LEN];
952
953   sprintf(entry, "%s:", token);
954   for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
955     entry[i] = ' ';
956   entry[i] = '\0';
957
958   strcat(entry, value);
959
960   return entry;
961 }
962
963 static char *getSetupEntry(char *prefix, int token_nr, int token_value)
964 {
965   int i;
966   static char entry[MAX_LINE_LEN];
967
968   sprintf(entry, "%s%s:", prefix, getSetupToken(token_nr));
969   for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
970     entry[i] = ' ';
971   entry[i] = '\0';
972
973   strcat(entry, getSetupValue(token_nr, token_value));
974
975   return entry;
976 }
977
978 static char *getSetupEntryWithComment(char *prefix,int token_nr, KeySym keysym)
979 {
980   int i;
981   static char entry[MAX_LINE_LEN];
982   char *keyname = getKeyNameFromKeySym(keysym);
983
984   sprintf(entry, "%s%s:", prefix, getSetupToken(token_nr));
985   for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
986     entry[i] = ' ';
987   entry[i] = '\0';
988
989   strcat(entry, getX11KeyNameFromKeySym(keysym));
990   for (i=strlen(entry); i<50; i++)
991     entry[i] = ' ';
992   entry[i] = '\0';
993
994   /* add comment, if useful */
995   if (strcmp(keyname, "(undefined)") != 0 &&
996       strcmp(keyname, "(unknown)") != 0)
997   {
998     strcat(entry, "# ");
999     strcat(entry, keyname);
1000   }
1001
1002   return entry;
1003 }
1004
1005 static void freeSetupFileList(struct SetupFileList *setup_file_list)
1006 {
1007   if (!setup_file_list)
1008     return;
1009
1010   if (setup_file_list->token)
1011     free(setup_file_list->token);
1012   if (setup_file_list->value)
1013     free(setup_file_list->value);
1014   if (setup_file_list->next)
1015     freeSetupFileList(setup_file_list->next);
1016   free(setup_file_list);
1017 }
1018
1019 static struct SetupFileList *newSetupFileList(char *token, char *value)
1020 {
1021   struct SetupFileList *new = checked_malloc(sizeof(struct SetupFileList));
1022
1023   new->token = checked_malloc(strlen(token) + 1);
1024   strcpy(new->token, token);
1025
1026   new->value = checked_malloc(strlen(value) + 1);
1027   strcpy(new->value, value);
1028
1029   new->next = NULL;
1030
1031   return new;
1032 }
1033
1034 static char *getSetupFileListEntry(struct SetupFileList *setup_file_list,
1035                                    char *token)
1036 {
1037   if (!setup_file_list)
1038     return NULL;
1039
1040   if (strcmp(setup_file_list->token, token) == 0)
1041     return setup_file_list->value;
1042   else
1043     return getSetupFileListEntry(setup_file_list->next, token);
1044 }
1045
1046 boolean setSetupFileListEntry(struct SetupFileList *setup_file_list,
1047                               char *token, char *value)
1048 {
1049   if (!setup_file_list)
1050     return FALSE;
1051
1052   if (strcmp(setup_file_list->token, token) == 0)
1053   {
1054     free(setup_file_list->value);
1055     setup_file_list->value = checked_malloc(strlen(value) + 1);
1056     strcpy(setup_file_list->value, value);
1057
1058     return TRUE;
1059   }
1060   else
1061     return setSetupFileListEntry(setup_file_list->next, token, value);
1062 }
1063
1064 void updateSetupFileListEntry(struct SetupFileList *setup_file_list,
1065                               char *token, char *value)
1066 {
1067   if (!setup_file_list)
1068     return;
1069
1070   if (getSetupFileListEntry(setup_file_list, token) != NULL)
1071     setSetupFileListEntry(setup_file_list, token, value);
1072   else
1073   {
1074     struct SetupFileList *list_entry = setup_file_list;
1075
1076     while (list_entry->next)
1077       list_entry = list_entry->next;
1078
1079     list_entry->next = newSetupFileList(token, value);
1080   }
1081 }
1082
1083 #ifdef DEBUG
1084 static void printSetupFileList(struct SetupFileList *setup_file_list)
1085 {
1086   if (!setup_file_list)
1087     return;
1088
1089   printf("token: '%s'\n", setup_file_list->token);
1090   printf("value: '%s'\n", setup_file_list->value);
1091
1092   printSetupFileList(setup_file_list->next);
1093 }
1094 #endif
1095
1096 static struct SetupFileList *loadSetupFileList(char *filename)
1097 {
1098   int line_len;
1099   char line[MAX_LINE_LEN];
1100   char *token, *value, *line_ptr;
1101   struct SetupFileList *setup_file_list = newSetupFileList("", "");
1102   struct SetupFileList *first_valid_list_entry;
1103
1104
1105
1106   /*
1107   struct SetupFileList **next_entry = &setup_file_list;
1108   */
1109
1110
1111   FILE *file;
1112
1113   if (!(file = fopen(filename, "r")))
1114   {
1115     Error(ERR_WARN, "cannot open setup file '%s'", filename);
1116     return NULL;
1117   }
1118
1119   while(!feof(file))
1120   {
1121     /* read next line of input file */
1122     if (!fgets(line, MAX_LINE_LEN, file))
1123       break;
1124
1125     /* cut trailing comment or whitespace from input line */
1126     for (line_ptr = line; *line_ptr; line_ptr++)
1127     {
1128       if (*line_ptr == '#' || *line_ptr == '\n')
1129       {
1130         *line_ptr = '\0';
1131         break;
1132       }
1133     }
1134
1135     /* cut trailing whitespaces from input line */
1136     for (line_ptr = &line[strlen(line)]; line_ptr > line; line_ptr--)
1137       if ((*line_ptr == ' ' || *line_ptr == '\t') && line_ptr[1] == '\0')
1138         *line_ptr = '\0';
1139
1140     /* ignore empty lines */
1141     if (*line == '\0')
1142       continue;
1143
1144     line_len = strlen(line);
1145
1146     /* cut leading whitespaces from token */
1147     for (token = line; *token; token++)
1148       if (*token != ' ' && *token != '\t')
1149         break;
1150
1151     /* find end of token */
1152     for (line_ptr = token; *line_ptr; line_ptr++)
1153     {
1154       if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':')
1155       {
1156         *line_ptr = '\0';
1157         break;
1158       }
1159     }
1160
1161     if (line_ptr < line + line_len)
1162       value = line_ptr + 1;
1163     else
1164       value = "\0";
1165
1166     /* cut leading whitespaces from value */
1167     for (; *value; value++)
1168       if (*value != ' ' && *value != '\t')
1169         break;
1170
1171     if (*token && *value)
1172       updateSetupFileListEntry(setup_file_list, token, value);
1173
1174
1175 #if 0
1176     {
1177       /* allocate new token/value pair */
1178
1179       *next_entry = newSetupFileList(token, value);
1180       next_entry = &((*next_entry)->next);
1181     }
1182 #endif
1183
1184
1185
1186   }
1187
1188   fclose(file);
1189
1190   first_valid_list_entry = setup_file_list->next;
1191
1192   /* free empty list header */
1193   setup_file_list->next = NULL;
1194   freeSetupFileList(setup_file_list);
1195
1196   if (!first_valid_list_entry)
1197     Error(ERR_WARN, "setup file is empty");
1198
1199   return first_valid_list_entry;
1200 }
1201
1202 static void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list,
1203                                          char *identifier)
1204 {
1205   if (!setup_file_list)
1206     return;
1207
1208   if (strcmp(setup_file_list->token, TOKEN_STR_FILE_IDENTIFIER) == 0)
1209   {
1210     if (strcmp(setup_file_list->value, identifier) != 0)
1211     {
1212       Error(ERR_WARN, "setup file has wrong version");
1213       return;
1214     }
1215     else
1216       return;
1217   }
1218
1219   if (setup_file_list->next)
1220     checkSetupFileListIdentifier(setup_file_list->next, identifier);
1221   else
1222   {
1223     Error(ERR_WARN, "setup file has no version information");
1224     return;
1225   }
1226 }
1227
1228 static void decodeSetupFileList(struct SetupFileList *setup_file_list)
1229 {
1230   int i;
1231   int token_nr = TOKEN_INVALID;
1232   int player_nr = 0;
1233   char *token;
1234   char *token_value;
1235   int token_integer_value;
1236   boolean token_boolean_value;
1237   int token_player_prefix_len;
1238
1239   if (!setup_file_list)
1240     return;
1241
1242   token = setup_file_list->token;
1243   token_value = setup_file_list->value;
1244   token_integer_value = get_string_integer_value(token_value);
1245   token_boolean_value = get_string_boolean_value(token_value);
1246
1247   token_player_prefix_len = strlen(TOKEN_STR_PLAYER_PREFIX);
1248
1249   if (strncmp(token, TOKEN_STR_PLAYER_PREFIX,
1250               token_player_prefix_len) == 0)
1251   {
1252     token += token_player_prefix_len;
1253
1254     if (*token >= '0' && *token <= '9')
1255     {
1256       player_nr = ((int)(*token - '0') - 1 + MAX_PLAYERS) % MAX_PLAYERS;
1257       token++;
1258     }
1259   }
1260
1261   for (i=0; i<NUM_SETUP_TOKENS; i++)
1262   {
1263     if (strcmp(token, setup_info[i].token) == 0)
1264     {
1265       token_nr = i;
1266       break;
1267     }
1268   }
1269
1270   if (strcmp(token, TOKEN_STR_FILE_IDENTIFIER) == 0)
1271     token_nr = TOKEN_IGNORE;
1272   else if (strcmp(token, TOKEN_STR_ALIAS_NAME) == 0)
1273     token_nr = SETUP_TOKEN_ALIAS_NAME;
1274
1275   switch (token_nr)
1276   {
1277     case SETUP_TOKEN_SOUND:
1278       setup.sound_on = token_boolean_value;
1279       break;
1280     case SETUP_TOKEN_SOUND_LOOPS:
1281       setup.sound_loops_on = token_boolean_value;
1282       break;
1283     case SETUP_TOKEN_SOUND_MUSIC:
1284       setup.sound_music_on = token_boolean_value;
1285       break;
1286     case SETUP_TOKEN_SOUND_SIMPLE:
1287       setup.sound_simple_on = token_boolean_value;
1288       break;
1289     case SETUP_TOKEN_TOONS:
1290       setup.toons_on = token_boolean_value;
1291       break;
1292     case SETUP_TOKEN_DIRECT_DRAW:
1293       setup.direct_draw_on = !token_boolean_value;
1294       break;
1295     case SETUP_TOKEN_SCROLL_DELAY:
1296       setup.scroll_delay_on = token_boolean_value;
1297       break;
1298     case SETUP_TOKEN_SOFT_SCROLLING:
1299       setup.soft_scrolling_on = token_boolean_value;
1300       break;
1301     case SETUP_TOKEN_FADING:
1302       setup.fading_on = token_boolean_value;
1303       break;
1304     case SETUP_TOKEN_AUTORECORD:
1305       setup.autorecord_on = token_boolean_value;
1306       break;
1307     case SETUP_TOKEN_QUICK_DOORS:
1308       setup.quick_doors = token_boolean_value;
1309       break;
1310
1311     case SETUP_TOKEN_USE_JOYSTICK:
1312       setup.input[player_nr].use_joystick = token_boolean_value;
1313       break;
1314     case SETUP_TOKEN_JOYSTICK_NR:
1315       if (token_integer_value < 0 || token_integer_value > 1)
1316         token_integer_value = 1;
1317       setup.input[player_nr].joystick_nr = token_integer_value - 1;
1318       break;
1319     case SETUP_TOKEN_JOY_SNAP:
1320       setup.input[player_nr].joy.snap = getJoySymbolFromJoyName(token_value);
1321       break;
1322     case SETUP_TOKEN_JOY_BOMB    :
1323       setup.input[player_nr].joy.bomb = getJoySymbolFromJoyName(token_value);
1324       break;
1325     case SETUP_TOKEN_KEY_LEFT:
1326       setup.input[player_nr].key.left = getKeySymFromX11KeyName(token_value);
1327       break;
1328     case SETUP_TOKEN_KEY_RIGHT:
1329       setup.input[player_nr].key.right = getKeySymFromX11KeyName(token_value);
1330       break;
1331     case SETUP_TOKEN_KEY_UP:
1332       setup.input[player_nr].key.up = getKeySymFromX11KeyName(token_value);
1333       break;
1334     case SETUP_TOKEN_KEY_DOWN:
1335       setup.input[player_nr].key.down = getKeySymFromX11KeyName(token_value);
1336       break;
1337     case SETUP_TOKEN_KEY_SNAP:
1338       setup.input[player_nr].key.snap = getKeySymFromX11KeyName(token_value);
1339       break;
1340     case SETUP_TOKEN_KEY_BOMB:
1341       setup.input[player_nr].key.bomb = getKeySymFromX11KeyName(token_value);
1342       break;
1343
1344     case SETUP_TOKEN_ALIAS_NAME:
1345       strncpy(local_player->alias_name, token_value, MAX_NAMELEN-1);
1346       local_player->alias_name[MAX_NAMELEN-1] = '\0';
1347       break;
1348
1349     case TOKEN_INVALID:
1350       Error(ERR_WARN, "unknown token '%s' not recognized", token);
1351       break;
1352
1353     case TOKEN_IGNORE:
1354     default:
1355       break;
1356   }
1357
1358   decodeSetupFileList(setup_file_list->next);
1359 }
1360
1361 void LoadSetup()
1362 {
1363   int i;
1364   char filename[MAX_FILENAME_LEN];
1365   struct SetupFileList *setup_file_list = NULL;
1366
1367   /* always start with reliable default setup values */
1368
1369   strncpy(local_player->login_name, GetLoginName(), MAX_NAMELEN-1);
1370   local_player->login_name[MAX_NAMELEN-1] = '\0';
1371
1372   strncpy(local_player->alias_name, GetLoginName(), MAX_NAMELEN-1);
1373   local_player->alias_name[MAX_NAMELEN-1] = '\0';
1374
1375   setup.sound_on = TRUE;
1376   setup.sound_loops_on = FALSE;
1377   setup.sound_music_on = FALSE;
1378   setup.sound_simple_on = FALSE;
1379   setup.toons_on = TRUE;
1380   setup.direct_draw_on = FALSE;
1381   setup.scroll_delay_on = FALSE;
1382   setup.soft_scrolling_on = TRUE;
1383   setup.fading_on = FALSE;
1384   setup.autorecord_on = FALSE;
1385   setup.quick_doors = FALSE;
1386
1387   for (i=0; i<MAX_PLAYERS; i++)
1388   {
1389     setup.input[i].use_joystick = FALSE;
1390     setup.input[i].joystick_nr = 0;
1391     setup.input[i].joy.snap  = (i == 0 ? JOY_BUTTON_1 : 0);
1392     setup.input[i].joy.bomb  = (i == 0 ? JOY_BUTTON_2 : 0);
1393     setup.input[i].key.left  = (i == 0 ? DEFAULT_KEY_LEFT  : KEY_UNDEFINDED);
1394     setup.input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINDED);
1395     setup.input[i].key.up    = (i == 0 ? DEFAULT_KEY_UP    : KEY_UNDEFINDED);
1396     setup.input[i].key.down  = (i == 0 ? DEFAULT_KEY_DOWN  : KEY_UNDEFINDED);
1397     setup.input[i].key.snap  = (i == 0 ? DEFAULT_KEY_SNAP  : KEY_UNDEFINDED);
1398     setup.input[i].key.bomb  = (i == 0 ? DEFAULT_KEY_BOMB  : KEY_UNDEFINDED);
1399   }
1400
1401   sprintf(filename, "%s/%s", SETUP_PATH, SETUP_FILENAME);
1402
1403   setup_file_list = loadSetupFileList(filename);
1404
1405   if (setup_file_list)
1406   {
1407
1408 #if 0
1409     printSetupFileList(setup_file_list);
1410 #endif
1411
1412     checkSetupFileListIdentifier(setup_file_list, SETUP_COOKIE);
1413     decodeSetupFileList(setup_file_list);
1414
1415     freeSetupFileList(setup_file_list);
1416   }
1417   else
1418     Error(ERR_RETURN, "using default setup values");
1419 }
1420
1421 void LoadLevelSetup()
1422 {
1423   char filename[MAX_FILENAME_LEN];
1424
1425   /* always start with reliable default setup values */
1426
1427   leveldir_nr = 0;
1428   level_nr = 0;
1429
1430   sprintf(filename, "%s/%s", SETUP_PATH, LEVELSETUP_FILENAME);
1431
1432   if (level_setup_list)
1433     freeSetupFileList(level_setup_list);
1434
1435   level_setup_list = loadSetupFileList(filename);
1436
1437   if (level_setup_list)
1438   {
1439     int i;
1440
1441     char *last_level_series =
1442       getSetupFileListEntry(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES);
1443
1444     if (last_level_series)
1445     {
1446       for (i=0; i<num_leveldirs; i++)
1447       {
1448         if (strcmp(last_level_series, leveldir[i].filename) == 0)
1449         {
1450           char *token_value =
1451             getSetupFileListEntry(level_setup_list, last_level_series);
1452
1453           leveldir_nr = i;
1454
1455           if (token_value)
1456           {
1457             level_nr = atoi(token_value);
1458
1459             if (level_nr < 0)
1460               level_nr = 0;
1461             if (level_nr > leveldir[leveldir_nr].levels - 1)
1462               level_nr = leveldir[leveldir_nr].levels - 1;
1463           }
1464
1465           break;
1466         }
1467       }
1468     }
1469
1470
1471 #if 0
1472     printSetupFileList(level_setup_list);
1473 #endif
1474
1475     checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
1476   }
1477   else
1478     Error(ERR_RETURN, "using default setup values");
1479 }
1480
1481 void SaveSetup()
1482 {
1483   int i;
1484   char filename[MAX_FILENAME_LEN];
1485   FILE *file;
1486
1487   sprintf(filename, "%s/%s", SETUP_PATH, SETUP_FILENAME);
1488
1489   if (!(file = fopen(filename, "w")))
1490   {
1491     Error(ERR_WARN, "cannot write setup file '%s'", filename);
1492     return;
1493   }
1494
1495   fprintf(file, "%s:              %s\n",
1496           TOKEN_STR_FILE_IDENTIFIER, SETUP_COOKIE);
1497
1498   fprintf(file, "\n");
1499
1500   fprintf(file, "%s\n",
1501           getSetupEntry("", SETUP_TOKEN_SOUND,
1502                         setup.sound_on));
1503   fprintf(file, "%s\n",
1504           getSetupEntry("", SETUP_TOKEN_SOUND_LOOPS,
1505                         setup.sound_loops_on));
1506   fprintf(file, "%s\n",
1507           getSetupEntry("", SETUP_TOKEN_SOUND_MUSIC,
1508                         setup.sound_music_on));
1509   fprintf(file, "%s\n",
1510           getSetupEntry("", SETUP_TOKEN_SOUND_SIMPLE,
1511                         setup.sound_simple_on));
1512   fprintf(file, "%s\n",
1513           getSetupEntry("", SETUP_TOKEN_TOONS,
1514                         setup.toons_on));
1515   fprintf(file, "%s\n",
1516           getSetupEntry("", SETUP_TOKEN_DIRECT_DRAW,
1517                         setup.direct_draw_on));
1518   fprintf(file, "%s\n",
1519           getSetupEntry("", SETUP_TOKEN_SCROLL_DELAY,
1520                         setup.scroll_delay_on));
1521   fprintf(file, "%s\n",
1522           getSetupEntry("", SETUP_TOKEN_SOFT_SCROLLING,
1523                         setup.soft_scrolling_on));
1524   fprintf(file, "%s\n",
1525           getSetupEntry("", SETUP_TOKEN_FADING,
1526                         setup.fading_on));
1527   fprintf(file, "%s\n",
1528           getSetupEntry("", SETUP_TOKEN_AUTORECORD,
1529                         setup.autorecord_on));
1530   fprintf(file, "%s\n",
1531           getSetupEntry("", SETUP_TOKEN_QUICK_DOORS,
1532                         setup.quick_doors));
1533
1534   fprintf(file, "\n");
1535
1536   fprintf(file, "%s\n",
1537           getFormattedSetupEntry(TOKEN_STR_ALIAS_NAME,
1538                                  local_player->alias_name));
1539
1540   for (i=0; i<MAX_PLAYERS; i++)
1541   {
1542     char prefix[30];
1543
1544     sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, i + 1);
1545
1546     fprintf(file, "\n");
1547
1548     fprintf(file, "%s\n",
1549             getSetupEntry(prefix, SETUP_TOKEN_USE_JOYSTICK,
1550                           setup.input[i].use_joystick));
1551     fprintf(file, "%s\n",
1552             getSetupEntry(prefix, SETUP_TOKEN_JOYSTICK_NR,
1553                           setup.input[i].joystick_nr));
1554
1555     fprintf(file, "%s%s:      %s\n", prefix,
1556             getSetupToken(SETUP_TOKEN_JOY_SNAP),
1557             getJoyNameFromJoySymbol(setup.input[i].joy.snap));
1558     fprintf(file, "%s%s:      %s\n", prefix,
1559             getSetupToken(SETUP_TOKEN_JOY_BOMB),
1560             getJoyNameFromJoySymbol(setup.input[i].joy.bomb));
1561
1562     fprintf(file, "%s\n",
1563             getSetupEntryWithComment(prefix, SETUP_TOKEN_KEY_LEFT,
1564                                      setup.input[i].key.left));
1565     fprintf(file, "%s\n",
1566             getSetupEntryWithComment(prefix, SETUP_TOKEN_KEY_RIGHT,
1567                                      setup.input[i].key.right));
1568     fprintf(file, "%s\n",
1569             getSetupEntryWithComment(prefix, SETUP_TOKEN_KEY_UP,
1570                                      setup.input[i].key.up));
1571     fprintf(file, "%s\n",
1572             getSetupEntryWithComment(prefix, SETUP_TOKEN_KEY_DOWN,
1573                                      setup.input[i].key.down));
1574     fprintf(file, "%s\n",
1575             getSetupEntryWithComment(prefix, SETUP_TOKEN_KEY_SNAP,
1576                                      setup.input[i].key.snap));
1577     fprintf(file, "%s\n",
1578             getSetupEntryWithComment(prefix, SETUP_TOKEN_KEY_BOMB,
1579                                      setup.input[i].key.bomb));
1580   }
1581
1582   fclose(file);
1583
1584   chmod(filename, SETUP_PERMS);
1585 }
1586
1587 void SaveLevelSetup()
1588 {
1589   char filename[MAX_FILENAME_LEN];
1590   struct SetupFileList *list_entry = level_setup_list;
1591   FILE *file;
1592
1593   updateSetupFileListEntry(level_setup_list,
1594                            TOKEN_STR_LAST_LEVEL_SERIES,
1595                            leveldir[leveldir_nr].filename);
1596
1597   updateSetupFileListEntry(level_setup_list,
1598                            leveldir[leveldir_nr].filename,
1599                            int2str(level_nr, 0));
1600
1601   sprintf(filename, "%s/%s", SETUP_PATH, LEVELSETUP_FILENAME);
1602
1603   if (!(file = fopen(filename, "w")))
1604   {
1605     Error(ERR_WARN, "cannot write setup file '%s'", filename);
1606     return;
1607   }
1608
1609   fprintf(file, "%s:              %s\n\n",
1610           TOKEN_STR_FILE_IDENTIFIER, LEVELSETUP_COOKIE);
1611
1612   while (list_entry)
1613   {
1614     if (strcmp(list_entry->token, TOKEN_STR_FILE_IDENTIFIER) != 0)
1615       fprintf(file, "%s\n",
1616               getFormattedSetupEntry(list_entry->token, list_entry->value));
1617
1618     /* just to make things nicer :) */
1619     if (strcmp(list_entry->token, TOKEN_STR_LAST_LEVEL_SERIES) == 0)
1620       fprintf(file, "\n");
1621
1622     list_entry = list_entry->next;
1623   }
1624
1625   fclose(file);
1626
1627   chmod(filename, SETUP_PERMS);
1628 }