diff --git a/src/openrct2/ParkImporter.cpp b/src/openrct2/ParkImporter.cpp index 6b20575930..3fe174a906 100644 --- a/src/openrct2/ParkImporter.cpp +++ b/src/openrct2/ParkImporter.cpp @@ -21,6 +21,65 @@ #include "object/ObjectRepository.h" #include "ParkImporter.h" +ParkLoadResult::ParkLoadResult(PARK_LOAD_ERROR error) + : Error(error) +{ +} + +ParkLoadResult::ParkLoadResult(PARK_LOAD_ERROR error, const std::vector &missingObjects) + : Error(error), + MissingObjects(missingObjects) +{ +} + +ParkLoadResult ParkLoadResult::CreateOK() +{ + return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_OK); +} + +ParkLoadResult ParkLoadResult::CreateInvalidExtension() +{ + return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_INVALID_EXTENSION); +} + +ParkLoadResult ParkLoadResult::CreateMissingObjects(const std::vector &missingObjects) +{ + return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_MISSING_OBJECTS, missingObjects); +} + +ParkLoadResult ParkLoadResult::CreateUnknown() +{ + return ParkLoadResult(PARK_LOAD_ERROR::PARK_LOAD_ERROR_UNKNOWN); +} + +extern "C" +{ + PARK_LOAD_ERROR ParkLoadResult_GetError(const ParkLoadResult * t) + { + return t->Error; + } + + size_t ParkLoadResult_GetMissingObjectsCount(const ParkLoadResult * t) + { + return t->MissingObjects.size(); + } + + const rct_object_entry * ParkLoadResult_GetMissingObjects(const ParkLoadResult * t) + { + return t->MissingObjects.data(); + } + + void ParkLoadResult_Delete(ParkLoadResult * t) + { + delete t; + } + + ParkLoadResult * ParkLoadResult_CreateInvalidExtension() + { + return new ParkLoadResult(ParkLoadResult::CreateInvalidExtension()); + } +} + namespace ParkImporter { IParkImporter * Create(const std::string &hintPath) diff --git a/src/openrct2/ParkImporter.h b/src/openrct2/ParkImporter.h index 7a0bee4e89..814cd9f45a 100644 --- a/src/openrct2/ParkImporter.h +++ b/src/openrct2/ParkImporter.h @@ -22,20 +22,45 @@ extern "C" { #endif -#include "park_load_result_types.h" + #include "object.h" #ifdef __cplusplus } #endif +typedef enum PARK_LOAD_ERROR +{ + PARK_LOAD_ERROR_OK, + PARK_LOAD_ERROR_MISSING_OBJECTS, + PARK_LOAD_ERROR_INVALID_EXTENSION, + PARK_LOAD_ERROR_UNKNOWN = 255 +} PARK_LOAD_ERROR; + #ifdef __cplusplus #include +#include #include "scenario/ScenarioRepository.h" interface IObjectManager; interface IObjectRepository; interface IStream; +struct ParkLoadResult final +{ +public: + const PARK_LOAD_ERROR Error; + const std::vector MissingObjects; + + static ParkLoadResult CreateOK(); + static ParkLoadResult CreateInvalidExtension(); + static ParkLoadResult CreateMissingObjects(const std::vector &missingObjects); + static ParkLoadResult CreateUnknown(); + +private: + ParkLoadResult(PARK_LOAD_ERROR error); + ParkLoadResult(PARK_LOAD_ERROR error, const std::vector &missingObjects); +}; + /** * Interface to import scenarios and saved games. */ @@ -43,10 +68,12 @@ interface IParkImporter { public: virtual ~IParkImporter() = default; - virtual park_load_result * Load(const utf8 * path) abstract; - virtual park_load_result * LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) abstract; - virtual park_load_result * LoadScenario(const utf8 * path, bool skipObjectCheck = false) abstract; - virtual park_load_result * LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) abstract; + + virtual ParkLoadResult Load(const utf8 * path) abstract; + virtual ParkLoadResult LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) abstract; + virtual ParkLoadResult LoadScenario(const utf8 * path, bool skipObjectCheck = false) abstract; + virtual ParkLoadResult LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) abstract; + virtual void Import() abstract; virtual bool GetDetails(scenario_index_entry * dst) abstract; }; @@ -61,6 +88,10 @@ namespace ParkImporter bool ExtensionIsScenario(const std::string &extension); } +#else + +typedef struct ParkLoadResult ParkLoadResult; + #endif #ifdef __cplusplus @@ -70,6 +101,11 @@ extern "C" void park_importer_load_from_stream(void * stream, const utf8 * hintPath); bool park_importer_extension_is_scenario(const utf8 * extension); + PARK_LOAD_ERROR ParkLoadResult_GetError(const ParkLoadResult * t); + size_t ParkLoadResult_GetMissingObjectsCount(const ParkLoadResult * t); + const rct_object_entry * ParkLoadResult_GetMissingObjects(const ParkLoadResult * t); + void ParkLoadResult_Delete(ParkLoadResult * t); + ParkLoadResult * ParkLoadResult_CreateInvalidExtension(); #ifdef __cplusplus } #endif diff --git a/src/openrct2/editor.c b/src/openrct2/editor.c index b9ab7e7f02..07c8c95d20 100644 --- a/src/openrct2/editor.c +++ b/src/openrct2/editor.c @@ -31,6 +31,7 @@ #include "platform/platform.h" #include "rct1.h" #include "ride/ride.h" +#include "ParkImporter.h" #include "scenario/scenario.h" #include "util/sawyercoding.h" #include "util/util.h" @@ -261,16 +262,18 @@ static sint32 editor_load_landscape_from_sc4(const char *path) */ static sint32 editor_read_s6(const char *path) { - park_load_result* loadResult = { 0 }; + ParkLoadResult * loadResult = NULL; const char *extension = path_get_extension(path); if (_stricmp(extension, ".sc6") == 0) { loadResult = scenario_load(path); } else if (_stricmp(extension, ".sv6") == 0) { loadResult = game_load_sv6_path(path); } - if (loadResult->error != PARK_LOAD_ERROR_NONE) { + if (ParkLoadResult_GetError(loadResult) != PARK_LOAD_ERROR_OK) { + ParkLoadResult_Delete(loadResult); return 0; } + ParkLoadResult_Delete(loadResult); editor_clear_map_for_editing(true); diff --git a/src/openrct2/game.c b/src/openrct2/game.c index e180737a03..9f7ecab429 100644 --- a/src/openrct2/game.c +++ b/src/openrct2/game.c @@ -33,6 +33,7 @@ #include "network/network.h" #include "object.h" #include "OpenRCT2.h" +#include "ParkImporter.h" #include "peep/peep.h" #include "peep/staff.h" #include "platform/platform.h" @@ -1094,15 +1095,16 @@ bool game_load_save(const utf8 *path) safe_strcpy(gScenarioSavePath, path, MAX_PATH); uint32 extension_type = get_file_extension_type(path); - park_load_result* result = {0}; + ParkLoadResult * result = NULL; bool load_success = false; if (extension_type == FILE_EXTENSION_SV6) { result = game_load_sv6_path(path); - load_success = (result->error == PARK_LOAD_ERROR_NONE); + load_success = (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK); if (load_success) gFirstTimeSaving = false; } else if (extension_type == FILE_EXTENSION_SV4) { - load_success = rct1_load_saved_game(path); + result = rct1_load_saved_game(path); + load_success = (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK); if (load_success) gFirstTimeSaving = true; } @@ -1126,20 +1128,20 @@ bool game_load_save(const utf8 *path) } } -void handle_park_load_failure(park_load_result* result, const utf8* path) +void handle_park_load_failure(const ParkLoadResult * result, const utf8 * path) { - if (result->error == PARK_LOAD_ERROR_BAD_OBJECTS) + if (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_MISSING_OBJECTS) { // The path needs to be duplicated as it's a const here // which the window function doesn't like - window_object_load_error_open(strndup(path, strnlen(path, MAX_PATH)), result->object_validity); - } - else if (result->error != PARK_LOAD_ERROR_NONE) { + window_object_load_error_open(strndup(path, strnlen(path, MAX_PATH)), + ParkLoadResult_GetMissingObjectsCount(result), + ParkLoadResult_GetMissingObjects(result)); + } else if (ParkLoadResult_GetError(result) != PARK_LOAD_ERROR_OK) { // If loading the SV6 or SV4 failed for a reason other than invalid objects // the current park state will be corrupted so just go back to the title screen. title_load(); } - SafeFree(result); } void game_load_init() @@ -1378,7 +1380,6 @@ void rct2_exit() bool game_load_save_or_scenario(const utf8 * path) { - park_load_result* result; uint32 extension = get_file_extension_type(path); switch (extension) { case FILE_EXTENSION_SV4: @@ -1386,8 +1387,12 @@ bool game_load_save_or_scenario(const utf8 * path) return game_load_save(path); case FILE_EXTENSION_SC4: case FILE_EXTENSION_SC6: - result = scenario_load_and_play_from_path(path); - return (result->error == PARK_LOAD_ERROR_NONE); + { + ParkLoadResult * result = scenario_load_and_play_from_path(path); + bool success = (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK); + ParkLoadResult_Delete(result); + return success; + } } return false; } diff --git a/src/openrct2/game.h b/src/openrct2/game.h index 9457e972fc..60614715f3 100644 --- a/src/openrct2/game.h +++ b/src/openrct2/game.h @@ -20,7 +20,6 @@ #include "rct2/addresses.h" #include "common.h" #include "scenario/scenario.h" -#include "park_load_result_types.h" enum GAME_COMMAND { GAME_COMMAND_SET_RIDE_APPEARANCE, @@ -171,7 +170,7 @@ sint32 game_do_command_p(sint32 command, sint32 *eax, sint32 *ebx, sint32 *ecx, void game_log_multiplayer_command(int command, int *eax, int* ebx, int* ecx, int* edx, int* edi, int* ebp); void game_load_or_quit_no_save_prompt(); -park_load_result * game_load_sv6_path(const char * path); +ParkLoadResult * game_load_sv6_path(const char * path); bool game_load_save(const utf8 *path); void game_load_init(); void game_pause_toggle(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 *edx, sint32 *esi, sint32 *edi, sint32 *ebp); @@ -180,7 +179,7 @@ bool game_is_paused(); bool game_is_not_paused(); void save_game(); void save_game_as(); -void handle_park_load_failure(park_load_result* result, const utf8* path); +void handle_park_load_failure(const ParkLoadResult * result, const utf8 * path); void rct2_exit(); void rct2_exit_reason(rct_string_id title, rct_string_id body); void game_autosave(); diff --git a/src/openrct2/interface/window.h b/src/openrct2/interface/window.h index 72525e131b..f38e7bcfe3 100644 --- a/src/openrct2/interface/window.h +++ b/src/openrct2/interface/window.h @@ -767,7 +767,7 @@ rct_window *window_mapgen_open(); rct_window *window_loadsave_open(sint32 type, char *defaultName); rct_window *window_changelog_open(); void window_debug_paint_open(); -rct_window *window_object_load_error_open(utf8* path, object_validity_result* result); +rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects); rct_window * window_editor_main_open(); void window_editor_bottom_toolbar_open(); diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index b4e77135e4..b1e0921cba 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -447,10 +447,10 @@ private: return duplicate; } - object_validity_result* GetInvalidObjects(const rct_object_entry * entries) override + std::vector GetInvalidObjects(const rct_object_entry * entries) override { - uint16 invalidObjectCount = 0; - rct_object_entry * * invalidEntries = Memory::AllocateArray(OBJECT_ENTRY_COUNT); + std::vector invalidEntries; + invalidEntries.reserve(OBJECT_ENTRY_COUNT); for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) { const rct_object_entry * entry = &entries[i]; @@ -460,7 +460,7 @@ private: ori = _objectRepository->FindObject(entry); if (ori == nullptr) { - invalidEntries[invalidObjectCount++] = DuplicateObjectEntry(entry); + invalidEntries.push_back(*entry); } else { @@ -471,16 +471,14 @@ private: loadedObject = _objectRepository->LoadObject(ori); if (loadedObject == nullptr) { - invalidEntries[invalidObjectCount++] = DuplicateObjectEntry(entry); + invalidEntries.push_back(*entry); } + delete loadedObject; } } } } - object_validity_result* result = Memory::Allocate(sizeof(object_validity_result)); - result->invalid_object_count = invalidObjectCount; - result->invalid_objects = invalidEntries; - return result; + return invalidEntries; } bool GetRequiredObjects(const rct_object_entry * entries, diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index d93f5bcda3..7aa837cea6 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -27,7 +27,6 @@ extern "C" { #endif #include "../object.h" - #include "../park_load_result_types.h" #ifdef __cplusplus } #endif @@ -42,10 +41,10 @@ interface IObjectManager { virtual ~IObjectManager() { } - virtual Object * GetLoadedObject(size_t index) abstract; - virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract; - virtual uint8 GetLoadedObjectEntryIndex(const Object * object) abstract; - virtual object_validity_result* GetInvalidObjects(const rct_object_entry * entries) abstract; + virtual Object * GetLoadedObject(size_t index) abstract; + virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract; + virtual uint8 GetLoadedObjectEntryIndex(const Object * object) abstract; + virtual std::vector GetInvalidObjects(const rct_object_entry * entries) abstract; virtual Object * LoadObject(const rct_object_entry * entry) abstract; virtual bool LoadObjects(const rct_object_entry * entries, size_t count) abstract; diff --git a/src/openrct2/park_load_result_types.h b/src/openrct2/park_load_result_types.h deleted file mode 100644 index 6e43388c6b..0000000000 --- a/src/openrct2/park_load_result_types.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma region Copyright (c) 2014-2017 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 - -#ifndef _PARK_LOAD_RESULT_H_ -#define _PARK_LOAD_RESULT_H_ - -#include "object.h" - -enum PARK_LOAD_ERROR { - PARK_LOAD_ERROR_NONE, - PARK_LOAD_ERROR_BAD_OBJECTS, - PARK_LOAD_ERROR_INVALID_EXTENSION, - PARK_LOAD_ERROR_UNKNOWN = 255 -}; - -typedef struct object_validity_result -{ - uint16 invalid_object_count; - rct_object_entry * * invalid_objects; - -} object_validity_result; - -typedef struct park_load_result { - uint8 error; - object_validity_result* object_validity; -} park_load_result; -#endif diff --git a/src/openrct2/rct1.h b/src/openrct2/rct1.h index 0126015adc..3135da565b 100644 --- a/src/openrct2/rct1.h +++ b/src/openrct2/rct1.h @@ -20,7 +20,6 @@ #include "management/award.h" #include "management/news_item.h" #include "management/research.h" -#include "park_load_result_types.h" #include "rct12.h" #include "rct2.h" #include "ride/ride.h" @@ -35,6 +34,8 @@ #define RCT1_MAX_RIDES_IN_PARK 128 #define RCT1_RESEARCH_FLAGS_SEPARATOR 0xFF +typedef struct ParkLoadResult ParkLoadResult; + #pragma pack(push, 1) typedef struct rct1_entrance { uint16 x; @@ -1210,8 +1211,8 @@ extern const uint8 gRideCategories[RIDE_TYPE_COUNT]; sint32 vehicle_preference_compare(uint8 rideType, const char * a, const char * b); bool rideTypeShouldLoseSeparateFlag(const rct_ride_entry *rideEntry); -park_load_result * rct1_load_saved_game(const char *path); -park_load_result * rct1_load_scenario(const char *path); +ParkLoadResult * rct1_load_saved_game(const char *path); +ParkLoadResult * rct1_load_scenario(const char *path); colour_t rct1_get_colour(colour_t colour); diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 0666430295..b7a99d4c01 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -26,6 +26,7 @@ #include "../core/Path.hpp" #include "../core/String.hpp" #include "../core/Util.hpp" +#include "../object/Object.h" #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" #include "../ParkImporter.h" @@ -126,7 +127,7 @@ private: uint8 _researchRideTypeUsed[128]; public: - park_load_result* Load(const utf8 * path) override + ParkLoadResult Load(const utf8 * path) override { const utf8 * extension = Path::GetExtension(path); if (String::Equals(extension, ".sc4", true)) @@ -143,27 +144,24 @@ public: } } - park_load_result* LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override + ParkLoadResult LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override { auto fs = FileStream(path, FILE_MODE_OPEN); - park_load_result* result = LoadFromStream(&fs, false, skipObjectCheck); + auto result = LoadFromStream(&fs, false, skipObjectCheck); _s4Path = path; return result; } - park_load_result* LoadScenario(const utf8 * path, bool skipObjectCheck = false) override + ParkLoadResult LoadScenario(const utf8 * path, bool skipObjectCheck = false) override { auto fs = FileStream(path, FILE_MODE_OPEN); - park_load_result* result = LoadFromStream(&fs, true, skipObjectCheck); + auto result = LoadFromStream(&fs, true, skipObjectCheck); _s4Path = path; return result; } - park_load_result* LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override + ParkLoadResult LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override { - park_load_result* result = Memory::Allocate(sizeof(park_load_result)); - result->error = PARK_LOAD_ERROR_NONE; - size_t dataSize = stream->GetLength() - stream->GetPosition(); std::unique_ptr data = std::unique_ptr(stream->ReadArray(dataSize)); std::unique_ptr decodedData = std::unique_ptr(Memory::Allocate(sizeof(rct1_s4))); @@ -188,12 +186,11 @@ public: { InitialiseEntryMaps(); CreateAvailableObjectMappings(); - object_validity_result* object_result = GetInvalidObjects(); - result->object_validity = object_result; - if (object_result->invalid_object_count > 0) + auto missingObjects = GetInvalidObjects(); + if (missingObjects.size() > 0) { - result->error = PARK_LOAD_ERROR_BAD_OBJECTS; + return ParkLoadResult::CreateMissingObjects(missingObjects); } } } @@ -201,7 +198,7 @@ public: { throw Exception("Unable to decode park."); } - return result; + return ParkLoadResult::CreateOK(); } void Import() override @@ -1751,22 +1748,16 @@ private: } } - object_validity_result* GetInvalidObjects() + std::vector GetInvalidObjects() { - object_validity_result* result = Memory::Allocate(sizeof(object_validity_result)); - uint16 invalidObjectCount = 0; - rct_object_entry * * invalidEntries = Memory::AllocateArray(OBJECT_ENTRY_COUNT); - - result->invalid_object_count = invalidObjectCount; - result->invalid_objects = invalidEntries; - - GetInvalidObjects(OBJECT_TYPE_RIDE, _rideEntries.GetEntries(), *result); - GetInvalidObjects(OBJECT_TYPE_SMALL_SCENERY, _smallSceneryEntries.GetEntries(), *result); - GetInvalidObjects(OBJECT_TYPE_LARGE_SCENERY, _largeSceneryEntries.GetEntries(), *result); - GetInvalidObjects(OBJECT_TYPE_WALLS, _wallEntries.GetEntries(), *result); - GetInvalidObjects(OBJECT_TYPE_PATHS, _pathEntries.GetEntries(), *result); - GetInvalidObjects(OBJECT_TYPE_PATH_BITS, _pathAdditionEntries.GetEntries(), *result); - GetInvalidObjects(OBJECT_TYPE_SCENERY_SETS, _sceneryGroupEntries.GetEntries(), *result); + std::vector missingObjects; + GetInvalidObjects(OBJECT_TYPE_RIDE, _rideEntries.GetEntries(), missingObjects); + GetInvalidObjects(OBJECT_TYPE_SMALL_SCENERY, _smallSceneryEntries.GetEntries(), missingObjects); + GetInvalidObjects(OBJECT_TYPE_LARGE_SCENERY, _largeSceneryEntries.GetEntries(), missingObjects); + GetInvalidObjects(OBJECT_TYPE_WALLS, _wallEntries.GetEntries(), missingObjects); + GetInvalidObjects(OBJECT_TYPE_PATHS, _pathEntries.GetEntries(), missingObjects); + GetInvalidObjects(OBJECT_TYPE_PATH_BITS, _pathAdditionEntries.GetEntries(), missingObjects); + GetInvalidObjects(OBJECT_TYPE_SCENERY_SETS, _sceneryGroupEntries.GetEntries(), missingObjects); GetInvalidObjects(OBJECT_TYPE_BANNERS, std::vector({ "BN1 ", "BN2 ", @@ -1777,14 +1768,13 @@ private: "BN7 ", "BN8 ", "BN9 " - }), *result); - GetInvalidObjects(OBJECT_TYPE_PARK_ENTRANCE, std::vector({ "PKENT1 " }), *result); - GetInvalidObjects(OBJECT_TYPE_WATER, _waterEntry.GetEntries(), *result); - - return result; + }), missingObjects); + GetInvalidObjects(OBJECT_TYPE_PARK_ENTRANCE, std::vector({ "PKENT1 " }), missingObjects); + GetInvalidObjects(OBJECT_TYPE_WATER, _waterEntry.GetEntries(), missingObjects); + return missingObjects; } - void GetInvalidObjects(uint8 objectType, const std::vector &entries, object_validity_result &result) + void GetInvalidObjects(uint8 objectType, const std::vector &entries, std::vector &missingObjects) { IObjectRepository * objectRepository = GetObjectRepository(); for (const char * objectName : entries) @@ -1794,26 +1784,19 @@ private: Memory::Copy(entry.name, objectName, 8); entry.checksum = 0; - const ObjectRepositoryItem * ori = nullptr; - ori = objectRepository->FindObject(&entry); + const ObjectRepositoryItem * ori = objectRepository->FindObject(&entry); if (ori == nullptr) { - rct_object_entry * invalid_entry = Memory::Allocate(sizeof(rct_object_entry)); - invalid_entry->flags = entry.flags; - Memory::Copy(invalid_entry->name, objectName, 8); - result.invalid_objects[result.invalid_object_count++] = invalid_entry; + missingObjects.push_back(entry); } else { Object * object = objectRepository->LoadObject(ori); if (object == nullptr && objectType != OBJECT_TYPE_SCENERY_SETS) { - rct_object_entry * invalid_entry = Memory::Allocate(sizeof(rct_object_entry)); - invalid_entry->flags = entry.flags; - Memory::Copy(invalid_entry->name, objectName, 8); - result.invalid_objects[result.invalid_object_count++] = invalid_entry; + missingObjects.push_back(entry); } - SafeFree(object); + delete object; } } } @@ -2661,46 +2644,43 @@ IParkImporter * ParkImporter::CreateS4() ///////////////////////////////////////// extern "C" { - park_load_result* rct1_load_saved_game(const utf8 * path) + ParkLoadResult * rct1_load_saved_game(const utf8 * path) { - park_load_result* result = {}; - - auto s4Importer = new S4Importer(); + ParkLoadResult * result = nullptr; + auto s4Importer = std::make_unique(); try { - result = s4Importer->LoadSavedGame(path); - if (result->error == PARK_LOAD_ERROR_NONE) + result = new ParkLoadResult(s4Importer->LoadSavedGame(path)); + if (result->Error == PARK_LOAD_ERROR_OK) { s4Importer->Import(); } - - } catch (const Exception &) - { - result = {}; - result->error = PARK_LOAD_ERROR_UNKNOWN; } - delete s4Importer; + catch (const Exception &) + { + delete result; + result = new ParkLoadResult(ParkLoadResult::CreateUnknown()); + } return result; } - park_load_result* rct1_load_scenario(const utf8 * path) + ParkLoadResult * rct1_load_scenario(const utf8 * path) { - park_load_result* result = {}; - - auto s4Importer = new S4Importer(); + ParkLoadResult * result = nullptr; + auto s4Importer = std::make_unique(); try { - result = s4Importer->LoadSavedGame(path); - if (result->error == PARK_LOAD_ERROR_NONE) + result = new ParkLoadResult(s4Importer->LoadSavedGame(path)); + if (result->Error == PARK_LOAD_ERROR_OK) { s4Importer->Import(); } - } catch (const Exception &) - { - result = {}; - result->error = PARK_LOAD_ERROR_UNKNOWN; } - delete s4Importer; + catch (const Exception &) + { + delete result; + result = new ParkLoadResult(ParkLoadResult::CreateUnknown()); + } return result; } diff --git a/src/openrct2/rct2.c b/src/openrct2/rct2.c index 89fe7de289..7179ef7dfb 100644 --- a/src/openrct2/rct2.c +++ b/src/openrct2/rct2.c @@ -38,6 +38,7 @@ #include "object.h" #include "object/ObjectManager.h" #include "OpenRCT2.h" +#include "ParkImporter.h" #include "peep/staff.h" #include "platform/platform.h" #include "rct1.h" @@ -339,12 +340,13 @@ bool rct2_open_file(const char *path) } } else if (_stricmp(extension, "sc6") == 0) { // TODO scenario install - park_load_result *result = scenario_load_and_play_from_path(path); - if (result->error == PARK_LOAD_ERROR_NONE) { + ParkLoadResult * result = scenario_load_and_play_from_path(path); + if (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK) { + ParkLoadResult_Delete(result); return true; - } - else { + } else { handle_park_load_failure(result, path); + ParkLoadResult_Delete(result); return false; } } else if (_stricmp(extension, "td6") == 0 || _stricmp(extension, "td4") == 0) { diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 9ca6083054..53ac9a2971 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -81,7 +81,7 @@ public: Memory::Set(&_s6, 0, sizeof(_s6)); } - park_load_result* Load(const utf8 * path) override + ParkLoadResult Load(const utf8 * path) override { const utf8 * extension = Path::GetExtension(path); if (String::Equals(extension, ".sc6", true)) @@ -98,29 +98,24 @@ public: } } - park_load_result* LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override + ParkLoadResult LoadSavedGame(const utf8 * path, bool skipObjectCheck = false) override { auto fs = FileStream(path, FILE_MODE_OPEN); - park_load_result* result = LoadFromStream(&fs, false, skipObjectCheck); + auto result = LoadFromStream(&fs, false, skipObjectCheck); _s6Path = path; - return result; } - park_load_result* LoadScenario(const utf8 * path, bool skipObjectCheck = false) override + ParkLoadResult LoadScenario(const utf8 * path, bool skipObjectCheck = false) override { auto fs = FileStream(path, FILE_MODE_OPEN); - park_load_result* result = LoadFromStream(&fs, true, skipObjectCheck); + auto result = LoadFromStream(&fs, true, skipObjectCheck); _s6Path = path; - return result; } - park_load_result* LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override + ParkLoadResult LoadFromStream(IStream * stream, bool isScenario, bool skipObjectCheck = false) override { - park_load_result* result = Memory::Allocate(sizeof(park_load_result)); - result->error = PARK_LOAD_ERROR_UNKNOWN; - if (isScenario && !gConfigGeneral.allow_loading_with_incorrect_checksum && !SawyerEncoding::ValidateChecksum(stream)) { throw IOException("Invalid checksum."); @@ -175,18 +170,12 @@ public: chunkReader.ReadChunk(&_s6.next_free_map_element_pointer_index, 3048816); } - object_validity_result* object_result = _objectManager->GetInvalidObjects(_s6.objects); - - result->object_validity = object_result; - if (object_result->invalid_object_count > 0) + auto missingObjects = _objectManager->GetInvalidObjects(_s6.objects); + if (missingObjects.size() > 0) { - result->error = PARK_LOAD_ERROR_BAD_OBJECTS; + return ParkLoadResult::CreateMissingObjects(missingObjects); } - else - { - result->error = PARK_LOAD_ERROR_NONE; - } - return result; + return ParkLoadResult::CreateOK(); } bool GetDetails(scenario_index_entry * dst) override @@ -439,17 +428,17 @@ IParkImporter * ParkImporter::CreateS6(IObjectRepository * objectRepository, IOb extern "C" { - park_load_result* game_load_sv6_path(const char * path) + ParkLoadResult * game_load_sv6_path(const char * path) { - park_load_result* result = {}; + ParkLoadResult * result = nullptr; auto s6Importer = new S6Importer(GetObjectRepository(), GetObjectManager()); try { - result = s6Importer->LoadSavedGame(path); + result = new ParkLoadResult(s6Importer->LoadSavedGame(path)); // We mustn't import if there's something // wrong with the park data - if (result->error == PARK_LOAD_ERROR_NONE) + if (result->Error == PARK_LOAD_ERROR_OK) { s6Importer->Import(); @@ -474,7 +463,11 @@ extern "C" } delete s6Importer; - if (result->error == PARK_LOAD_ERROR_NONE) + if (result == nullptr) + { + result = new ParkLoadResult(ParkLoadResult::CreateUnknown()); + } + if (result->Error == PARK_LOAD_ERROR_OK) { gScreenAge = 0; gLastAutoSaveUpdate = AUTOSAVE_PAUSE; @@ -487,14 +480,14 @@ extern "C" * rct2: 0x00676053 * scenario (ebx) */ - park_load_result* scenario_load(const char * path) + ParkLoadResult * scenario_load(const char * path) { - park_load_result* result = {}; + ParkLoadResult * result = nullptr; auto s6Importer = new S6Importer(GetObjectRepository(), GetObjectManager()); try { - result = s6Importer->LoadScenario(path); - if (result->error == PARK_LOAD_ERROR_NONE) + result = new ParkLoadResult(s6Importer->LoadScenario(path)); + if (result->Error == PARK_LOAD_ERROR_OK) { s6Importer->Import(); @@ -518,7 +511,12 @@ extern "C" gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA; } delete s6Importer; - if (result->error != PARK_LOAD_ERROR_NONE) + + if (result == nullptr) + { + result = new ParkLoadResult(ParkLoadResult::CreateUnknown()); + } + if (result->Error != PARK_LOAD_ERROR_OK) { gScreenAge = 0; gLastAutoSaveUpdate = AUTOSAVE_PAUSE; diff --git a/src/openrct2/scenario/scenario.c b/src/openrct2/scenario/scenario.c index 17ca3d4677..2e1a7d6277 100644 --- a/src/openrct2/scenario/scenario.c +++ b/src/openrct2/scenario/scenario.c @@ -30,6 +30,7 @@ #include "../object.h" #include "../object_list.h" #include "../OpenRCT2.h" +#include "../ParkImporter.h" #include "../peep/staff.h" #include "../platform/platform.h" #include "../rct1.h" @@ -88,28 +89,24 @@ money32 gScenarioCompanyValueRecord; static sint32 scenario_create_ducks(); static void scenario_objective_check(); -park_load_result* scenario_load_and_play_from_path(const char *path) +ParkLoadResult * scenario_load_and_play_from_path(const char * path) { window_close_construction_windows(); uint32 extension = get_file_extension_type(path); - park_load_result* result = malloc(sizeof(park_load_result)); + ParkLoadResult * result = NULL; if (extension == FILE_EXTENSION_SC6) { result = scenario_load(path); - if (result->error != PARK_LOAD_ERROR_NONE) - { + if (ParkLoadResult_GetError(result) != PARK_LOAD_ERROR_OK) { return result; } - } - else if (extension == FILE_EXTENSION_SC4) { + } else if (extension == FILE_EXTENSION_SC4) { result = rct1_load_scenario(path); - if (result->error != PARK_LOAD_ERROR_NONE) - { + if (ParkLoadResult_GetError(result) != PARK_LOAD_ERROR_OK) { return result; } - } - else { - result->error = PARK_LOAD_ERROR_INVALID_EXTENSION; + } else { + result = ParkLoadResult_CreateInvalidExtension(); return result; } diff --git a/src/openrct2/scenario/scenario.h b/src/openrct2/scenario/scenario.h index 13db64199b..f592b001e6 100644 --- a/src/openrct2/scenario/scenario.h +++ b/src/openrct2/scenario/scenario.h @@ -21,7 +21,6 @@ #include "../management/finance.h" #include "../management/research.h" #include "../object.h" -#include "../park_load_result_types.h" #include "../rct12.h" #include "../rct2.h" #include "../rct2/addresses.h" @@ -32,6 +31,8 @@ #include "../world/map_animation.h" #include "../world/sprite.h" +typedef struct ParkLoadResult ParkLoadResult; + #pragma pack(push, 1) /** * SV6/SC6 header chunk @@ -390,8 +391,8 @@ extern uint32 gLastAutoSaveUpdate; extern const char *_scenarioFileName; -park_load_result *scenario_load(const char *path); -park_load_result *scenario_load_and_play_from_path(const char *path); +ParkLoadResult * scenario_load(const char *path); +ParkLoadResult * scenario_load_and_play_from_path(const char *path); void scenario_begin(); void scenario_update(); diff --git a/src/openrct2/util/util.h b/src/openrct2/util/util.h index 1ada3c6a5d..16a1eb64a0 100644 --- a/src/openrct2/util/util.h +++ b/src/openrct2/util/util.h @@ -19,7 +19,6 @@ #include #include "../common.h" -#include "../park_load_result_types.h" sint32 squaredmetres_to_squaredfeet(sint32 squaredMetres); sint32 metres_to_feet(sint32 metres); diff --git a/src/openrct2/windows/object_load_error.c b/src/openrct2/windows/object_load_error.c index 659c368cc7..64de98ac6e 100644 --- a/src/openrct2/windows/object_load_error.c +++ b/src/openrct2/windows/object_load_error.c @@ -21,7 +21,6 @@ #include "../object.h" #include "../platform/platform.h" #include "../sprites.h" -#include "../util/util.h" enum WINDOW_OBJECT_LOAD_ERROR_WIDGET_IDX { WIDX_BACKGROUND, @@ -91,7 +90,7 @@ static rct_window_event_list window_object_load_error_events = { window_object_load_error_scrollpaint }; -rct_object_entry * * invalid_entries = NULL; +rct_object_entry * invalid_entries = NULL; sint32 highlighted_index = -1; utf8* file_path = NULL; @@ -168,20 +167,20 @@ static utf8* combine_object_names(rct_window *w) for (uint16 i = 0; i < w->no_list_items; i++) { cur_len += (8 + line_sep_len); assert(cur_len < buffer_len); - strncat(buffer, invalid_entries[i]->name, 8); + strncat(buffer, invalid_entries[i].name, 8); strncat(buffer, PLATFORM_NEWLINE, line_sep_len); } return buffer; } -rct_window *window_object_load_error_open(utf8* path, object_validity_result* result) +rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects) { - rct_window* window; - - invalid_entries = result->invalid_objects; + size_t missingObjectsSize = numMissingObjects * sizeof(rct_object_entry); + invalid_entries = malloc(missingObjectsSize); + memcpy(invalid_entries, missingObjects, missingObjectsSize); // Check if window is already open - window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR); + rct_window * window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR); if (window == NULL) { window = window_create_centred( WW, @@ -201,7 +200,7 @@ rct_window *window_object_load_error_open(utf8* path, object_validity_result* re } // Refresh list items and path - window->no_list_items = result->invalid_object_count; + window->no_list_items = (uint16)numMissingObjects; file_path = path; window_invalidate(window); @@ -232,7 +231,7 @@ static void window_object_load_error_mouseup(rct_window *w, rct_widgetindex widg break; case WIDX_COPY_CURRENT: if (w->selected_list_item > -1) { - selected_name = strndup(invalid_entries[w->selected_list_item]->name, 8); + selected_name = strndup(invalid_entries[w->selected_list_item].name, 8); platform_place_string_on_clipboard(selected_name); SafeFree(selected_name); } @@ -296,7 +295,6 @@ static void window_object_load_error_paint(rct_window *w, rct_drawpixelinfo *dpi static void window_object_load_error_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex) { - gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ColourMapA[w->colours[1]].mid_light); const sint32 list_width = w->widgets[WIDX_SCROLL].right - w->widgets[WIDX_SCROLL].left; @@ -317,12 +315,10 @@ static void window_object_load_error_scrollpaint(rct_window *w, rct_drawpixelinf gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000); // Draw the actual object entry's name... - gfx_draw_string(dpi, strndup(invalid_entries[i]->name, 8), COLOUR_DARK_GREEN, 5, y); + gfx_draw_string(dpi, strndup(invalid_entries[i].name, 8), COLOUR_DARK_GREEN, 5, y); // ... and type - rct_string_id type = get_object_type_string(invalid_entries[i]); + rct_string_id type = get_object_type_string(&invalid_entries[i]); gfx_draw_string_left(dpi, type, NULL, COLOUR_DARK_GREEN, (WW - 5) / 3 + 1, y); } - - } diff --git a/src/openrct2/windows/server_start.c b/src/openrct2/windows/server_start.c index 54bac250b5..d2f4bcc4c8 100644 --- a/src/openrct2/windows/server_start.c +++ b/src/openrct2/windows/server_start.c @@ -21,6 +21,7 @@ #include "../interface/window.h" #include "../localisation/localisation.h" #include "../network/network.h" +#include "../ParkImporter.h" #include "../platform/platform.h" #include "../sprites.h" #include "../title/TitleScreen.h" @@ -165,14 +166,14 @@ static void window_server_start_close(rct_window *w) static void window_server_start_scenarioselect_callback(const utf8 *path) { - park_load_result* result; network_set_password(_password); - result = scenario_load_and_play_from_path(path); - if (result->error == PARK_LOAD_ERROR_NONE) { + ParkLoadResult * result = scenario_load_and_play_from_path(path); + if (ParkLoadResult_GetError(result) == PARK_LOAD_ERROR_OK) { network_begin_server(gConfigNetwork.default_port, gConfigNetwork.listen_address); } else { handle_park_load_failure(result, path); } + ParkLoadResult_Delete(result); } static void window_server_start_loadsave_callback(sint32 result, const utf8 * path) diff --git a/src/openrct2/windows/title_menu.c b/src/openrct2/windows/title_menu.c index a722cc8781..b5b0c52308 100644 --- a/src/openrct2/windows/title_menu.c +++ b/src/openrct2/windows/title_menu.c @@ -22,6 +22,7 @@ #include "../interface/widget.h" #include "../interface/window.h" #include "../localisation/localisation.h" +#include "../ParkImporter.h" #include "../sprites.h" #include "../title/TitleScreen.h" #include "../util/util.h" @@ -129,8 +130,9 @@ void window_title_menu_open() static void window_title_menu_scenarioselect_callback(const utf8 *path) { - park_load_result *result = scenario_load_and_play_from_path(path); + ParkLoadResult * result = scenario_load_and_play_from_path(path); handle_park_load_failure(result, path); + ParkLoadResult_Delete(result); } static void window_title_menu_mouseup(rct_window *w, rct_widgetindex widgetIndex) diff --git a/src/openrct2/windows/top_toolbar.c b/src/openrct2/windows/top_toolbar.c index c05751e896..abea8d1be7 100644 --- a/src/openrct2/windows/top_toolbar.c +++ b/src/openrct2/windows/top_toolbar.c @@ -30,6 +30,7 @@ #include "../localisation/localisation.h" #include "../network/network.h" #include "../network/twitch.h" +#include "../ParkImporter.h" #include "../peep/staff.h" #include "../scenario/scenario.h" #include "../sprites.h" @@ -519,8 +520,9 @@ static void window_top_toolbar_mousedown(rct_widgetindex widgetIndex, rct_window static void window_top_toolbar_scenarioselect_callback(const utf8 *path) { - park_load_result *result = scenario_load_and_play_from_path(path); + ParkLoadResult * result = scenario_load_and_play_from_path(path); handle_park_load_failure(result, path); + ParkLoadResult_Delete(result); } /**