From c9d7cd8216a2a6cb4549fa99d1f24f82f166a2fb Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 30 Jan 2017 18:55:17 +0000 Subject: [PATCH 1/7] Refactor loading of SC6 information when scanning scenarios --- src/openrct2/FileClassifier.cpp | 32 +-------- src/openrct2/libopenrct2.vcxproj | 4 +- src/openrct2/rct12/SawyerEncoding.cpp | 57 ++++++++++++++++ src/openrct2/rct12/SawyerEncoding.h | 32 +++++++++ src/openrct2/scenario/ScenarioRepository.cpp | 72 ++++++++++++++++---- src/openrct2/scenario/scenario.c | 37 ---------- src/openrct2/scenario/scenario.h | 1 - 7 files changed, 154 insertions(+), 81 deletions(-) create mode 100644 src/openrct2/rct12/SawyerEncoding.cpp create mode 100644 src/openrct2/rct12/SawyerEncoding.h diff --git a/src/openrct2/FileClassifier.cpp b/src/openrct2/FileClassifier.cpp index b3b64bdf01..897328a662 100644 --- a/src/openrct2/FileClassifier.cpp +++ b/src/openrct2/FileClassifier.cpp @@ -16,6 +16,7 @@ #include "core/FileStream.hpp" #include "FileClassifier.h" +#include "rct12/SawyerEncoding.h" extern "C" { @@ -26,7 +27,6 @@ extern "C" static bool TryClassifyAsS6(IStream * stream, ClassifiedFile * result); static bool TryClassifyAsS4(IStream * stream, ClassifiedFile * result); static bool TryClassifyAsTD4_TD6(IStream * stream, ClassifiedFile * result); -static bool sawyercoding_try_read_chunk(void * dst, size_t expectedSize, IStream * stream); bool TryClassifyFile(const std::string &path, ClassifiedFile * result) { @@ -72,7 +72,7 @@ bool TryClassifyFile(IStream * stream, ClassifiedFile * result) static bool TryClassifyAsS6(IStream * stream, ClassifiedFile * result) { rct_s6_header s6Header; - if (sawyercoding_try_read_chunk(&s6Header, sizeof(rct_s6_header), stream)) + if (SawyerEncoding::TryReadChunk(&s6Header, stream)) { if (s6Header.type == S6_TYPE_SAVEDGAME) { @@ -145,31 +145,3 @@ static bool TryClassifyAsTD4_TD6(IStream * stream, ClassifiedFile * result) return success; } - -static bool sawyercoding_try_read_chunk(void * dst, size_t expectedSize, IStream * stream) -{ - uint64 originalPosition = stream->GetPosition(); - - bool success = false; - auto header = stream->ReadValue(); - switch (header.encoding) { - case CHUNK_ENCODING_NONE: - case CHUNK_ENCODING_RLE: - case CHUNK_ENCODING_RLECOMPRESSED: - case CHUNK_ENCODING_ROTATE: - uint8 * compressedData = Memory::Allocate(header.length); - if (stream->TryRead(compressedData, header.length) == header.length) - { - size_t uncompressedLength = sawyercoding_read_chunk_buffer((uint8 *)dst, compressedData, header, expectedSize); - if (uncompressedLength == expectedSize) - { - success = true; - } - } - Memory::Free(compressedData); - break; - } - - stream->SetPosition(originalPosition); - return success; -} diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index f83b8ea4a0..9cf193573e 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -73,6 +73,7 @@ + @@ -414,6 +415,7 @@ + @@ -596,4 +598,4 @@ - + \ No newline at end of file diff --git a/src/openrct2/rct12/SawyerEncoding.cpp b/src/openrct2/rct12/SawyerEncoding.cpp new file mode 100644 index 0000000000..68971a2b59 --- /dev/null +++ b/src/openrct2/rct12/SawyerEncoding.cpp @@ -0,0 +1,57 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "../core/IStream.hpp" +#include "SawyerEncoding.h" + +extern "C" +{ + #include "../util/sawyercoding.h" +} + +namespace SawyerEncoding +{ + bool TryReadChunk(void * dst, size_t expectedSize, IStream * stream) + { + uint64 originalPosition = stream->GetPosition(); + + bool success = false; + auto header = stream->ReadValue(); + switch (header.encoding) { + case CHUNK_ENCODING_NONE: + case CHUNK_ENCODING_RLE: + case CHUNK_ENCODING_RLECOMPRESSED: + case CHUNK_ENCODING_ROTATE: + uint8 * compressedData = Memory::Allocate(header.length); + if (stream->TryRead(compressedData, header.length) == header.length) + { + size_t uncompressedLength = sawyercoding_read_chunk_buffer((uint8 *)dst, compressedData, header, expectedSize); + if (uncompressedLength == expectedSize) + { + success = true; + } + } + Memory::Free(compressedData); + break; + } + + if (!success) + { + stream->SetPosition(originalPosition); + } + return success; + } +} diff --git a/src/openrct2/rct12/SawyerEncoding.h b/src/openrct2/rct12/SawyerEncoding.h new file mode 100644 index 0000000000..188ebed2db --- /dev/null +++ b/src/openrct2/rct12/SawyerEncoding.h @@ -0,0 +1,32 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../common.h" + +interface IStream; + +namespace SawyerEncoding +{ + bool TryReadChunk(void * dst, size_t expectedSize, IStream * stream); + + template + bool TryReadChunk(T * dst, IStream * stream) + { + return TryReadChunk(dst, sizeof(T), stream); + } +} diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index 0efe3d0928..5c4a0ecb8b 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -25,6 +25,7 @@ #include "../core/String.hpp" #include "../core/Util.hpp" #include "../PlatformEnvironment.h" +#include "../rct12/SawyerEncoding.h" #include "ScenarioRepository.h" #include "ScenarioSources.h" @@ -142,8 +143,10 @@ public: _scenarios.clear(); // Scan RCT2 directory + std::string rct1dir = _env->GetDirectoryPath(DIRBASE::RCT1, DIRID::SCENARIO); std::string rct2dir = _env->GetDirectoryPath(DIRBASE::RCT2, DIRID::SCENARIO); std::string openrct2dir = _env->GetDirectoryPath(DIRBASE::USER, DIRID::SCENARIO); + Scan(rct1dir); Scan(rct2dir); Scan(openrct2dir); @@ -253,7 +256,7 @@ private: { utf8 pattern[MAX_PATH]; String::Set(pattern, sizeof(pattern), directory.c_str()); - Path::Append(pattern, sizeof(pattern), "*.sc6"); + Path::Append(pattern, sizeof(pattern), "*.sc4;*.sc6"); IFileScanner * scanner = Path::ScanDirectory(pattern, true); while (scanner->Next()) @@ -265,43 +268,88 @@ private: delete scanner; } - void AddScenario(const utf8 * path, uint64 timestamp) + void AddScenario(const std::string &path, uint64 timestamp) { - rct_s6_header s6Header; rct_s6_info s6Info; - if (!scenario_load_basic(path, &s6Header, &s6Info)) + if (!GetScenarioInfo(path, &s6Info)) { - Console::Error::WriteLine("Unable to read scenario: '%s'", path); return; } - const utf8 * filename = Path::GetFileName(path); - scenario_index_entry * existingEntry = GetByFilename(filename); + const std::string filename = Path::GetFileName(path); + scenario_index_entry * existingEntry = GetByFilename(filename.c_str()); if (existingEntry != nullptr) { - const utf8 * conflictPath; + std::string conflictPath; if (existingEntry->timestamp > timestamp) { // Existing entry is more recent - conflictPath = existingEntry->path; + conflictPath = String::ToStd(existingEntry->path); // Overwrite existing entry with this one - *existingEntry = CreateNewScenarioEntry(path, timestamp, &s6Info); + *existingEntry = CreateNewScenarioEntry(path.c_str(), timestamp, &s6Info); } else { // This entry is more recent conflictPath = path; } - Console::WriteLine("Scenario conflict: '%s' ignored because it is newer.", conflictPath); + Console::WriteLine("Scenario conflict: '%s' ignored because it is newer.", conflictPath.c_str()); } else { - scenario_index_entry entry = CreateNewScenarioEntry(path, timestamp, &s6Info); + scenario_index_entry entry = CreateNewScenarioEntry(path.c_str(), timestamp, &s6Info); _scenarios.push_back(entry); } } + /** + * Reads basic information from a scenario file. + */ + bool GetScenarioInfo(const std::string &path, rct_s6_info * info) + { + log_verbose("GetScenarioInfo(%s, ...)", path); + try + { + auto fs = FileStream(path, FILE_MODE_OPEN); + + std::string extension = Path::GetExtension(path); + if (String::Equals(extension, ".sc4", true)) + { + // RCT1 scenario + log_verbose("%s is an RCT1 scenario, not yet supported", path); + } + else + { + // RCT2 scenario + rct_s6_header header; + if (SawyerEncoding::TryReadChunk(&header, &fs)) + { + if (header.type == S6_TYPE_SCENARIO) + { + if (SawyerEncoding::TryReadChunk(info, &fs)) + { + return true; + } + else + { + throw new IOException("Unable to read S6_INFO chunk."); + } + } + else + { + log_verbose("%s is not a scenario", path); + } + } + } + } + catch (Exception) + { + Console::Error::WriteLine("Unable to read scenario: '%s'", path); + } + return false; + } + scenario_index_entry CreateNewScenarioEntry(const utf8 * path, uint64 timestamp, rct_s6_info * s6Info) { scenario_index_entry entry = { 0 }; diff --git a/src/openrct2/scenario/scenario.c b/src/openrct2/scenario/scenario.c index 697edb81c5..fd13c0791e 100644 --- a/src/openrct2/scenario/scenario.c +++ b/src/openrct2/scenario/scenario.c @@ -88,43 +88,6 @@ money32 gScenarioCompanyValueRecord; static sint32 scenario_create_ducks(); static void scenario_objective_check(); -/** - * Loads only the basic information from a scenario. - * rct2: 0x006761D6 - */ -bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info) -{ - log_verbose("loading scenario details, %s", path); - - SDL_RWops* rw = SDL_RWFromFile(path, "rb"); - if (rw != NULL) { - // Read first chunk - size_t loaded_size = sawyercoding_read_chunk_with_size(rw, (uint8*)header, sizeof(rct_s6_header)); - if (loaded_size != sizeof(rct_s6_header)) { - log_error("Failed to read header from scenario %s", path); - SDL_RWclose(rw); - return false; - } - if (header->type == S6_TYPE_SCENARIO) { - // Read second chunk - loaded_size = sawyercoding_read_chunk_with_size(rw, (uint8*)info, sizeof(rct_s6_info)); - SDL_RWclose(rw); - if (loaded_size != sizeof(rct_s6_info)) { - log_error("Failed to read info from scenario %s", path); - return false; - } - return true; - } else { - log_error("invalid scenario, %s", path); - SDL_RWclose(rw); - return false; - } - } - - log_error("unable to open scenario, %s", path); - return false; -} - sint32 scenario_load_and_play_from_path(const char *path) { window_close_construction_windows(); diff --git a/src/openrct2/scenario/scenario.h b/src/openrct2/scenario/scenario.h index 020ff2b50a..7c4a2b4026 100644 --- a/src/openrct2/scenario/scenario.h +++ b/src/openrct2/scenario/scenario.h @@ -376,7 +376,6 @@ extern uint32 gLastAutoSaveUpdate; extern const char *_scenarioFileName; -bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info); bool scenario_load_rw(SDL_RWops * rw); sint32 scenario_load(const char *path); sint32 scenario_load_and_play_from_path(const char *path); From a8e329ef99063866959c70a57bf6258bc94acde2 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 30 Jan 2017 21:32:58 +0000 Subject: [PATCH 2/7] Implement getting sc entries from SC4s --- src/openrct2/rct1/S4Importer.cpp | 42 ++++++++++++++++++++ src/openrct2/rct1/S4Importer.h | 2 + src/openrct2/scenario/ScenarioRepository.cpp | 33 ++++++++++----- 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index b2e57adf64..2724a4279d 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -168,6 +168,48 @@ public: map_count_remaining_land_rights(); } + bool GetDetails(scenario_index_entry * dst) override + { + bool result = false; + Memory::Set(dst, 0, sizeof(scenario_index_entry)); + + source_desc desc; + if (ScenarioSources::TryGetById(_s4.scenario_slot_index, &desc)) + { + dst->category = desc.category; + dst->source_game = desc.source; + dst->source_index = desc.index; + dst->sc_id = desc.id; + + dst->objective_type = _s4.scenario_objective_type; + dst->objective_arg_1 = _s4.scenario_objective_years; + dst->objective_arg_2 = _s4.scenario_objective_currency; + dst->objective_arg_3 = _s4.scenario_objective_num_guests; + + std::string name = std::string(_s4.scenario_name, sizeof(_s4.scenario_name)); + std::string details; + rct_string_id localisedStringIds[3]; + if (language_get_localised_scenario_strings(desc.title, localisedStringIds)) + { + if (localisedStringIds[0] != STR_NONE) + { + name = String::ToStd(language_get_string(localisedStringIds[0])); + } + if (localisedStringIds[2] != STR_NONE) + { + details = String::ToStd(language_get_string(localisedStringIds[2])); + } + } + + String::Set(dst->name, sizeof(dst->name), name.c_str()); + String::Set(dst->details, sizeof(dst->details), details.c_str()); + + result = true; + } + + return result; + } + private: void Initialise() { diff --git a/src/openrct2/rct1/S4Importer.h b/src/openrct2/rct1/S4Importer.h index 84c2b9183c..64bb5df230 100644 --- a/src/openrct2/rct1/S4Importer.h +++ b/src/openrct2/rct1/S4Importer.h @@ -17,6 +17,7 @@ #pragma once #include "../common.h" +#include "../scenario/ScenarioRepository.h" /** * Interface to import RollerCoaster Tycoon 1 scenarios (*.SC4) and saved games (*.SV4). @@ -28,6 +29,7 @@ public: virtual void LoadSavedGame(const utf8 * path) abstract; virtual void LoadScenario(const utf8 * path) abstract; virtual void Import() abstract; + virtual bool GetDetails(scenario_index_entry * dst) abstract; }; IS4Importer * CreateS4Importer(); diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index 5c4a0ecb8b..d838e0387e 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -25,6 +25,7 @@ #include "../core/String.hpp" #include "../core/Util.hpp" #include "../PlatformEnvironment.h" +#include "../rct1/S4Importer.h" #include "../rct12/SawyerEncoding.h" #include "ScenarioRepository.h" #include "ScenarioSources.h" @@ -270,8 +271,8 @@ private: void AddScenario(const std::string &path, uint64 timestamp) { - rct_s6_info s6Info; - if (!GetScenarioInfo(path, &s6Info)) + scenario_index_entry entry; + if (!GetScenarioInfo(path, timestamp, &entry)) { return; } @@ -287,7 +288,7 @@ private: conflictPath = String::ToStd(existingEntry->path); // Overwrite existing entry with this one - *existingEntry = CreateNewScenarioEntry(path.c_str(), timestamp, &s6Info); + *existingEntry = entry; } else { @@ -298,7 +299,6 @@ private: } else { - scenario_index_entry entry = CreateNewScenarioEntry(path.c_str(), timestamp, &s6Info); _scenarios.push_back(entry); } } @@ -306,29 +306,40 @@ private: /** * Reads basic information from a scenario file. */ - bool GetScenarioInfo(const std::string &path, rct_s6_info * info) + bool GetScenarioInfo(const std::string &path, uint64 timestamp, scenario_index_entry * entry) { log_verbose("GetScenarioInfo(%s, ...)", path); try { - auto fs = FileStream(path, FILE_MODE_OPEN); - std::string extension = Path::GetExtension(path); if (String::Equals(extension, ".sc4", true)) { // RCT1 scenario - log_verbose("%s is an RCT1 scenario, not yet supported", path); + bool result = false; + IS4Importer * s4Importer = CreateS4Importer(); + s4Importer->LoadScenario(path.c_str()); + if (s4Importer->GetDetails(entry)) + { + String::Set(entry->path, sizeof(entry->path), path.c_str()); + entry->timestamp = timestamp; + result = true; + } + delete s4Importer; + return result; } else { // RCT2 scenario + auto fs = FileStream(path, FILE_MODE_OPEN); rct_s6_header header; if (SawyerEncoding::TryReadChunk(&header, &fs)) { if (header.type == S6_TYPE_SCENARIO) { - if (SawyerEncoding::TryReadChunk(info, &fs)) + rct_s6_info info; + if (SawyerEncoding::TryReadChunk(&info, &fs)) { + *entry = CreateNewScenarioEntry(path, timestamp, &info); return true; } else @@ -350,12 +361,12 @@ private: return false; } - scenario_index_entry CreateNewScenarioEntry(const utf8 * path, uint64 timestamp, rct_s6_info * s6Info) + scenario_index_entry CreateNewScenarioEntry(const std::string &path, uint64 timestamp, rct_s6_info * s6Info) { scenario_index_entry entry = { 0 }; // Set new entry - String::Set(entry.path, sizeof(entry.path), path); + String::Set(entry.path, sizeof(entry.path), path.c_str()); entry.timestamp = timestamp; entry.category = s6Info->category; entry.objective_type = s6Info->objective_type; From daaf6c69a319d92b879c30760f075c0553f5ec7a Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 30 Jan 2017 21:35:57 +0000 Subject: [PATCH 3/7] Use missing SC IDs in scenario sources --- src/openrct2/scenario/ScenarioSources.cpp | 42 +++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index 7e2088fe76..5bc839635b 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -218,32 +218,32 @@ namespace ScenarioSources // Real parks static const ScenarioTitleDescriptor ScenarioTitlesRealParks[] = { - { SC_UNIDENTIFIED, "Alton Towers", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Heide-Park", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL }, - { SC_UNIDENTIFIED, "Six Flags over Texas", SCENARIO_CATEGORY_REAL }, + { ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL }, + { SC_HEIDE_PARK, "Heide-Park", SCENARIO_CATEGORY_REAL }, + { SC_BLACKPOOL_PLEASURE_BEACH, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL }, + { SC_UNIDENTIFIED, "Six Flags over Texas", SCENARIO_CATEGORY_REAL }, }; // Other parks static const ScenarioTitleDescriptor ScenarioTitlesOtherParks[] = { - { SC_UNIDENTIFIED, "Fort Anachronism", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "PC Player", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "PC Gaming World", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "gameplay", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "Competition Land 1", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "Competition Land 2", SCENARIO_CATEGORY_DLC }, - { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, - { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC }, + { SC_PCPLAYER, "PC Player", SCENARIO_CATEGORY_DLC }, + { SC_PCGW, "PC Gaming World", SCENARIO_CATEGORY_DLC }, + { SC_GAMEPLAY, "gameplay", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Competition Land 1", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Competition Land 2", SCENARIO_CATEGORY_DLC }, + { SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, + { SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_BUILD_YOUR_OWN }, }; #define DEFINE_SCENARIO_TITLE_DESC_GROUP(x) { Util::CountOf(x), x } From 612e268e5f9d27b373613b9bc0302ba4e5a1151e Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 30 Jan 2017 22:06:24 +0000 Subject: [PATCH 4/7] Allow SC4s to be loaded by title seq player --- src/openrct2/rct1/S4Importer.cpp | 1 - src/openrct2/title/TitleSequencePlayer.cpp | 48 ++++++++++++++++++---- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 2724a4279d..89dbed9611 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -227,7 +227,6 @@ private: uint16 mapSize = _s4.map_size == 0 ? 128 : _s4.map_size; // Do map initialisation, same kind of stuff done when loading scenario editor - audio_stop_all_music_and_sounds(); GetObjectManager()->UnloadAll(); game_init_all(mapSize); gS6Info.editor_step = EDITOR_STEP_OBJECT_SELECTION; diff --git a/src/openrct2/title/TitleSequencePlayer.cpp b/src/openrct2/title/TitleSequencePlayer.cpp index 32029ed072..0505b531ef 100644 --- a/src/openrct2/title/TitleSequencePlayer.cpp +++ b/src/openrct2/title/TitleSequencePlayer.cpp @@ -22,6 +22,7 @@ #include "../core/Math.hpp" #include "../core/Path.hpp" #include "../core/String.hpp" +#include "../rct1/S4Importer.h" #include "../scenario/ScenarioRepository.h" #include "../scenario/ScenarioSources.h" #include "TitleSequence.h" @@ -352,12 +353,40 @@ private: bool LoadParkFromFile(const utf8 * path) { bool success = false; - bool isScenario = String::Equals(Path::GetExtension(path), ".sc6", true); - SDL_RWops * rw = SDL_RWFromFile(path, "rb"); - if (rw != nullptr) + const utf8 * extension = Path::GetExtension(path); + if (String::Equals(extension, ".sc4", true) || + String::Equals(extension, ".sv4", true)) { - success = LoadParkFromRW(rw, isScenario); - SDL_RWclose(rw); + try + { + bool isScenario = String::Equals(extension, ".sc4", true); + IS4Importer * s4Importer = CreateS4Importer(); + if (isScenario) + { + s4Importer->LoadScenario(path); + s4Importer->Import(); + } + else + { + s4Importer->LoadSavedGame(path); + s4Importer->Import(); + } + PrepareParkForPlayback(isScenario); + success = true; + } + catch (Exception) + { + } + } + else + { + bool isScenario = String::Equals(extension, ".sc6", true); + SDL_RWops * rw = SDL_RWFromFile(path, "rb"); + if (rw != nullptr) + { + success = LoadParkFromRW(rw, isScenario); + SDL_RWclose(rw); + } } return success; } @@ -366,11 +395,15 @@ private: { bool successfulLoad = isScenario ? scenario_load_rw(rw) : game_load_sv6(rw); - if (!successfulLoad) + if (successfulLoad) { - return false; + PrepareParkForPlayback(isScenario); } + return successfulLoad; + } + void PrepareParkForPlayback(bool isScenario) + { rct_window * w = window_get_main(); w->viewport_target_sprite = -1; w->saved_view_x = gSavedViewX; @@ -410,7 +443,6 @@ private: gfx_invalidate_screen(); gScreenAge = 0; gGameSpeed = 1; - return true; } /** From 4670d2f770f94494dd70e13a36b161c41c9841e4 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 31 Jan 2017 17:57:10 +0000 Subject: [PATCH 5/7] Fix some SC enum items missing prefix --- src/openrct2/scenario/ScenarioSources.cpp | 4 ++-- src/openrct2/scenario/ScenarioSources.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp index 5bc839635b..be6c84075a 100644 --- a/src/openrct2/scenario/ScenarioSources.cpp +++ b/src/openrct2/scenario/ScenarioSources.cpp @@ -218,7 +218,7 @@ namespace ScenarioSources // Real parks static const ScenarioTitleDescriptor ScenarioTitlesRealParks[] = { - { ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL }, + { SC_ALTON_TOWERS, "Alton Towers", SCENARIO_CATEGORY_REAL }, { SC_HEIDE_PARK, "Heide-Park", SCENARIO_CATEGORY_REAL }, { SC_BLACKPOOL_PLEASURE_BEACH, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL }, { SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL }, @@ -231,7 +231,7 @@ namespace ScenarioSources // Other parks static const ScenarioTitleDescriptor ScenarioTitlesOtherParks[] = { - { FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC }, + { SC_FORT_ANACHRONISM, "Fort Anachronism", SCENARIO_CATEGORY_DLC }, { SC_PCPLAYER, "PC Player", SCENARIO_CATEGORY_DLC }, { SC_PCGW, "PC Gaming World", SCENARIO_CATEGORY_DLC }, { SC_GAMEPLAY, "gameplay", SCENARIO_CATEGORY_DLC }, diff --git a/src/openrct2/scenario/ScenarioSources.h b/src/openrct2/scenario/ScenarioSources.h index 73b17df777..caa7d6f3c4 100644 --- a/src/openrct2/scenario/ScenarioSources.h +++ b/src/openrct2/scenario/ScenarioSources.h @@ -93,8 +93,8 @@ enum SC_WACKY_WARREN, // Special - ALTON_TOWERS, - FORT_ANACHRONISM, + SC_ALTON_TOWERS, + SC_FORT_ANACHRONISM, // Added Attractions SC_WHISPERING_CLIFFS = 40, From 72800acd5c2807595b6971f196257ee9f87d771a Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 31 Jan 2017 17:59:42 +0000 Subject: [PATCH 6/7] Fix std::string used as char * --- src/openrct2/scenario/ScenarioRepository.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/openrct2/scenario/ScenarioRepository.cpp b/src/openrct2/scenario/ScenarioRepository.cpp index d838e0387e..c37881ec27 100644 --- a/src/openrct2/scenario/ScenarioRepository.cpp +++ b/src/openrct2/scenario/ScenarioRepository.cpp @@ -308,7 +308,7 @@ private: */ bool GetScenarioInfo(const std::string &path, uint64 timestamp, scenario_index_entry * entry) { - log_verbose("GetScenarioInfo(%s, ...)", path); + log_verbose("GetScenarioInfo(%s, ...)", path.c_str()); try { std::string extension = Path::GetExtension(path); @@ -349,14 +349,14 @@ private: } else { - log_verbose("%s is not a scenario", path); + log_verbose("%s is not a scenario", path.c_str()); } } } } catch (Exception) { - Console::Error::WriteLine("Unable to read scenario: '%s'", path); + Console::Error::WriteLine("Unable to read scenario: '%s'", path.c_str()); } return false; } From 0a2b63eced9da71ba90c9bc9e7421670d217465a Mon Sep 17 00:00:00 2001 From: danidoedel Date: Wed, 1 Feb 2017 12:32:49 +0100 Subject: [PATCH 7/7] Update Xcode project --- OpenRCT2.xcodeproj/project.pbxproj | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 8cec0fb816..78fa044bbc 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 008BF72C1CDAA5C30019A2AD /* track_design.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7281CDAA5C30019A2AD /* track_design.c */; }; 00EFEE721CF1D80B0035213B /* NetworkKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00EFEE701CF1D80B0035213B /* NetworkKey.cpp */; }; 652076321E22EFE7000D0C04 /* Imaging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 652076301E22EFE7000D0C04 /* Imaging.cpp */; }; + 652747EC1E41CE1B000F36FD /* SawyerEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 652747EA1E41CE1B000F36FD /* SawyerEncoding.cpp */; }; 791166FB1D7486EF005912EA /* NetworkServerAdvertiser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */; }; 85060FD31D8C17CC00DFA2B3 /* track_data_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 8594C05F1D885CF600235E93 /* track_data_old.c */; }; 8594C0601D885CF600235E93 /* track_data_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 8594C05F1D885CF600235E93 /* track_data_old.c */; }; @@ -518,6 +519,8 @@ 00EFEE711CF1D80B0035213B /* NetworkKey.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; path = NetworkKey.h; sourceTree = ""; usesTabs = 0; }; 652076301E22EFE7000D0C04 /* Imaging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Imaging.cpp; sourceTree = ""; }; 652076311E22EFE7000D0C04 /* Imaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Imaging.h; sourceTree = ""; }; + 652747EA1E41CE1B000F36FD /* SawyerEncoding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SawyerEncoding.cpp; path = rct12/SawyerEncoding.cpp; sourceTree = ""; }; + 652747EB1E41CE1B000F36FD /* SawyerEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SawyerEncoding.h; path = rct12/SawyerEncoding.h; sourceTree = ""; }; 791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkServerAdvertiser.cpp; sourceTree = ""; }; 791166FA1D7486EF005912EA /* NetworkServerAdvertiser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServerAdvertiser.h; sourceTree = ""; }; 8594C05F1D885CF600235E93 /* track_data_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_data_old.c; sourceTree = ""; }; @@ -1235,6 +1238,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 652747E91E41CDFE000F36FD /* rct12 */ = { + isa = PBXGroup; + children = ( + 652747EA1E41CE1B000F36FD /* SawyerEncoding.cpp */, + 652747EB1E41CE1B000F36FD /* SawyerEncoding.h */, + ); + name = rct12; + sourceTree = ""; + }; 8546F74A1D7E1D220004004C /* Tests */ = { isa = PBXGroup; children = ( @@ -1513,6 +1525,7 @@ D442715B1CC81B3200D84D28 /* peep */, D44271601CC81B3200D84D28 /* platform */, C650B2141CCABBDD00B4D91C /* rct1 */, + 652747E91E41CDFE000F36FD /* rct12 */, C6B5A7CF1CDFE4CB00C9C006 /* rct2 */, D442716E1CC81B3200D84D28 /* ride */, C6E96E1C1E04070E0076A04F /* scenario */, @@ -2766,6 +2779,7 @@ D44272891CC81B3200D84D28 /* themes.c in Sources */, C686F9531CDBC3B7009F9BFC /* splash_boats.c in Sources */, C686F9441CDBC3B7009F9BFC /* pirate_ship.c in Sources */, + 652747EC1E41CE1B000F36FD /* SawyerEncoding.cpp in Sources */, D44272791CC81B3200D84D28 /* publisher_credits.c in Sources */, C686F91E1CDBC3B7009F9BFC /* reverse_freefall_coaster.c in Sources */, D442723B1CC81B3200D84D28 /* crash.cpp in Sources */,