X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=19f536d9f2498e18bdbe9ca11b36211757fb37ba;hb=aacdd16335c68a011fab047272b828792a2a884e;hp=a453554b856f9cde652bf1a25e1c9837f17f7be3;hpb=1a8dede2cb67e1800ba2fa26182883920da1b160;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index a453554b..19f536d9 100644 --- a/src/files.c +++ b/src/files.c @@ -17,6 +17,7 @@ #include "libgame/libgame.h" #include "files.h" +#include "init.h" #include "tools.h" #include "tape.h" @@ -44,7 +45,7 @@ static void setLevelInfoToDefaults() { - int i, x, y; + int i, j, x, y; level.file_version = FILE_VERSION_ACTUAL; level.game_version = GAME_VERSION_ACTUAL; @@ -83,19 +84,46 @@ static void setLevelInfoToDefaults() for(i=0; iscore[i] = fgetc(file); - level->num_yam_contents = STD_ELEMENT_CONTENTS; + level->num_yamyam_contents = STD_ELEMENT_CONTENTS; for(i=0; iyam_content[i][x][y] = checkLevelElement(fgetc(file)); + level->yamyam_content[i][x][y] = checkLevelElement(fgetc(file)); level->amoeba_speed = fgetc(file); level->time_magic_wall = fgetc(file); @@ -255,19 +283,19 @@ static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level) } fgetc(file); - level->num_yam_contents = fgetc(file); + level->num_yamyam_contents = fgetc(file); fgetc(file); fgetc(file); /* correct invalid number of content fields -- should never happen */ - if (level->num_yam_contents < 1 || - level->num_yam_contents > MAX_ELEMENT_CONTENTS) - level->num_yam_contents = STD_ELEMENT_CONTENTS; + if (level->num_yamyam_contents < 1 || + level->num_yamyam_contents > MAX_ELEMENT_CONTENTS) + level->num_yamyam_contents = STD_ELEMENT_CONTENTS; for(i=0; iyam_content[i][x][y] = + level->yamyam_content[i][x][y] = checkLevelElement(level->encoding_16bit_field ? getFile16BitBE(file) : fgetc(file)); return chunk_size; @@ -297,12 +325,12 @@ static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level) if (element == EL_YAMYAM) { - level->num_yam_contents = num_contents; + level->num_yamyam_contents = num_contents; for(i=0; iyam_content[i][x][y] = content_array[i][x][y]; + level->yamyam_content[i][x][y] = content_array[i][x][y]; } else if (element == EL_BD_AMOEBA) { @@ -334,7 +362,33 @@ static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level) int properties = getFile32BitBE(file); if (IS_CUSTOM_ELEMENT(element)) - Properties1[element] = properties; + Properties[element][EP_BITFIELD_BASE] = properties; + else + Error(ERR_WARN, "invalid custom element number %d", element); + } + + return chunk_size; +} + +static int LoadLevel_CUS2(FILE *file, int chunk_size, struct LevelInfo *level) +{ + int num_changed_custom_elements = getFile16BitBE(file); + int chunk_size_expected = 2 + num_changed_custom_elements * 4; + int i; + + if (chunk_size_expected != chunk_size) + { + ReadUnusedBytesFromFile(file, chunk_size - 2); + return chunk_size_expected; + } + + for (i=0; i < num_changed_custom_elements; i++) + { + int element = getFile16BitBE(file); + int custom_element_successor = getFile16BitBE(file); + + if (IS_CUSTOM_ELEMENT(element)) + element_info[element].change.successor = custom_element_successor; else Error(ERR_WARN, "invalid custom element number %d", element); } @@ -421,6 +475,7 @@ void LoadLevelFromFilename(char *filename) { "CONT", -1, LoadLevel_CONT }, { "CNT2", LEVEL_CHUNK_CNT2_SIZE, LoadLevel_CNT2 }, { "CUS1", -1, LoadLevel_CUS1 }, + { "CUS2", -1, LoadLevel_CUS2 }, { NULL, 0, NULL } }; @@ -515,6 +570,32 @@ void LoadLevelFromFilename(char *filename) level.em_slippery_gems = TRUE; } + /* map some elements which have changed in newer versions */ + if (level.game_version <= VERSION_IDENT(2,2,0)) + { + int x, y; + + /* map game font elements */ + for(y=0; yencoding_16bit_yamyam ? EL_EMPTY : - level->yam_content[i][x][y]), + level->yamyam_content[i][x][y]), file); fputc(level->amoeba_speed, file); fputc(level->time_magic_wall, file); @@ -593,7 +675,7 @@ static void SaveLevel_CONT(FILE *file, struct LevelInfo *level) int i, x, y; fputc(EL_YAMYAM, file); - fputc(level->num_yam_contents, file); + fputc(level->num_yamyam_contents, file); fputc(0, file); fputc(0, file); @@ -601,9 +683,9 @@ static void SaveLevel_CONT(FILE *file, struct LevelInfo *level) for(y=0; y<3; y++) for(x=0; x<3; x++) if (level->encoding_16bit_field) - putFile16BitBE(file, level->yam_content[i][x][y]); + putFile16BitBE(file, level->yamyam_content[i][x][y]); else - fputc(level->yam_content[i][x][y], file); + fputc(level->yamyam_content[i][x][y], file); } #endif @@ -615,14 +697,14 @@ static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element) if (element == EL_YAMYAM) { - num_contents = level->num_yam_contents; + num_contents = level->num_yamyam_contents; content_xsize = 3; content_ysize = 3; for(i=0; iyam_content[i][x][y]; + content_array[i][x][y] = level->yamyam_content[i][x][y]; } else if (element == EL_BD_AMOEBA) { @@ -658,7 +740,8 @@ static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element) putFile16BitBE(file, content_array[i][x][y]); } -static void SaveLevel_CUS1(FILE *file, int num_changed_custom_elements) +static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level, + int num_changed_custom_elements) { int i, check = 0; @@ -668,12 +751,12 @@ static void SaveLevel_CUS1(FILE *file, int num_changed_custom_elements) { int element = EL_CUSTOM_START + i; - if (Properties1[element] != EP_BITMASK_DEFAULT) + if (Properties[element][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT) { if (check < num_changed_custom_elements) { putFile16BitBE(file, element); - putFile32BitBE(file, Properties1[element]); + putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]); } check++; @@ -684,11 +767,39 @@ static void SaveLevel_CUS1(FILE *file, int num_changed_custom_elements) Error(ERR_WARN, "inconsistent number of custom element properties"); } +static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level, + int num_changed_custom_elements) +{ + int i, check = 0; + + putFile16BitBE(file, num_changed_custom_elements); + + for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) + { + int element = EL_CUSTOM_START + i; + + if (element_info[element].change.successor != EL_EMPTY_SPACE) + { + if (check < num_changed_custom_elements) + { + putFile16BitBE(file, element); + putFile16BitBE(file, element_info[element].change.successor); + } + + check++; + } + } + + if (check != num_changed_custom_elements) /* should not happen */ + Error(ERR_WARN, "inconsistent number of custom element successors"); +} + void SaveLevel(int level_nr) { char *filename = getLevelFilename(level_nr); int body_chunk_size; - int num_changed_custom_elements = 0; + int num_changed_custom_elements1 = 0; + int num_changed_custom_elements2 = 0; int i, x, y; FILE *file; @@ -710,10 +821,10 @@ void SaveLevel(int level_nr) /* check yamyam content for 16-bit elements */ level.encoding_16bit_yamyam = FALSE; - for(i=0; i 255) + if (level.yamyam_content[i][x][y] > 255) level.encoding_16bit_yamyam = TRUE; /* check amoeba content for 16-bit elements */ @@ -727,8 +838,13 @@ void SaveLevel(int level_nr) /* check for non-standard custom elements and calculate "CUS1" chunk size */ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) - if (Properties1[EL_CUSTOM_START + i] != EP_BITMASK_DEFAULT) - num_changed_custom_elements++; + if (Properties[EL_CUSTOM_START +i][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT) + num_changed_custom_elements1++; + + /* check for non-standard custom elements and calculate "CUS2" chunk size */ + for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) + if (element_info[EL_CUSTOM_START + i].change.successor != EL_EMPTY_SPACE) + num_changed_custom_elements2++; putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED); putFileChunkBE(file, "CAVE", CHUNK_SIZE_NONE); @@ -746,7 +862,7 @@ void SaveLevel(int level_nr) SaveLevel_BODY(file, &level); if (level.encoding_16bit_yamyam || - level.num_yam_contents != STD_ELEMENT_CONTENTS) + level.num_yamyam_contents != STD_ELEMENT_CONTENTS) { putFileChunkBE(file, "CNT2", LEVEL_CHUNK_CNT2_SIZE); SaveLevel_CNT2(file, &level, EL_YAMYAM); @@ -758,10 +874,16 @@ void SaveLevel(int level_nr) SaveLevel_CNT2(file, &level, EL_BD_AMOEBA); } - if (num_changed_custom_elements > 0) + if (num_changed_custom_elements1 > 0) { - putFileChunkBE(file, "CUS1", 2 + num_changed_custom_elements * 6); - SaveLevel_CUS1(file, num_changed_custom_elements); + putFileChunkBE(file, "CUS1", 2 + num_changed_custom_elements1 * 6); + SaveLevel_CUS1(file, &level, num_changed_custom_elements1); + } + + if (num_changed_custom_elements2 > 0) + { + putFileChunkBE(file, "CUS2", 2 + num_changed_custom_elements2 * 4); + SaveLevel_CUS2(file, &level, num_changed_custom_elements2); } fclose(file); @@ -772,7 +894,7 @@ void SaveLevel(int level_nr) void DumpLevel(struct LevelInfo *level) { printf_line("-", 79); - printf("Level xxx (file version %06d, game version %06d)\n", + printf("Level xxx (file version %08d, game version %08d)\n", level->file_version, level->game_version); printf_line("-", 79); @@ -872,6 +994,26 @@ static int LoadTape_HEAD(FILE *file, int chunk_size, struct TapeInfo *tape) return chunk_size; } +static int LoadTape_INFO(FILE *file, int chunk_size, struct TapeInfo *tape) +{ + int level_identifier_size; + int i; + + level_identifier_size = getFile16BitBE(file); + + tape->level_identifier = + checked_realloc(tape->level_identifier, level_identifier_size); + + for(i=0; i < level_identifier_size; i++) + tape->level_identifier[i] = fgetc(file); + + tape->level_nr = getFile16BitBE(file); + + chunk_size = 2 + level_identifier_size + 2; + + return chunk_size; +} + static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape) { int i, j; @@ -1025,6 +1167,7 @@ void LoadTapeFromFilename(char *filename) { { "VERS", FILE_VERS_CHUNK_SIZE, LoadTape_VERS }, { "HEAD", TAPE_HEADER_SIZE, LoadTape_HEAD }, + { "INFO", -1, LoadTape_INFO }, { "BODY", -1, LoadTape_BODY }, { NULL, 0, NULL } }; @@ -1071,6 +1214,10 @@ void LoadTapeFromFilename(char *filename) fclose(file); tape.length_seconds = GetTapeLength(); + +#if 0 + printf("tape version: %d\n", tape.game_version); +#endif } void LoadTape(int level_nr) @@ -1108,6 +1255,19 @@ static void SaveTape_HEAD(FILE *file, struct TapeInfo *tape) putFileVersion(file, tape->engine_version); } +static void SaveTape_INFO(FILE *file, struct TapeInfo *tape) +{ + int level_identifier_size = strlen(tape->level_identifier) + 1; + int i; + + putFile16BitBE(file, level_identifier_size); + + for(i=0; i < level_identifier_size; i++) + fputc(tape->level_identifier[i], file); + + putFile16BitBE(file, tape->level_nr); +} + static void SaveTape_BODY(FILE *file, struct TapeInfo *tape) { int i, j; @@ -1124,12 +1284,13 @@ static void SaveTape_BODY(FILE *file, struct TapeInfo *tape) void SaveTape(int level_nr) { - int i; char *filename = getTapeFilename(level_nr); FILE *file; boolean new_tape = TRUE; int num_participating_players = 0; + int info_chunk_size; int body_chunk_size; + int i; InitTapeDirectory(leveldir_current->filename); @@ -1155,6 +1316,7 @@ void SaveTape(int level_nr) if (tape.player_participates[i]) num_participating_players++; + info_chunk_size = 2 + (strlen(tape.level_identifier) + 1) + 2; body_chunk_size = (num_participating_players + 1) * tape.length; putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED); @@ -1166,6 +1328,9 @@ void SaveTape(int level_nr) putFileChunkBE(file, "HEAD", TAPE_HEADER_SIZE); SaveTape_HEAD(file, &tape); + putFileChunkBE(file, "INFO", info_chunk_size); + SaveTape_INFO(file, &tape); + putFileChunkBE(file, "BODY", body_chunk_size); SaveTape_BODY(file, &tape); @@ -1190,8 +1355,9 @@ void DumpTape(struct TapeInfo *tape) } printf_line("-", 79); - printf("Tape of Level %03d (file version %06d, game version %06d)\n", + printf("Tape of Level %03d (file version %08d, game version %08d)\n", tape->level_nr, tape->file_version, tape->game_version); + printf("Level series identifier: '%s'\n", tape->level_identifier); printf_line("-", 79); for(i=0; ilength; i++) @@ -1379,14 +1545,27 @@ void SaveScore(int level_nr) #define NUM_PLAYER_SETUP_TOKENS 16 +/* system setup */ +#define SETUP_TOKEN_SYSTEM_SDL_AUDIODRIVER 0 +#define SETUP_TOKEN_SYSTEM_AUDIO_FRAGMENT_SIZE 1 + +#define NUM_SYSTEM_SETUP_TOKENS 2 + +/* options setup */ +#define SETUP_TOKEN_OPTIONS_VERBOSE 0 + +#define NUM_OPTIONS_SETUP_TOKENS 1 + + static struct SetupInfo si; static struct SetupEditorInfo sei; static struct SetupShortcutInfo ssi; static struct SetupInputInfo sii; +static struct SetupSystemInfo syi; +static struct OptionInfo soi; static struct TokenInfo global_setup_tokens[] = { - /* global setup */ { TYPE_STRING, &si.player_name, "player_name" }, { TYPE_SWITCH, &si.sound, "sound" }, { TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" }, @@ -1413,7 +1592,6 @@ static struct TokenInfo global_setup_tokens[] = static struct TokenInfo editor_setup_tokens[] = { - /* shortcut setup */ { TYPE_SWITCH, &sei.el_boulderdash, "editor.el_boulderdash" }, { TYPE_SWITCH, &sei.el_emerald_mine, "editor.el_emerald_mine" }, { TYPE_SWITCH, &sei.el_more, "editor.el_more" }, @@ -1427,7 +1605,6 @@ static struct TokenInfo editor_setup_tokens[] = static struct TokenInfo shortcut_setup_tokens[] = { - /* shortcut setup */ { TYPE_KEY_X11, &ssi.save_game, "shortcut.save_game" }, { TYPE_KEY_X11, &ssi.load_game, "shortcut.load_game" }, { TYPE_KEY_X11, &ssi.toggle_pause, "shortcut.toggle_pause" } @@ -1435,7 +1612,6 @@ static struct TokenInfo shortcut_setup_tokens[] = static struct TokenInfo player_setup_tokens[] = { - /* player setup */ { TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" }, { TYPE_STRING, &sii.joy.device_name, ".joy.device_name" }, { TYPE_INTEGER, &sii.joy.xleft, ".joy.xleft" }, @@ -1454,11 +1630,37 @@ static struct TokenInfo player_setup_tokens[] = { TYPE_KEY_X11, &sii.key.bomb, ".key.place_bomb" } }; +static struct TokenInfo system_setup_tokens[] = +{ + { TYPE_STRING, &syi.sdl_audiodriver, "system.sdl_audiodriver" }, + { TYPE_INTEGER, &syi.audio_fragment_size,"system.audio_fragment_size" } +}; + +static struct TokenInfo options_setup_tokens[] = +{ + { TYPE_BOOLEAN, &soi.verbose, "options.verbose" } +}; + +static char *get_corrected_login_name(char *login_name) +{ + /* needed because player name must be a fixed length string */ + char *login_name_new = checked_malloc(MAX_PLAYER_NAME_LEN + 1); + + strncpy(login_name_new, login_name, MAX_PLAYER_NAME_LEN); + login_name_new[MAX_PLAYER_NAME_LEN] = '\0'; + + if (strlen(login_name) > MAX_PLAYER_NAME_LEN) /* name has been cut */ + if (strchr(login_name_new, ' ')) + *strchr(login_name_new, ' ') = '\0'; + + return login_name_new; +} + static void setSetupInfoToDefaults(struct SetupInfo *si) { int i; - si->player_name = getStringCopy(getLoginName()); + si->player_name = get_corrected_login_name(getLoginName()); si->sound = TRUE; si->sound_loops = TRUE; @@ -1493,7 +1695,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->editor.el_diamond_caves = TRUE; si->editor.el_dx_boulderdash = TRUE; si->editor.el_chars = TRUE; - si->editor.el_custom = FALSE; + si->editor.el_custom = TRUE; si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME; si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME; @@ -1518,34 +1720,39 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->input[i].key.snap = (i == 0 ? DEFAULT_KEY_SNAP : KSYM_UNDEFINED); si->input[i].key.bomb = (i == 0 ? DEFAULT_KEY_BOMB : KSYM_UNDEFINED); } + + si->system.sdl_audiodriver = getStringCopy(ARG_DEFAULT); + si->system.audio_fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE; + + si->options.verbose = FALSE; } -static void decodeSetupFileList(struct SetupFileList *setup_file_list) +static void decodeSetupFileHash(SetupFileHash *setup_file_hash) { int i, pnr; - if (!setup_file_list) + if (!setup_file_hash) return; /* global setup */ si = setup; for (i=0; i MAX_PLAYER_NAME_LEN) - setup.player_name[MAX_PLAYER_NAME_LEN] = '\0'; - else if (strlen(setup.player_name) < MAX_PLAYER_NAME_LEN) - { - char *new_name = checked_malloc(MAX_PLAYER_NAME_LEN + 1); - - strcpy(new_name, setup.player_name); - free(setup.player_name); - setup.player_name = new_name; - } + player_name_new = get_corrected_login_name(setup.player_name); + free(setup.player_name); + setup.player_name = player_name_new; } else Error(ERR_WARN, "using default setup values"); @@ -1658,6 +1874,18 @@ void SaveSetup() fprintf(file, "%s\n", getSetupLine(player_setup_tokens, prefix, i)); } + /* system setup */ + syi = setup.system; + fprintf(file, "\n"); + for (i=0; i