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