/** * Loads only the basic information from a scenario. * rct2: 0x006761D6 */ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info) { SDL_RWops* rw; log_verbose("loading scenario details, %s", path); rw = SDL_RWFromFile(path, "rb"); if (rw != NULL) { // Read first chunk sawyercoding_read_chunk(rw, (uint8*)header); if (header->type == S6_TYPE_SCENARIO) { // Read second chunk sawyercoding_read_chunk(rw, (uint8*)info); SDL_RWclose(rw); RCT2_GLOBAL(0x009AA00C, uint8) = 0; // Get filename utf8 filename[MAX_PATH]; const char *temp_filename = path_get_filename(path); int len = strnlen(temp_filename, MAX_PATH); safe_strncpy(filename, temp_filename, MAX_PATH); if (len == MAX_PATH) { filename[MAX_PATH - 1] = '\0'; log_warning("truncated string %s", filename); } path_remove_extension(filename); rct_string_id localisedStringIds[3]; if (language_get_localised_scenario_strings(filename, localisedStringIds)) { if (localisedStringIds[0] != (rct_string_id)STR_NONE) { safe_strncpy(info->name, language_get_string(localisedStringIds[0]), 64); } if (localisedStringIds[2] != (rct_string_id)STR_NONE) { safe_strncpy(info->details, language_get_string(localisedStringIds[2]), 256); } } else { // Checks for a scenario string object (possibly for localisation) if ((info->entry.flags & 0xFF) != 255) { if (object_get_scenario_text(&info->entry)) { rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*); format_string(info->name, stex_entry->scenario_name, NULL); format_string(info->details, stex_entry->details, NULL); RCT2_GLOBAL(0x009AA00C, uint8) = stex_entry->var_06; object_free_scenario_text(); } } }
static void window_title_editor_add_park_callback(sint32 result, const utf8 * path) { uint32 extension = get_file_extension_type(path); if (extension != FILE_EXTENSION_SV4 && extension != FILE_EXTENSION_SV6) return; const utf8 * filename = path_get_filename(path); if (save_filename_exists(filename)) { free(_renameSavePath); _renameSavePath = _strdup(filename); // set_format_arg(0, intptr_t, (intptr_t)&_renameSavePath); rct_window * w = window_find_by_class(WC_TITLE_EDITOR); window_text_input_open(w, WIDX_TITLE_EDITOR_RENAME_SAVE, STR_FILEBROWSER_RENAME_SAVE_TITLE, STR_ERROR_EXISTING_NAME, STR_STRING, (uintptr_t)_renameSavePath, 52 - 1); return; } TitleSequenceAddPark(_editingTitleSequence, path, filename); }
static void window_loadsave_select(rct_window *w, const char *path) { SDL_RWops* rw; switch (_loadsaveType & 0x0F) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) : if (gLoadSaveTitleSequenceSave) { utf8 newName[MAX_PATH]; char *extension = (char*)path_get_extension(path); safe_strcpy(newName, path_get_filename(path), MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newName, ".sv6"); if (title_sequence_save_exists(gCurrentTitleSequence, newName)) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&_listItems[w->selected_list_item].name; window_text_input_open(w, WIDX_SCROLL, 5435, 5404, 1170, (uint32)_listItems[w->selected_list_item].name, TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1); } else { title_sequence_add_save(gCurrentTitleSequence, path, newName); window_close(w); } window_loadsave_invoke_callback(MODAL_RESULT_OK); } else if (game_load_save(path)) { safe_strcpy(gScenarioSavePath, path, MAX_PATH); gFirstTimeSave = 0; window_close(w); gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); } else { // 1050, not the best message... window_error_open(STR_LOAD_GAME, 1050); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME) : rw = SDL_RWFromFile(path, "wb+"); if (rw != NULL) { int success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 1 : 0); SDL_RWclose(rw); if (success) { safe_strcpy(gScenarioSavePath, path, MAX_PATH); gFirstTimeSave = 0; window_close_by_class(WC_LOADSAVE); gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); } else { window_error_open(STR_SAVE_GAME, 1047); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } } else { window_error_open(STR_SAVE_GAME, 1047); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE) : if (editor_load_landscape(path)) { gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); } else { // 1050, not the best message... window_error_open(STR_LOAD_LANDSCAPE, 1050); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE) : rw = SDL_RWFromFile(path, "wb+"); if (rw != NULL) { scenario_set_filename(path); int success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 3 : 2); SDL_RWclose(rw); if (success) { window_close_by_class(WC_LOADSAVE); gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); } else { window_error_open(STR_SAVE_LANDSCAPE, 1049); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } } else { window_error_open(STR_SAVE_LANDSCAPE, 1049); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO) : { rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; int parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32); RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_18; s6Info->editor_step = 255; rw = SDL_RWFromFile(path, "wb+"); int success = 0; if (rw != NULL) { scenario_set_filename(path); success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 3 : 2); SDL_RWclose(rw); } RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = parkFlagsBackup; if (success) { window_close_by_class(WC_LOADSAVE); window_loadsave_invoke_callback(MODAL_RESULT_OK); title_load(); } else { window_error_open(STR_FILE_DIALOG_TITLE_SAVE_SCENARIO, STR_SCENARIO_SAVE_FAILED); s6Info->editor_step = EDITOR_STEP_OBJECTIVE_SELECTION; window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } break; } case (LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK) : window_install_track_open(path); window_close_by_class(WC_LOADSAVE); window_loadsave_invoke_callback(MODAL_RESULT_OK); break; } }
static void scenario_list_add(const utf8 *path, uint64 timestamp) { // Load the basic scenario information rct_s6_header s6Header; rct_s6_info s6Info; if (!scenario_load_basic(path, &s6Header, &s6Info)) { return; } scenario_index_entry *newEntry = NULL; const utf8 *filename = path_get_filename(path); scenario_index_entry *existingEntry = scenario_list_find_by_filename(filename); if (existingEntry != NULL) { bool bail = false; const utf8 *conflictPath; if (existingEntry->timestamp > timestamp) { // Existing entry is more recent conflictPath = existingEntry->path; // Overwrite existing entry with this one newEntry = existingEntry; } else { // This entry is more recent conflictPath = path; bail = true; } printf("Scenario conflict: '%s' ignored because it is newer.\n", conflictPath); if (bail) { return; } } if (newEntry == NULL) { // Increase list size if (gScenarioListCount == gScenarioListCapacity) { gScenarioListCapacity = max(8, gScenarioListCapacity * 2); gScenarioList = (scenario_index_entry*)realloc(gScenarioList, gScenarioListCapacity * sizeof(scenario_index_entry)); } newEntry = &gScenarioList[gScenarioListCount]; gScenarioListCount++; } // Set new entry safe_strcpy(newEntry->path, path, sizeof(newEntry->path)); newEntry->timestamp = timestamp; newEntry->category = s6Info.category; newEntry->objective_type = s6Info.objective_type; newEntry->objective_arg_1 = s6Info.objective_arg_1; newEntry->objective_arg_2 = s6Info.objective_arg_2; newEntry->objective_arg_3 = s6Info.objective_arg_3; newEntry->highscore = NULL; safe_strcpy(newEntry->name, s6Info.name, sizeof(newEntry->name)); safe_strcpy(newEntry->details, s6Info.details, sizeof(newEntry->details)); // Normalise the name to make the scenario as recognisable as possible. scenario_normalise_name(newEntry->name); // Look up and store information regarding the origins of this scenario. source_desc desc; if (scenario_get_source_desc(newEntry->name, &desc)) { newEntry->sc_id = desc.id; newEntry->source_index = desc.index; newEntry->source_game = desc.source; newEntry->category = desc.category; } else { newEntry->sc_id = SC_UNIDENTIFIED; newEntry->source_index = -1; if (newEntry->category == SCENARIO_CATEGORY_REAL) { newEntry->source_game = SCENARIO_SOURCE_REAL; } else { newEntry->source_game = SCENARIO_SOURCE_OTHER; } } scenario_translate(newEntry, &s6Info.entry); }