mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-16 03:23:15 +01:00
Merge pull request #5145 from IntelOrca/feature/rct1-scenario-select
Enable RCT1 SC4s for scenario select
This commit is contained in:
@@ -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 = "<group>"; usesTabs = 0; };
|
||||
652076301E22EFE7000D0C04 /* Imaging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Imaging.cpp; sourceTree = "<group>"; };
|
||||
652076311E22EFE7000D0C04 /* Imaging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Imaging.h; sourceTree = "<group>"; };
|
||||
652747EA1E41CE1B000F36FD /* SawyerEncoding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SawyerEncoding.cpp; path = rct12/SawyerEncoding.cpp; sourceTree = "<group>"; };
|
||||
652747EB1E41CE1B000F36FD /* SawyerEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SawyerEncoding.h; path = rct12/SawyerEncoding.h; sourceTree = "<group>"; };
|
||||
791166F91D7486EF005912EA /* NetworkServerAdvertiser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkServerAdvertiser.cpp; sourceTree = "<group>"; };
|
||||
791166FA1D7486EF005912EA /* NetworkServerAdvertiser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkServerAdvertiser.h; sourceTree = "<group>"; };
|
||||
8594C05F1D885CF600235E93 /* track_data_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_data_old.c; sourceTree = "<group>"; };
|
||||
@@ -1235,6 +1238,15 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
652747E91E41CDFE000F36FD /* rct12 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
652747EA1E41CE1B000F36FD /* SawyerEncoding.cpp */,
|
||||
652747EB1E41CE1B000F36FD /* SawyerEncoding.h */,
|
||||
);
|
||||
name = rct12;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 */,
|
||||
|
||||
@@ -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<sawyercoding_chunk_header>();
|
||||
switch (header.encoding) {
|
||||
case CHUNK_ENCODING_NONE:
|
||||
case CHUNK_ENCODING_RLE:
|
||||
case CHUNK_ENCODING_RLECOMPRESSED:
|
||||
case CHUNK_ENCODING_ROTATE:
|
||||
uint8 * compressedData = Memory::Allocate<uint8>(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;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<ClCompile Include="audio\MemoryAudioSource.cpp" />
|
||||
<ClCompile Include="audio\NullAudioSource.cpp" />
|
||||
<ClCompile Include="FileClassifier.cpp" />
|
||||
<ClCompile Include="rct12\SawyerEncoding.cpp" />
|
||||
<ClCompile Include="rct2\addresses.c" />
|
||||
<ClCompile Include="audio\audio.c" />
|
||||
<ClCompile Include="cheats.c" />
|
||||
@@ -414,6 +415,7 @@
|
||||
<ClInclude Include="audio\AudioSource.h" />
|
||||
<ClInclude Include="FileClassifier.h" />
|
||||
<ClInclude Include="rct12.h" />
|
||||
<ClInclude Include="rct12\SawyerEncoding.h" />
|
||||
<ClInclude Include="rct2\addresses.h" />
|
||||
<ClInclude Include="audio\audio.h" />
|
||||
<ClInclude Include="cheats.h" />
|
||||
@@ -596,4 +598,4 @@
|
||||
<Image Include="..\..\resources\logo\icon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -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()
|
||||
{
|
||||
@@ -185,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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
57
src/openrct2/rct12/SawyerEncoding.cpp
Normal file
57
src/openrct2/rct12/SawyerEncoding.cpp
Normal file
@@ -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<sawyercoding_chunk_header>();
|
||||
switch (header.encoding) {
|
||||
case CHUNK_ENCODING_NONE:
|
||||
case CHUNK_ENCODING_RLE:
|
||||
case CHUNK_ENCODING_RLECOMPRESSED:
|
||||
case CHUNK_ENCODING_ROTATE:
|
||||
uint8 * compressedData = Memory::Allocate<uint8>(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;
|
||||
}
|
||||
}
|
||||
32
src/openrct2/rct12/SawyerEncoding.h
Normal file
32
src/openrct2/rct12/SawyerEncoding.h
Normal file
@@ -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<typename T>
|
||||
bool TryReadChunk(T * dst, IStream * stream)
|
||||
{
|
||||
return TryReadChunk(dst, sizeof(T), stream);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@
|
||||
#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"
|
||||
|
||||
@@ -142,8 +144,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 +257,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,49 +269,104 @@ 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))
|
||||
scenario_index_entry entry;
|
||||
if (!GetScenarioInfo(path, timestamp, &entry))
|
||||
{
|
||||
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 = entry;
|
||||
}
|
||||
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);
|
||||
_scenarios.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
scenario_index_entry CreateNewScenarioEntry(const utf8 * path, uint64 timestamp, rct_s6_info * s6Info)
|
||||
/**
|
||||
* Reads basic information from a scenario file.
|
||||
*/
|
||||
bool GetScenarioInfo(const std::string &path, uint64 timestamp, scenario_index_entry * entry)
|
||||
{
|
||||
log_verbose("GetScenarioInfo(%s, ...)", path.c_str());
|
||||
try
|
||||
{
|
||||
std::string extension = Path::GetExtension(path);
|
||||
if (String::Equals(extension, ".sc4", true))
|
||||
{
|
||||
// RCT1 scenario
|
||||
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)
|
||||
{
|
||||
rct_s6_info info;
|
||||
if (SawyerEncoding::TryReadChunk(&info, &fs))
|
||||
{
|
||||
*entry = CreateNewScenarioEntry(path, timestamp, &info);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Unable to read S6_INFO chunk.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_verbose("%s is not a scenario", path.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to read scenario: '%s'", path.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user