1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
22 boolean LoadLevelInfo()
25 char filename[MAX_FILENAME_LEN];
26 char cookie[MAX_FILENAME_LEN];
29 sprintf(filename,"%s/%s",level_directory,LEVDIR_FILENAME);
31 if (!(file=fopen(filename,"r")))
33 Error(ERR_WARN, "cannot read level info '%s'", filename);
37 fscanf(file,"%s\n",cookie);
38 if (strcmp(cookie,LEVELDIR_COOKIE)) /* ungültiges Format? */
40 Error(ERR_WARN, "wrong format of level info file");
47 for(i=0;i<MAX_LEVDIR_ENTRIES;i++)
49 fscanf(file,"%s",leveldir[i].filename);
50 fscanf(file,"%s",leveldir[i].name);
51 fscanf(file,"%d",&leveldir[i].levels);
52 fscanf(file,"%d",&leveldir[i].readonly);
61 Error(ERR_WARN, "empty level info '%s'", filename);
68 void LoadLevel(int level_nr)
71 char filename[MAX_FILENAME_LEN];
72 char cookie[MAX_FILENAME_LEN];
75 sprintf(filename,"%s/%s/%d",
76 level_directory,leveldir[leveldir_nr].filename,level_nr);
78 if (!(file = fopen(filename,"r")))
79 Error(ERR_WARN, "cannot read level '%s' - creating new level", filename);
82 fgets(cookie,LEVEL_COOKIE_LEN,file);
85 if (strcmp(cookie,LEVEL_COOKIE)) /* ungültiges Format? */
87 Error(ERR_WARN, "wrong format of level file '%s'", filename);
95 lev_fieldx = level.fieldx = fgetc(file);
96 lev_fieldy = level.fieldy = fgetc(file);
98 level.time = (fgetc(file)<<8) | fgetc(file);
99 level.edelsteine = (fgetc(file)<<8) | fgetc(file);
100 for(i=0;i<MAX_LEVNAMLEN;i++)
101 level.name[i] = fgetc(file);
102 level.name[MAX_LEVNAMLEN-1] = 0;
103 for(i=0;i<MAX_LEVSCORE_ENTRIES;i++)
104 level.score[i] = fgetc(file);
108 level.mampfer_inhalt[i][x][y] = fgetc(file);
109 level.tempo_amoebe = fgetc(file);
110 level.dauer_sieb = fgetc(file);
111 level.dauer_ablenk = fgetc(file);
112 level.amoebe_inhalt = fgetc(file);
114 for(i=0;i<NUM_FREE_LVHD_BYTES;i++) /* Rest frei / Headergröße 80 Bytes */
117 for(y=0;y<MAX_LEV_FIELDY;y++)
118 for(x=0;x<MAX_LEV_FIELDX;x++)
119 Feld[x][y] = Ur[x][y] = EL_ERDREICH;
121 for(y=0;y<lev_fieldy;y++)
122 for(x=0;x<lev_fieldx;x++)
123 Feld[x][y] = Ur[x][y] = fgetc(file);
127 if (level.time<=10) /* Mindestspieldauer */
132 lev_fieldx = level.fieldx = STD_LEV_FIELDX;
133 lev_fieldy = level.fieldy = STD_LEV_FIELDY;
136 level.edelsteine = 0;
137 strncpy(level.name,"Nameless Level",MAX_LEVNAMLEN-1);
138 for(i=0;i<MAX_LEVSCORE_ENTRIES;i++)
143 level.mampfer_inhalt[i][x][y] = EL_FELSBROCKEN;
144 level.tempo_amoebe = 10;
145 level.dauer_sieb = 10;
146 level.dauer_ablenk = 10;
147 level.amoebe_inhalt = EL_DIAMANT;
149 for(y=0;y<STD_LEV_FIELDY;y++)
150 for(x=0;x<STD_LEV_FIELDX;x++)
151 Feld[x][y] = Ur[x][y] = EL_ERDREICH;
152 Feld[0][0] = Ur[0][0] = EL_SPIELFIGUR;
153 Feld[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] =
154 Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_AUSGANG_ZU;
158 void SaveLevel(int level_nr)
161 char filename[MAX_FILENAME_LEN];
164 sprintf(filename,"%s/%s/%d",
165 level_directory,leveldir[leveldir_nr].filename,level_nr);
167 if (!(file=fopen(filename,"w")))
169 Error(ERR_WARN, "cannot save level file '%s'", filename);
173 fputs(LEVEL_COOKIE,file); /* Formatkennung */
176 fputc(level.fieldx,file);
177 fputc(level.fieldy,file);
178 fputc(level.time / 256,file);
179 fputc(level.time % 256,file);
180 fputc(level.edelsteine / 256,file);
181 fputc(level.edelsteine % 256,file);
183 for(i=0;i<MAX_LEVNAMLEN;i++)
184 fputc(level.name[i],file);
185 for(i=0;i<MAX_LEVSCORE_ENTRIES;i++)
186 fputc(level.score[i],file);
190 fputc(level.mampfer_inhalt[i][x][y],file);
191 fputc(level.tempo_amoebe,file);
192 fputc(level.dauer_sieb,file);
193 fputc(level.dauer_ablenk,file);
194 fputc(level.amoebe_inhalt,file);
196 for(i=0;i<NUM_FREE_LVHD_BYTES;i++) /* Rest frei / Headergröße 80 Bytes */
199 for(y=0;y<lev_fieldy;y++)
200 for(x=0;x<lev_fieldx;x++)
201 fputc(Ur[x][y],file);
205 chmod(filename, LEVEL_PERMS);
208 void LoadLevelTape(int level_nr)
211 char filename[MAX_FILENAME_LEN];
212 char cookie[MAX_FILENAME_LEN];
214 boolean levelrec_10 = FALSE;
217 sprintf(filename,"%s/%s/%d.tape",
218 level_directory,leveldir[leveldir_nr].filename,level_nr);
220 sprintf(filename,"%s/%s/%d.tap",
221 level_directory,leveldir[leveldir_nr].filename,level_nr);
224 if ((file=fopen(filename,"r")))
226 fgets(cookie,LEVELREC_COOKIE_LEN,file);
228 if (!strcmp(cookie,LEVELREC_COOKIE_10)) /* old 1.0 tape format */
230 else if (strcmp(cookie,LEVELREC_COOKIE)) /* unknown tape format */
232 Error(ERR_WARN, "wrong format of level recording file '%s'", filename);
242 (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
244 (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
246 (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
248 tape.level_nr = level_nr;
250 tape.changed = FALSE;
252 tape.recording = FALSE;
253 tape.playing = FALSE;
254 tape.pausing = FALSE;
256 for(i=0;i<tape.length;i++)
260 if (i >= MAX_TAPELEN)
263 for(j=0; j<MAX_PLAYERS; j++)
265 if (levelrec_10 && j > 0)
267 tape.pos[i].action[j] = MV_NO_MOVING;
270 tape.pos[i].action[j] = fgetc(file);
273 tape.pos[i].delay = fgetc(file);
277 /* eliminate possible diagonal moves in old tapes */
278 /* this is only for backward compatibility */
280 byte joy_dir[4] = { JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN };
281 byte action = tape.pos[i].action[0];
282 int k, num_moves = 0;
286 if (action & joy_dir[k])
288 tape.pos[i + num_moves].action[0] = joy_dir[k];
290 tape.pos[i + num_moves].delay = 0;
299 tape.length += num_moves;
309 if (i != tape.length)
310 Error(ERR_WARN, "level recording file '%s' corrupted", filename);
312 tape.length_seconds = GetTapeLength();
315 void SaveLevelTape(int level_nr)
318 char filename[MAX_FILENAME_LEN];
320 boolean new_tape = TRUE;
323 sprintf(filename,"%s/%s/%d.tape",
324 level_directory,leveldir[leveldir_nr].filename,level_nr);
326 sprintf(filename,"%s/%s/%d.tap",
327 level_directory,leveldir[leveldir_nr].filename,level_nr);
330 /* Testen, ob bereits eine Aufnahme existiert */
331 if ((file=fopen(filename,"r")))
336 if (!Request("Replace old tape ?",REQ_ASK))
340 if (!(file=fopen(filename,"w")))
342 Error(ERR_WARN, "cannot save level recording file '%s'", filename);
346 fputs(LEVELREC_COOKIE,file); /* Formatkennung */
349 fputc((tape.random_seed >> 24) & 0xff,file);
350 fputc((tape.random_seed >> 16) & 0xff,file);
351 fputc((tape.random_seed >> 8) & 0xff,file);
352 fputc((tape.random_seed >> 0) & 0xff,file);
354 fputc((tape.date >> 24) & 0xff,file);
355 fputc((tape.date >> 16) & 0xff,file);
356 fputc((tape.date >> 8) & 0xff,file);
357 fputc((tape.date >> 0) & 0xff,file);
359 fputc((tape.length >> 24) & 0xff,file);
360 fputc((tape.length >> 16) & 0xff,file);
361 fputc((tape.length >> 8) & 0xff,file);
362 fputc((tape.length >> 0) & 0xff,file);
364 for(i=0;i<tape.length;i++)
368 for(j=0; j<MAX_PLAYERS; j++)
369 fputc(tape.pos[i].action[j],file);
371 fputc(tape.pos[i].delay,file);
376 chmod(filename, LEVREC_PERMS);
378 tape.changed = FALSE;
381 Request("tape saved !",REQ_CONFIRM);
384 boolean CreateNewScoreFile()
387 char filename[MAX_FILENAME_LEN];
388 char empty_alias[MAX_NAMELEN];
391 sprintf(filename,"%s/%s/%s",
392 level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
394 if (!(file=fopen(filename,"w")))
397 for(i=0;i<MAX_NAMELEN;i++)
399 strncpy(empty_alias,EMPTY_ALIAS,MAX_NAMELEN-1);
401 fputs(SCORE_COOKIE,file); /* Formatkennung */
402 for(i=0;i<leveldir[leveldir_nr].levels;i++)
404 for(j=0;j<MAX_SCORE_ENTRIES;j++)
406 for(k=0;k<MAX_NAMELEN;k++)
407 fputc(empty_alias[k],file);
414 chmod(filename, SCORE_PERMS);
418 void LoadScore(int level_nr)
421 char filename[MAX_FILENAME_LEN];
422 char cookie[MAX_FILENAME_LEN];
425 sprintf(filename,"%s/%s/%s",
426 level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
428 if (!(file = fopen(filename,"r")))
430 if (!CreateNewScoreFile())
431 Error(ERR_WARN, "cannot create score file '%s'", filename);
432 else if (!(file = fopen(filename,"r")))
433 Error(ERR_WARN, "cannot read score for level %d", level_nr);
438 fgets(cookie,SCORE_COOKIE_LEN,file);
439 if (strcmp(cookie,SCORE_COOKIE)) /* ungültiges Format? */
441 Error(ERR_WARN, "wrong format of score file '%s'", filename);
450 SCORE_COOKIE_LEN-1+level_nr*(MAX_SCORE_ENTRIES*(MAX_NAMELEN+2)),
452 for(i=0;i<MAX_SCORE_ENTRIES;i++)
454 for(j=0;j<MAX_NAMELEN;j++)
455 highscore[i].Name[j] = fgetc(file);
456 highscore[i].Score = (fgetc(file)<<8) | fgetc(file);
462 for(i=0;i<MAX_SCORE_ENTRIES;i++)
464 strcpy(highscore[i].Name,EMPTY_ALIAS);
465 highscore[i].Score = 0;
470 void SaveScore(int level_nr)
473 char filename[MAX_FILENAME_LEN];
476 sprintf(filename,"%s/%s/%s",
477 level_directory,leveldir[leveldir_nr].filename,SCORE_FILENAME);
479 if (!(file=fopen(filename,"r+")))
481 Error(ERR_WARN, "cannot save score for level %d", level_nr);
486 SCORE_COOKIE_LEN-1+level_nr*(MAX_SCORE_ENTRIES*(MAX_NAMELEN+2)),
488 for(i=0;i<MAX_SCORE_ENTRIES;i++)
490 for(j=0;j<MAX_NAMELEN;j++)
491 fputc(highscore[i].Name[j],file);
492 fputc(highscore[i].Score / 256,file);
493 fputc(highscore[i].Score % 256,file);
498 #define MAX_LINE_LEN 1000
500 #define TOKEN_STR_FILE_IDENTIFIER "file_identifier"
501 #define TOKEN_STR_LAST_LEVEL_SERIES "last_level_series"
502 #define TOKEN_STR_PLAYER_PREFIX "player_"
504 #define TOKEN_VALUE_POSITION 30
506 #define SETUP_TOKEN_SOUND 0
507 #define SETUP_TOKEN_SOUND_LOOPS 1
508 #define SETUP_TOKEN_SOUND_MUSIC 2
509 #define SETUP_TOKEN_SOUND_SIMPLE 3
510 #define SETUP_TOKEN_TOONS 4
511 #define SETUP_TOKEN_DOUBLE_BUFFERING 5
512 #define SETUP_TOKEN_SCROLL_DELAY 6
513 #define SETUP_TOKEN_SOFT_SCROLLING 7
514 #define SETUP_TOKEN_FADING 8
515 #define SETUP_TOKEN_AUTORECORD 9
516 #define SETUP_TOKEN_QUICK_DOORS 10
517 #define SETUP_TOKEN_TEAM_MODE 11
518 #define SETUP_TOKEN_ALIAS_NAME 12
520 #define SETUP_TOKEN_USE_JOYSTICK 13
521 #define SETUP_TOKEN_JOY_DEVICE_NAME 14
522 #define SETUP_TOKEN_JOY_XLEFT 15
523 #define SETUP_TOKEN_JOY_XMIDDLE 16
524 #define SETUP_TOKEN_JOY_XRIGHT 17
525 #define SETUP_TOKEN_JOY_YUPPER 18
526 #define SETUP_TOKEN_JOY_YMIDDLE 19
527 #define SETUP_TOKEN_JOY_YLOWER 20
528 #define SETUP_TOKEN_JOY_SNAP 21
529 #define SETUP_TOKEN_JOY_BOMB 22
530 #define SETUP_TOKEN_KEY_LEFT 23
531 #define SETUP_TOKEN_KEY_RIGHT 24
532 #define SETUP_TOKEN_KEY_UP 25
533 #define SETUP_TOKEN_KEY_DOWN 26
534 #define SETUP_TOKEN_KEY_SNAP 27
535 #define SETUP_TOKEN_KEY_BOMB 28
537 #define NUM_SETUP_TOKENS 29
539 #define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_SOUND
540 #define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_ALIAS_NAME
542 #define FIRST_PLAYER_SETUP_TOKEN SETUP_TOKEN_USE_JOYSTICK
543 #define LAST_PLAYER_SETUP_TOKEN SETUP_TOKEN_KEY_BOMB
545 #define TYPE_BOOLEAN 1
546 #define TYPE_SWITCH 2
547 #define TYPE_KEYSYM 3
548 #define TYPE_INTEGER 4
549 #define TYPE_STRING 5
551 static struct SetupInfo si;
552 static struct SetupInputInfo sii;
560 { TYPE_SWITCH, &si.sound, "sound" },
561 { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" },
562 { TYPE_SWITCH, &si.sound_music, "background_music" },
563 { TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" },
564 { TYPE_SWITCH, &si.toons, "toons" },
565 { TYPE_SWITCH, &si.double_buffering, "double_buffering" },
566 { TYPE_SWITCH, &si.scroll_delay, "scroll_delay" },
567 { TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" },
568 { TYPE_SWITCH, &si.fading, "screen_fading" },
569 { TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" },
570 { TYPE_SWITCH, &si.quick_doors, "quick_doors" },
571 { TYPE_SWITCH, &si.team_mode, "team_mode" },
572 { TYPE_STRING, &si.alias_name, "alias_name" },
574 /* for each player: */
575 { TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" },
576 { TYPE_STRING, &sii.joy.device_name, ".joy.device_name" },
577 { TYPE_INTEGER, &sii.joy.xleft, ".joy.xleft" },
578 { TYPE_INTEGER, &sii.joy.xmiddle, ".joy.xmiddle" },
579 { TYPE_INTEGER, &sii.joy.xright, ".joy.xright" },
580 { TYPE_INTEGER, &sii.joy.yupper, ".joy.yupper" },
581 { TYPE_INTEGER, &sii.joy.ymiddle, ".joy.ymiddle" },
582 { TYPE_INTEGER, &sii.joy.ylower, ".joy.ylower" },
583 { TYPE_INTEGER, &sii.joy.snap, ".joy.snap_field" },
584 { TYPE_INTEGER, &sii.joy.bomb, ".joy.place_bomb" },
585 { TYPE_KEYSYM, &sii.key.left, ".key.move_left" },
586 { TYPE_KEYSYM, &sii.key.right, ".key.move_right" },
587 { TYPE_KEYSYM, &sii.key.up, ".key.move_up" },
588 { TYPE_KEYSYM, &sii.key.down, ".key.move_down" },
589 { TYPE_KEYSYM, &sii.key.snap, ".key.snap_field" },
590 { TYPE_KEYSYM, &sii.key.bomb, ".key.place_bomb" }
593 static char *string_tolower(char *s)
595 static char s_lower[100];
598 if (strlen(s) >= 100)
603 for (i=0; i<strlen(s_lower); i++)
604 s_lower[i] = tolower(s_lower[i]);
609 static int get_string_integer_value(char *s)
611 static char *number_text[][3] =
613 { "0", "zero", "null", },
614 { "1", "one", "first" },
615 { "2", "two", "second" },
616 { "3", "three", "third" },
617 { "4", "four", "fourth" },
618 { "5", "five", "fifth" },
619 { "6", "six", "sixth" },
620 { "7", "seven", "seventh" },
621 { "8", "eight", "eighth" },
622 { "9", "nine", "ninth" },
623 { "10", "ten", "tenth" },
624 { "11", "eleven", "eleventh" },
625 { "12", "twelve", "twelfth" },
632 if (strcmp(string_tolower(s), number_text[i][j]) == 0)
638 static boolean get_string_boolean_value(char *s)
640 if (strcmp(string_tolower(s), "true") == 0 ||
641 strcmp(string_tolower(s), "yes") == 0 ||
642 strcmp(string_tolower(s), "on") == 0 ||
643 get_string_integer_value(s) == 1)
649 static char *getFormattedSetupEntry(char *token, char *value)
652 static char entry[MAX_LINE_LEN];
654 sprintf(entry, "%s:", token);
655 for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
659 strcat(entry, value);
664 static void freeSetupFileList(struct SetupFileList *setup_file_list)
666 if (!setup_file_list)
669 if (setup_file_list->token)
670 free(setup_file_list->token);
671 if (setup_file_list->value)
672 free(setup_file_list->value);
673 if (setup_file_list->next)
674 freeSetupFileList(setup_file_list->next);
675 free(setup_file_list);
678 static struct SetupFileList *newSetupFileList(char *token, char *value)
680 struct SetupFileList *new = checked_malloc(sizeof(struct SetupFileList));
682 new->token = checked_malloc(strlen(token) + 1);
683 strcpy(new->token, token);
685 new->value = checked_malloc(strlen(value) + 1);
686 strcpy(new->value, value);
693 static char *getTokenValue(struct SetupFileList *setup_file_list,
696 if (!setup_file_list)
699 if (strcmp(setup_file_list->token, token) == 0)
700 return setup_file_list->value;
702 return getTokenValue(setup_file_list->next, token);
705 static void setTokenValue(struct SetupFileList *setup_file_list,
706 char *token, char *value)
708 if (!setup_file_list)
711 if (strcmp(setup_file_list->token, token) == 0)
713 free(setup_file_list->value);
714 setup_file_list->value = checked_malloc(strlen(value) + 1);
715 strcpy(setup_file_list->value, value);
717 else if (setup_file_list->next == NULL)
718 setup_file_list->next = newSetupFileList(token, value);
720 setTokenValue(setup_file_list->next, token, value);
724 static void printSetupFileList(struct SetupFileList *setup_file_list)
726 if (!setup_file_list)
729 printf("token: '%s'\n", setup_file_list->token);
730 printf("value: '%s'\n", setup_file_list->value);
732 printSetupFileList(setup_file_list->next);
736 static struct SetupFileList *loadSetupFileList(char *filename)
739 char line[MAX_LINE_LEN];
740 char *token, *value, *line_ptr;
741 struct SetupFileList *setup_file_list = newSetupFileList("", "");
742 struct SetupFileList *first_valid_list_entry;
746 if (!(file = fopen(filename, "r")))
748 Error(ERR_WARN, "cannot open setup file '%s'", filename);
754 /* read next line of input file */
755 if (!fgets(line, MAX_LINE_LEN, file))
758 /* cut trailing comment or whitespace from input line */
759 for (line_ptr = line; *line_ptr; line_ptr++)
761 if (*line_ptr == '#' || *line_ptr == '\n')
768 /* cut trailing whitespaces from input line */
769 for (line_ptr = &line[strlen(line)]; line_ptr > line; line_ptr--)
770 if ((*line_ptr == ' ' || *line_ptr == '\t') && line_ptr[1] == '\0')
773 /* ignore empty lines */
777 line_len = strlen(line);
779 /* cut leading whitespaces from token */
780 for (token = line; *token; token++)
781 if (*token != ' ' && *token != '\t')
784 /* find end of token */
785 for (line_ptr = token; *line_ptr; line_ptr++)
787 if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':')
794 if (line_ptr < line + line_len)
795 value = line_ptr + 1;
799 /* cut leading whitespaces from value */
800 for (; *value; value++)
801 if (*value != ' ' && *value != '\t')
804 if (*token && *value)
805 setTokenValue(setup_file_list, token, value);
810 first_valid_list_entry = setup_file_list->next;
812 /* free empty list header */
813 setup_file_list->next = NULL;
814 freeSetupFileList(setup_file_list);
816 if (!first_valid_list_entry)
817 Error(ERR_WARN, "setup file is empty");
819 return first_valid_list_entry;
822 static void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list,
825 if (!setup_file_list)
828 if (strcmp(setup_file_list->token, TOKEN_STR_FILE_IDENTIFIER) == 0)
830 if (strcmp(setup_file_list->value, identifier) != 0)
832 Error(ERR_WARN, "setup file has wrong version");
839 if (setup_file_list->next)
840 checkSetupFileListIdentifier(setup_file_list->next, identifier);
843 Error(ERR_WARN, "setup file has no version information");
848 static void setSetupInfoToDefaults(struct SetupInfo *si)
853 si->sound_loops = FALSE;
854 si->sound_music = FALSE;
855 si->sound_simple = FALSE;
857 si->double_buffering = TRUE;
858 si->direct_draw = !si->double_buffering;
859 si->scroll_delay = FALSE;
860 si->soft_scrolling = TRUE;
862 si->autorecord = FALSE;
863 si->quick_doors = FALSE;
865 strncpy(si->login_name, GetLoginName(), MAX_NAMELEN-1);
866 si->login_name[MAX_NAMELEN-1] = '\0';
867 strncpy(si->alias_name, GetLoginName(), MAX_NAMELEN-1);
868 si->alias_name[MAX_NAMELEN-1] = '\0';
870 for (i=0; i<MAX_PLAYERS; i++)
872 si->input[i].use_joystick = FALSE;
873 strcpy(si->input[i].joy.device_name, joystick_device_name[i]);
874 si->input[i].joy.xleft = JOYSTICK_XLEFT;
875 si->input[i].joy.xmiddle = JOYSTICK_XMIDDLE;
876 si->input[i].joy.xright = JOYSTICK_XRIGHT;
877 si->input[i].joy.yupper = JOYSTICK_YUPPER;
878 si->input[i].joy.ymiddle = JOYSTICK_YMIDDLE;
879 si->input[i].joy.ylower = JOYSTICK_YLOWER;
880 si->input[i].joy.snap = (i == 0 ? JOY_BUTTON_1 : 0);
881 si->input[i].joy.bomb = (i == 0 ? JOY_BUTTON_2 : 0);
882 si->input[i].key.left = (i == 0 ? DEFAULT_KEY_LEFT : KEY_UNDEFINDED);
883 si->input[i].key.right = (i == 0 ? DEFAULT_KEY_RIGHT : KEY_UNDEFINDED);
884 si->input[i].key.up = (i == 0 ? DEFAULT_KEY_UP : KEY_UNDEFINDED);
885 si->input[i].key.down = (i == 0 ? DEFAULT_KEY_DOWN : KEY_UNDEFINDED);
886 si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KEY_UNDEFINDED);
887 si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KEY_UNDEFINDED);
891 static void setSetupInfo(int token_nr, char *token_value)
893 int token_type = token_info[token_nr].type;
894 void *setup_value = token_info[token_nr].value;
896 if (token_value == NULL)
899 /* set setup field to corresponding token value */
904 *(boolean *)setup_value = get_string_boolean_value(token_value);
908 *(KeySym *)setup_value = getKeySymFromX11KeyName(token_value);
912 *(int *)setup_value = get_string_integer_value(token_value);
916 strcpy((char *)setup_value, token_value);
924 static void decodeSetupFileList(struct SetupFileList *setup_file_list)
928 if (!setup_file_list)
931 /* handle global setup values */
933 for (i=FIRST_GLOBAL_SETUP_TOKEN; i<=LAST_GLOBAL_SETUP_TOKEN; i++)
934 setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text));
937 /* handle player specific setup values */
938 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
942 sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1);
944 sii = setup.input[pnr];
945 for (i=FIRST_PLAYER_SETUP_TOKEN; i<=LAST_PLAYER_SETUP_TOKEN; i++)
947 char full_token[100];
949 sprintf(full_token, "%s%s", prefix, token_info[i].text);
950 setSetupInfo(i, getTokenValue(setup_file_list, full_token));
952 setup.input[pnr] = sii;
956 int getLevelSeriesNrFromLevelSeriesName(char *level_series_name)
960 if (!level_series_name)
963 for (i=0; i<num_leveldirs; i++)
964 if (strcmp(level_series_name, leveldir[i].filename) == 0)
970 int getLastPlayedLevelOfLevelSeries(char *level_series_name)
973 int level_series_nr = getLevelSeriesNrFromLevelSeriesName(level_series_name);
974 int last_level_nr = 0;
976 if (!level_series_name)
979 token_value = getTokenValue(level_setup_list, level_series_name);
983 int highest_level_nr = leveldir[level_series_nr].levels - 1;
985 last_level_nr = atoi(token_value);
987 if (last_level_nr < 0)
989 if (last_level_nr > highest_level_nr)
990 last_level_nr = highest_level_nr;
993 return last_level_nr;
998 char filename[MAX_FILENAME_LEN];
999 struct SetupFileList *setup_file_list = NULL;
1001 /* always start with reliable default setup values */
1002 setSetupInfoToDefaults(&setup);
1004 sprintf(filename, "%s/%s", SETUP_PATH, SETUP_FILENAME);
1006 setup_file_list = loadSetupFileList(filename);
1008 if (setup_file_list)
1010 checkSetupFileListIdentifier(setup_file_list, SETUP_COOKIE);
1011 decodeSetupFileList(setup_file_list);
1013 setup.direct_draw = !setup.double_buffering;
1015 freeSetupFileList(setup_file_list);
1018 Error(ERR_WARN, "using default setup values");
1021 static char *getSetupLine(char *prefix, int token_nr)
1024 static char entry[MAX_LINE_LEN];
1025 int token_type = token_info[token_nr].type;
1026 void *setup_value = token_info[token_nr].value;
1027 char *token_text = token_info[token_nr].text;
1029 /* start with the prefix, token and some spaces to format output line */
1030 sprintf(entry, "%s%s:", prefix, token_text);
1031 for (i=strlen(entry); i<TOKEN_VALUE_POSITION; i++)
1034 /* continue with the token's value (which can have different types) */
1038 strcat(entry, (*(boolean *)setup_value ? "true" : "false"));
1042 strcat(entry, (*(boolean *)setup_value ? "on" : "off"));
1047 KeySym keysym = *(KeySym *)setup_value;
1048 char *keyname = getKeyNameFromKeySym(keysym);
1050 strcat(entry, getX11KeyNameFromKeySym(keysym));
1051 for (i=strlen(entry); i<50; i++)
1054 /* add comment, if useful */
1055 if (strcmp(keyname, "(undefined)") != 0 &&
1056 strcmp(keyname, "(unknown)") != 0)
1058 strcat(entry, "# ");
1059 strcat(entry, keyname);
1066 char buffer[MAX_LINE_LEN];
1068 sprintf(buffer, "%d", *(int *)setup_value);
1069 strcat(entry, buffer);
1074 strcat(entry, (char *)setup_value);
1087 char filename[MAX_FILENAME_LEN];
1090 sprintf(filename, "%s/%s", SETUP_PATH, SETUP_FILENAME);
1092 if (!(file = fopen(filename, "w")))
1094 Error(ERR_WARN, "cannot write setup file '%s'", filename);
1098 fprintf(file, "%s\n",
1099 getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, SETUP_COOKIE));
1100 fprintf(file, "\n");
1102 /* handle global setup values */
1104 for (i=FIRST_GLOBAL_SETUP_TOKEN; i<=LAST_GLOBAL_SETUP_TOKEN; i++)
1106 /* just to make things nicer :) */
1107 if (i == SETUP_TOKEN_ALIAS_NAME)
1108 fprintf(file, "\n");
1110 fprintf(file, "%s\n", getSetupLine("", i));
1113 /* handle player specific setup values */
1114 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
1118 sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1);
1119 fprintf(file, "\n");
1121 sii = setup.input[pnr];
1122 for (i=FIRST_PLAYER_SETUP_TOKEN; i<=LAST_PLAYER_SETUP_TOKEN; i++)
1123 fprintf(file, "%s\n", getSetupLine(prefix, i));
1128 chmod(filename, SETUP_PERMS);
1131 void LoadLevelSetup()
1133 char filename[MAX_FILENAME_LEN];
1135 /* always start with reliable default setup values */
1140 sprintf(filename, "%s/%s", SETUP_PATH, LEVELSETUP_FILENAME);
1142 if (level_setup_list)
1143 freeSetupFileList(level_setup_list);
1145 level_setup_list = loadSetupFileList(filename);
1147 if (level_setup_list)
1149 char *last_level_series =
1150 getTokenValue(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES);
1152 leveldir_nr = getLevelSeriesNrFromLevelSeriesName(last_level_series);
1153 level_nr = getLastPlayedLevelOfLevelSeries(last_level_series);
1155 checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
1158 Error(ERR_WARN, "using default setup values");
1161 void SaveLevelSetup()
1163 char filename[MAX_FILENAME_LEN];
1164 struct SetupFileList *list_entry = level_setup_list;
1167 setTokenValue(level_setup_list,
1168 TOKEN_STR_LAST_LEVEL_SERIES, leveldir[leveldir_nr].filename);
1170 setTokenValue(level_setup_list,
1171 leveldir[leveldir_nr].filename, int2str(level_nr, 0));
1173 sprintf(filename, "%s/%s", SETUP_PATH, LEVELSETUP_FILENAME);
1175 if (!(file = fopen(filename, "w")))
1177 Error(ERR_WARN, "cannot write setup file '%s'", filename);
1181 fprintf(file, "%s: %s\n\n",
1182 TOKEN_STR_FILE_IDENTIFIER, LEVELSETUP_COOKIE);
1186 if (strcmp(list_entry->token, TOKEN_STR_FILE_IDENTIFIER) != 0)
1187 fprintf(file, "%s\n",
1188 getFormattedSetupEntry(list_entry->token, list_entry->value));
1190 /* just to make things nicer :) */
1191 if (strcmp(list_entry->token, TOKEN_STR_LAST_LEVEL_SERIES) == 0)
1192 fprintf(file, "\n");
1194 list_entry = list_entry->next;
1199 chmod(filename, SETUP_PERMS);