X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=a2efae2a1874ceacf48a4210c472ebcbe193e867;hb=bd4bc1bc76940bd91ecfbf7d01790c0433ab19e2;hp=11eba8f4b95dd2c3cd72b620d64c9ae8e388381e;hpb=91b5e8017245999d9f72b5cd8089597eb827666e;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 11eba8f4..a2efae2a 100644 --- a/src/files.c +++ b/src/files.c @@ -51,6 +51,7 @@ // (element number only) #define LEVEL_CHUNK_GRPX_UNCHANGED 2 +#define LEVEL_CHUNK_EMPX_UNCHANGED 2 #define LEVEL_CHUNK_NOTE_UNCHANGED 2 // (nothing at all if unchanged) @@ -1376,6 +1377,26 @@ static struct LevelFileConfigInfo chunk_config_GRPX[] = } }; +static struct LevelFileConfigInfo chunk_config_EMPX[] = +{ + { + -1, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(1), + &xx_ei.use_gfx_element, FALSE + }, + { + -1, -1, + TYPE_ELEMENT, CONF_VALUE_16_BIT(1), + &xx_ei.gfx_element_initial, EL_EMPTY_SPACE + }, + + { + -1, -1, + -1, -1, + NULL, -1 + } +}; + static struct LevelFileConfigInfo chunk_config_CONF[] = // (OBSOLETE) { { @@ -1893,6 +1914,16 @@ static void setLevelInfoToDefaults_Elements(struct LevelInfo *level) *group = xx_group; } + + if (IS_EMPTY_ELEMENT(element) || + IS_INTERNAL_ELEMENT(element)) + { + xx_ei = *ei; // copy element data into temporary buffer + + setConfigToDefaultsFromConfigList(chunk_config_EMPX); + + *ei = xx_ei; + } } clipboard_elements_initialized = TRUE; @@ -2814,8 +2845,9 @@ static int LoadLevel_CUS3(File *file, int chunk_size, struct LevelInfo *level) for (x = 0; x < 3; x++) ei->content.e[x][y] = getMappedElement(getFile16BitBE(file)); + // bits 0 - 31 of "has_event[]" event_bits = getFile32BitBE(file); - for (j = 0; j < NUM_CHANGE_EVENTS; j++) + for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++) if (event_bits & (1 << j)) ei->change->has_event[j] = TRUE; @@ -3371,6 +3403,30 @@ static int LoadLevel_GRPX(File *file, int chunk_size, struct LevelInfo *level) return real_chunk_size; } +static int LoadLevel_EMPX(File *file, int chunk_size, struct LevelInfo *level) +{ + int element = getMappedElement(getFile16BitBE(file)); + int real_chunk_size = 2; + struct ElementInfo *ei = &element_info[element]; + + xx_ei = *ei; // copy element data into temporary buffer + + while (!checkEndOfFile(file)) + { + real_chunk_size += LoadLevel_MicroChunk(file, chunk_config_EMPX, + -1, element); + + if (real_chunk_size >= chunk_size) + break; + } + + *ei = xx_ei; + + level->file_has_custom_elements = TRUE; + + return real_chunk_size; +} + static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, struct LevelFileInfo *level_file_info, boolean level_info_only) @@ -3493,6 +3549,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { "NOTE", -1, LoadLevel_NOTE }, { "CUSX", -1, LoadLevel_CUSX }, { "GRPX", -1, LoadLevel_GRPX }, + { "EMPX", -1, LoadLevel_EMPX }, { NULL, 0, NULL } }; @@ -7537,6 +7594,22 @@ static int SaveLevel_GRPX(FILE *file, struct LevelInfo *level, int element) return chunk_size; } +static int SaveLevel_EMPX(FILE *file, struct LevelInfo *level, int element) +{ + struct ElementInfo *ei = &element_info[element]; + int chunk_size = 0; + int i; + + chunk_size += putFile16BitBE(file, element); + + xx_ei = *ei; // copy element data into temporary buffer + + for (i = 0; chunk_config_EMPX[i].data_type != -1; i++) + chunk_size += SaveLevel_MicroChunk(file, &chunk_config_EMPX[i], FALSE); + + return chunk_size; +} + static void SaveLevelFromFilename(struct LevelInfo *level, char *filename, boolean save_as_template) { @@ -7628,6 +7701,18 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename, SaveLevel_GRPX(file, level, element); } } + + for (i = 0; i < NUM_EMPTY_ELEMENTS_ALL; i++) + { + int element = GET_EMPTY_ELEMENT(i); + + chunk_size = SaveLevel_EMPX(NULL, level, element); + if (chunk_size > LEVEL_CHUNK_EMPX_UNCHANGED) // save if changed + { + putFileChunkBE(file, "EMPX", chunk_size); + SaveLevel_EMPX(file, level, element); + } + } } fclose(file); @@ -8401,7 +8486,7 @@ void SaveScoreTape(int nr) char *filename = getScoreTapeFilename(tape.score_tape_basename, nr); // used instead of "leveldir_current->subdir" (for network games) - InitScoreDirectory(levelset.identifier); + InitScoreTapeDirectory(levelset.identifier, nr); SaveTapeExt(filename); } @@ -8565,6 +8650,13 @@ static void setScoreInfoToDefaultsExt(struct ScoreInfo *scores) strcpy(scores->entry[i].name, EMPTY_PLAYER_NAME); scores->entry[i].score = 0; scores->entry[i].time = 0; + + scores->entry[i].id = -1; + strcpy(scores->entry[i].tape_date, UNKNOWN_NAME); + strcpy(scores->entry[i].platform, UNKNOWN_NAME); + strcpy(scores->entry[i].version, UNKNOWN_NAME); + strcpy(scores->entry[i].country_name, UNKNOWN_NAME); + strcpy(scores->entry[i].country_code, "??"); } scores->num_entries = 0; @@ -8720,6 +8812,18 @@ static int LoadScore_SCOR(File *file, int chunk_size, struct ScoreInfo *scores) return chunk_size; } +static int LoadScore_SC4R(File *file, int chunk_size, struct ScoreInfo *scores) +{ + int i; + + for (i = 0; i < scores->num_entries; i++) + scores->entry[i].score = getFile32BitBE(file); + + chunk_size = scores->num_entries * 4; + + return chunk_size; +} + static int LoadScore_TIME(File *file, int chunk_size, struct ScoreInfo *scores) { int i; @@ -8821,6 +8925,7 @@ void LoadScore(int nr) { "INFO", -1, LoadScore_INFO }, { "NAME", -1, LoadScore_NAME }, { "SCOR", -1, LoadScore_SCOR }, + { "SC4R", -1, LoadScore_SC4R }, { "TIME", -1, LoadScore_TIME }, { "TAPE", -1, LoadScore_TAPE }, @@ -8940,6 +9045,14 @@ static void SaveScore_SCOR(FILE *file, struct ScoreInfo *scores) putFile16BitBE(file, scores->entry[i].score); } +static void SaveScore_SC4R(FILE *file, struct ScoreInfo *scores) +{ + int i; + + for (i = 0; i < scores->num_entries; i++) + putFile32BitBE(file, scores->entry[i].score); +} + static void SaveScore_TIME(FILE *file, struct ScoreInfo *scores) { int i; @@ -8967,8 +9080,11 @@ static void SaveScoreToFilename(char *filename) int info_chunk_size; int name_chunk_size; int scor_chunk_size; + int sc4r_chunk_size; int time_chunk_size; int tape_chunk_size; + boolean has_large_score_values; + int i; if (!(file = fopen(filename, MODE_WRITE))) { @@ -8980,9 +9096,15 @@ static void SaveScoreToFilename(char *filename) info_chunk_size = 2 + (strlen(scores.level_identifier) + 1) + 2 + 2; name_chunk_size = scores.num_entries * MAX_PLAYER_NAME_LEN; scor_chunk_size = scores.num_entries * 2; + sc4r_chunk_size = scores.num_entries * 4; time_chunk_size = scores.num_entries * 4; tape_chunk_size = scores.num_entries * MAX_SCORE_TAPE_BASENAME_LEN; + has_large_score_values = FALSE; + for (i = 0; i < scores.num_entries; i++) + if (scores.entry[i].score > 0xffff) + has_large_score_values = TRUE; + putFileChunkBE(file, "RND1", CHUNK_SIZE_UNDEFINED); putFileChunkBE(file, "SCOR", CHUNK_SIZE_NONE); @@ -8995,8 +9117,16 @@ static void SaveScoreToFilename(char *filename) putFileChunkBE(file, "NAME", name_chunk_size); SaveScore_NAME(file, &scores); - putFileChunkBE(file, "SCOR", scor_chunk_size); - SaveScore_SCOR(file, &scores); + if (has_large_score_values) + { + putFileChunkBE(file, "SC4R", sc4r_chunk_size); + SaveScore_SC4R(file, &scores); + } + else + { + putFileChunkBE(file, "SCOR", scor_chunk_size); + SaveScore_SCOR(file, &scores); + } putFileChunkBE(file, "TIME", time_chunk_size); SaveScore_TIME(file, &scores); @@ -9114,20 +9244,28 @@ static boolean SetRequest_ApiGetScore(struct HttpRequest *request, request->method = API_SERVER_METHOD; request->uri = API_SERVER_URI_GET; + char *levelset_identifier = getEscapedJSON(leveldir_current->identifier); + char *levelset_name = getEscapedJSON(leveldir_current->name); + snprintf(request->body, MAX_HTTP_BODY_SIZE, "{\n" "%s" " \"game_version\": \"%s\",\n" " \"game_platform\": \"%s\",\n" " \"levelset_identifier\": \"%s\",\n" + " \"levelset_name\": \"%s\",\n" " \"level_nr\": \"%d\"\n" "}\n", getPasswordJSON(setup.api_server_password), getProgramRealVersionString(), getProgramPlatformString(), - levelset.identifier, + levelset_identifier, + levelset_name, level_nr); + checked_free(levelset_identifier); + checked_free(levelset_name); + ConvertHttpRequestBodyToServerEncoding(request); return TRUE; @@ -9243,6 +9381,10 @@ static void ApiGetScore_HttpRequestExt(struct HttpRequest *request, if (!HTTP_SUCCESS(response->status_code)) { + // do not show error message if no scores found for this level set + if (response->status_code == 404) + return; + Error("server failed to handle request: %d %s", response->status_code, response->status_text); @@ -9268,12 +9410,16 @@ static int ApiGetScoreThread(void *data_raw) struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest)); struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse)); + program.api_thread_count++; + #if defined(PLATFORM_EMSCRIPTEN) Emscripten_ApiGetScore_HttpRequest(request, data_raw); #else ApiGetScore_HttpRequest(request, response, data_raw); #endif + program.api_thread_count--; + checked_free(request); checked_free(response); @@ -9304,6 +9450,12 @@ static void LoadServerScoreFromCache(int nr) { &score_entry.time, FALSE, 0 }, { score_entry.name, TRUE, MAX_PLAYER_NAME_LEN }, { score_entry.tape_basename, TRUE, MAX_FILENAME_LEN }, + { score_entry.tape_date, TRUE, MAX_ISO_DATE_LEN }, + { &score_entry.id, FALSE, 0 }, + { score_entry.platform, TRUE, MAX_PLATFORM_TEXT_LEN }, + { score_entry.version, TRUE, MAX_VERSION_TEXT_LEN }, + { score_entry.country_code, TRUE, MAX_COUNTRY_CODE_LEN }, + { score_entry.country_name, TRUE, MAX_COUNTRY_NAME_LEN }, { NULL, FALSE, 0 } }; @@ -9429,10 +9581,25 @@ static char *get_file_base64(char *filename) return buffer_encoded; } +static void PrepareScoreTapesForUpload(char *leveldir_subdir) +{ + MarkTapeDirectoryUploadsAsIncomplete(leveldir_subdir); + + // if score tape not uploaded, ask for uploading missing tapes later + if (!setup.has_remaining_tapes) + setup.ask_for_remaining_tapes = TRUE; + + setup.provide_uploading_tapes = TRUE; + setup.has_remaining_tapes = TRUE; + + SaveSetup_ServerSetup(); +} + struct ApiAddScoreThreadData { int level_nr; boolean tape_saved; + char *leveldir_subdir; char *score_tape_filename; struct ScoreEntry score_entry; }; @@ -9449,8 +9616,9 @@ static void *CreateThreadData_ApiAddScore(int nr, boolean tape_saved, data->level_nr = nr; data->tape_saved = tape_saved; - data->score_entry = *score_entry; + data->leveldir_subdir = getStringCopy(leveldir_current->subdir); data->score_tape_filename = getStringCopy(score_tape_filename); + data->score_entry = *score_entry; return data; } @@ -9459,6 +9627,7 @@ static void FreeThreadData_ApiAddScore(void *data_raw) { struct ApiAddScoreThreadData *data = data_raw; + checked_free(data->leveldir_subdir); checked_free(data->score_tape_filename); checked_free(data); } @@ -9517,6 +9686,7 @@ static boolean SetRequest_ApiAddScore(struct HttpRequest *request, " \"level_nr\": \"%d\",\n" " \"level_name\": \"%s\",\n" " \"level_author\": \"%s\",\n" + " \"use_step_counter\": \"%d\",\n" " \"rate_time_over_score\": \"%d\",\n" " \"player_name\": \"%s\",\n" " \"player_uuid\": \"%s\",\n" @@ -9538,6 +9708,7 @@ static boolean SetRequest_ApiAddScore(struct HttpRequest *request, level_nr, level_name, level_author, + level.use_step_counter, level.rate_time_over_score, player_name, player_uuid, @@ -9568,6 +9739,13 @@ static void HandleResponse_ApiAddScore(struct HttpResponse *response, server_scores.uploaded = TRUE; } +static void HandleFailure_ApiAddScore(void *data_raw) +{ + struct ApiAddScoreThreadData *data = data_raw; + + PrepareScoreTapesForUpload(data->leveldir_subdir); +} + #if defined(PLATFORM_EMSCRIPTEN) static void Emscripten_ApiAddScore_Loaded(unsigned handle, void *data_raw, void *buffer, unsigned int size) @@ -9583,6 +9761,8 @@ static void Emscripten_ApiAddScore_Loaded(unsigned handle, void *data_raw, else { Error("server response too large to handle (%d bytes)", size); + + HandleFailure_ApiAddScore(data_raw); } FreeThreadData_ApiAddScore(data_raw); @@ -9593,6 +9773,8 @@ static void Emscripten_ApiAddScore_Failed(unsigned handle, void *data_raw, { Error("server failed to handle request: %d %s", code, status); + HandleFailure_ApiAddScore(data_raw); + FreeThreadData_ApiAddScore(data_raw); } @@ -9635,6 +9817,8 @@ static void ApiAddScore_HttpRequestExt(struct HttpRequest *request, { Error("HTTP request failed: %s", GetHttpError()); + HandleFailure_ApiAddScore(data_raw); + return; } @@ -9644,6 +9828,8 @@ static void ApiAddScore_HttpRequestExt(struct HttpRequest *request, response->status_code, response->status_text); + HandleFailure_ApiAddScore(data_raw); + return; } @@ -9665,12 +9851,16 @@ static int ApiAddScoreThread(void *data_raw) struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest)); struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse)); + program.api_thread_count++; + #if defined(PLATFORM_EMSCRIPTEN) Emscripten_ApiAddScore_HttpRequest(request, data_raw); #else ApiAddScore_HttpRequest(request, response, data_raw); #endif + program.api_thread_count--; + checked_free(request); checked_free(response); @@ -9691,7 +9881,11 @@ static void ApiAddScoreAsThread(int nr, boolean tape_saved, void SaveServerScore(int nr, boolean tape_saved) { if (!runtime.use_api_server) + { + PrepareScoreTapesForUpload(leveldir_current->subdir); + return; + } ApiAddScoreAsThread(nr, tape_saved, NULL); } @@ -9709,12 +9903,17 @@ void LoadLocalAndServerScore(int nr, boolean download_score) { int last_added_local = scores.last_added_local; - LoadScore(nr); + // needed if only showing server scores + setScoreInfoToDefaults(); + + if (!strEqual(setup.scores_in_highscore_list, STR_SCORES_TYPE_SERVER_ONLY)) + LoadScore(nr); // restore last added local score entry (before merging server scores) scores.last_added = scores.last_added_local = last_added_local; - if (setup.use_api_server && !setup.only_show_local_scores) + if (setup.use_api_server && + !strEqual(setup.scores_in_highscore_list, STR_SCORES_TYPE_LOCAL_ONLY)) { // load server scores from cache file and trigger update from server LoadServerScore(nr, download_score); @@ -9790,6 +9989,10 @@ static struct TokenInfo global_setup_tokens[] = TYPE_SWITCH, &setup.autorecord, "automatic_tape_recording" }, + { + TYPE_SWITCH, + &setup.auto_pause_on_start, "auto_pause_on_start" + }, { TYPE_SWITCH, &setup.show_titlescreen, "show_titlescreen" @@ -9915,8 +10118,8 @@ static struct TokenInfo global_setup_tokens[] = &setup.show_undo_redo_buttons, "show_undo_redo_buttons" }, { - TYPE_SWITCH, - &setup.only_show_local_scores, "only_show_local_scores" + TYPE_STRING, + &setup.scores_in_highscore_list, "scores_in_highscore_list" }, { TYPE_STRING, @@ -10022,6 +10225,10 @@ static struct TokenInfo server_setup_tokens[] = TYPE_STRING, &setup.player_uuid, "player_uuid" }, + { + TYPE_INTEGER, + &setup.player_version, "player_version" + }, { TYPE_SWITCH, &setup.use_api_server, TEST_PREFIX "use_api_server" @@ -10038,10 +10245,22 @@ static struct TokenInfo server_setup_tokens[] = TYPE_SWITCH, &setup.ask_for_uploading_tapes, TEST_PREFIX "ask_for_uploading_tapes" }, + { + TYPE_SWITCH, + &setup.ask_for_remaining_tapes, TEST_PREFIX "ask_for_remaining_tapes" + }, { TYPE_SWITCH, &setup.provide_uploading_tapes, TEST_PREFIX "provide_uploading_tapes" }, + { + TYPE_SWITCH, + &setup.ask_for_using_api_server,TEST_PREFIX "ask_for_using_api_server" + }, + { + TYPE_SWITCH, + &setup.has_remaining_tapes, TEST_PREFIX "has_remaining_tapes" + }, }; static struct TokenInfo editor_setup_tokens[] = @@ -10134,6 +10353,10 @@ static struct TokenInfo editor_cascade_setup_tokens[] = TYPE_SWITCH, &setup.editor_cascade.el_ge, "editor.cascade.el_ge" }, + { + TYPE_SWITCH, + &setup.editor_cascade.el_es, "editor.cascade.el_es" + }, { TYPE_SWITCH, &setup.editor_cascade.el_ref, "editor.cascade.el_ref" @@ -10158,6 +10381,14 @@ static struct TokenInfo shortcut_setup_tokens[] = TYPE_KEY_X11, &setup.shortcut.load_game, "shortcut.load_game" }, + { + TYPE_KEY_X11, + &setup.shortcut.restart_game, "shortcut.restart_game" + }, + { + TYPE_KEY_X11, + &setup.shortcut.pause_before_end, "shortcut.pause_before_end" + }, { TYPE_KEY_X11, &setup.shortcut.toggle_pause, "shortcut.toggle_pause" @@ -10580,6 +10811,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->engine_snapshot_memory = SNAPSHOT_MEMORY_DEFAULT; si->fade_screens = TRUE; si->autorecord = TRUE; + si->auto_pause_on_start = FALSE; si->show_titlescreen = TRUE; si->quick_doors = FALSE; si->team_mode = FALSE; @@ -10611,7 +10843,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->small_game_graphics = FALSE; si->show_load_save_buttons = FALSE; si->show_undo_redo_buttons = FALSE; - si->only_show_local_scores = FALSE; + si->scores_in_highscore_list = getStringCopy(STR_SCORES_TYPE_DEFAULT); si->graphics_set = getStringCopy(GFX_CLASSIC_SUBDIR); si->sounds_set = getStringCopy(SND_CLASSIC_SUBDIR); @@ -10716,6 +10948,8 @@ static void setSetupInfoToDefaults(struct SetupInfo *si) si->shortcut.save_game = DEFAULT_KEY_SAVE_GAME; si->shortcut.load_game = DEFAULT_KEY_LOAD_GAME; + si->shortcut.restart_game = DEFAULT_KEY_RESTART_GAME; + si->shortcut.pause_before_end = DEFAULT_KEY_PAUSE_BEFORE_END; si->shortcut.toggle_pause = DEFAULT_KEY_TOGGLE_PAUSE; si->shortcut.focus_player[0] = DEFAULT_KEY_FOCUS_PLAYER_1; @@ -10838,12 +11072,16 @@ static void setSetupInfoToDefaults_AutoSetup(struct SetupInfo *si) static void setSetupInfoToDefaults_ServerSetup(struct SetupInfo *si) { si->player_uuid = NULL; // (will be set later) + si->player_version = 1; // (will be set later) si->use_api_server = TRUE; si->api_server_hostname = getStringCopy(API_SERVER_HOSTNAME); si->api_server_password = getStringCopy(UNDEFINED_PASSWORD); si->ask_for_uploading_tapes = TRUE; + si->ask_for_remaining_tapes = FALSE; si->provide_uploading_tapes = TRUE; + si->ask_for_using_api_server = TRUE; + si->has_remaining_tapes = FALSE; } static void setSetupInfoToDefaults_EditorCascade(struct SetupInfo *si) @@ -10864,6 +11102,7 @@ static void setSetupInfoToDefaults_EditorCascade(struct SetupInfo *si) si->editor_cascade.el_steel_chars = FALSE; si->editor_cascade.el_ce = FALSE; si->editor_cascade.el_ge = FALSE; + si->editor_cascade.el_es = FALSE; si->editor_cascade.el_ref = FALSE; si->editor_cascade.el_user = FALSE; si->editor_cascade.el_dynamic = FALSE; @@ -11197,6 +11436,7 @@ void LoadSetup_ServerSetup(void) { // player UUID does not yet exist in setup file setup.player_uuid = getStringCopy(getUUID()); + setup.player_version = 2; SaveSetup_ServerSetup(); } @@ -11894,6 +12134,7 @@ int get_parameter_value(char *value_raw, char *suffix, int type) string_has_parameter(value, "pingpong") ? ANIM_PINGPONG : string_has_parameter(value, "pingpong2") ? ANIM_PINGPONG2 : string_has_parameter(value, "random") ? ANIM_RANDOM : + string_has_parameter(value, "random_static") ? ANIM_RANDOM_STATIC : string_has_parameter(value, "ce_value") ? ANIM_CE_VALUE : string_has_parameter(value, "ce_score") ? ANIM_CE_SCORE : string_has_parameter(value, "ce_delay") ? ANIM_CE_DELAY : @@ -11901,6 +12142,7 @@ int get_parameter_value(char *value_raw, char *suffix, int type) string_has_parameter(value, "vertical") ? ANIM_VERTICAL : string_has_parameter(value, "centered") ? ANIM_CENTERED : string_has_parameter(value, "all") ? ANIM_ALL : + string_has_parameter(value, "tiled") ? ANIM_TILED : ANIM_DEFAULT); if (string_has_parameter(value, "once")) @@ -12008,14 +12250,18 @@ static int get_token_parameter_value(char *token, char *value_raw) return get_parameter_value(value_raw, suffix, TYPE_INTEGER); } -void InitMenuDesignSettings_Static(void) +void InitMenuDesignSettings_FromHash(SetupFileHash *setup_file_hash, + boolean ignore_defaults) { int i; - // always start with reliable default values from static default config for (i = 0; image_config_vars[i].token != NULL; i++) { - char *value = getHashEntry(image_config_hash, image_config_vars[i].token); + char *value = getHashEntry(setup_file_hash, image_config_vars[i].token); + + // (ignore definitions set to "[DEFAULT]" which are already initialized) + if (ignore_defaults && strEqual(value, ARG_DEFAULT)) + continue; if (value != NULL) *image_config_vars[i].value = @@ -12023,6 +12269,12 @@ void InitMenuDesignSettings_Static(void) } } +void InitMenuDesignSettings_Static(void) +{ + // always start with reliable default values from static default config + InitMenuDesignSettings_FromHash(image_config_hash, FALSE); +} + static void InitMenuDesignSettings_SpecialPreProcessing(void) { int i; @@ -12821,15 +13073,7 @@ static void LoadMenuDesignSettingsFromFilename(char *filename) *menu_config_players[i].value = TRUE; // read (and overwrite with) values that may be specified in config file - for (i = 0; image_config_vars[i].token != NULL; i++) - { - char *value = getHashEntry(setup_file_hash, image_config_vars[i].token); - - // (ignore definitions set to "[DEFAULT]" which are already initialized) - if (value != NULL && !strEqual(value, ARG_DEFAULT)) - *image_config_vars[i].value = - get_token_parameter_value(image_config_vars[i].token, value); - } + InitMenuDesignSettings_FromHash(setup_file_hash, TRUE); freeSetupFileHash(setup_file_hash); }