From 78e15b1d56207c6da99afd5b0b0bed8555f2f08a Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 25 Jun 2016 16:34:35 +0100 Subject: [PATCH] start getting object loading working --- openrct2.vcxproj | 2 + src/drawing/drawing.h | 2 + src/drawing/sprite.c | 23 +++++++++ src/localisation/language.cpp | 13 +++++ src/localisation/language.h | 2 + src/object.c | 2 +- src/object/EntranceObject.cpp | 11 ++++- src/object/ImageTable.h | 4 +- src/object/Object.h | 3 +- src/object/ObjectFactory.cpp | 6 ++- src/object/ObjectFactory.h | 2 +- src/object/ObjectRepository.cpp | 88 +++++++++++++++++++++++++++++++++ src/object/ObjectRepository.h | 3 +- src/object/StexObject.cpp | 77 +++++++++++++++++++++++++++++ src/object/StexObject.h | 45 +++++++++++++++++ src/scenario.h | 2 + src/scenario_list.c | 24 --------- 17 files changed, 277 insertions(+), 32 deletions(-) create mode 100644 src/object/StexObject.cpp create mode 100644 src/object/StexObject.h diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 34dfd4296f..78e43f5706 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -123,6 +123,7 @@ + @@ -429,6 +430,7 @@ + diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 04367bc40e..4c0d568ea8 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -176,6 +176,8 @@ int gfx_load_g2(); void gfx_unload_g1(); void gfx_unload_g2(); rct_g1_element* gfx_get_g1_element(int image_id); +uint32 gfx_object_allocate_images(const rct_g1_element * images, uint32 count); +void gfx_object_free_images(uint32 baseImageId, uint32 count); void sub_68371D(); void FASTCALL gfx_rle_sprite_to_buffer(const uint8* RESTRICT source_bits_pointer, uint8* RESTRICT dest_bits_pointer, const uint8* RESTRICT palette_pointer, const rct_drawpixelinfo * RESTRICT dpi, int image_type, int source_y_start, int height, int source_x_start, int width); void FASTCALL gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index 26458bb1ab..0c16ef28cc 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -173,6 +173,29 @@ int gfx_load_g2() return 0; } +static uint32 _nextImageId = 29294; + +uint32 gfx_object_allocate_images(const rct_g1_element * images, uint32 count) +{ + uint32 baseImageId = _nextImageId; + for (uint32 i = 0; i < count; i++) { + uint32 imageId = _nextImageId; + if (imageId >= 291438) { + log_error("Reached maximum image limit."); + break; + } + + g1Elements[imageId] = images[i]; + drawing_engine_invalidate_image(imageId); + _nextImageId++; + } + return baseImageId; +} + +void gfx_object_free_images(uint32 baseImageId, uint32 count) +{ +} + /** * This function looks like it initialises the 0x009E3CE4 array which references sprites used for background / palette mixing or * something. Further investigation is needed. diff --git a/src/localisation/language.cpp b/src/localisation/language.cpp index 43c9e635f0..70f357c162 100644 --- a/src/localisation/language.cpp +++ b/src/localisation/language.cpp @@ -455,4 +455,17 @@ bool language_get_localised_scenario_strings(const utf8 *scenarioFilename, rct_s outStringIds[2] != STR_NONE; } +static rct_string_id _nextObjectStringId = NONSTEX_BASE_STRING_ID; + +rct_string_id language_allocate_object_string(const utf8 * target) +{ + rct_string_id stringId = _nextObjectStringId++; + _languageCurrent->SetString(stringId, target); + return stringId; +} + +void language_free_object_string(rct_string_id stringId) +{ +} + } diff --git a/src/localisation/language.h b/src/localisation/language.h index 8e2d1f8511..4bcab7a61f 100644 --- a/src/localisation/language.h +++ b/src/localisation/language.h @@ -82,5 +82,7 @@ wchar_t *utf8_to_widechar(const utf8 *src); utf8 *widechar_to_utf8(const wchar_t *src); bool language_get_localised_scenario_strings(const utf8 *scenarioFilename, rct_string_id *outStringIds); +rct_string_id language_allocate_object_string(const utf8 * target); +void language_free_object_string(rct_string_id stringId); #endif diff --git a/src/object.c b/src/object.c index ce0d7c86e3..225cf5518f 100644 --- a/src/object.c +++ b/src/object.c @@ -149,7 +149,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi * * rct2: 0x006A985D */ -int object_load_chunk(int groupIndex, rct_object_entry *entry, int* chunkSize) +int object_load_chunk_old(int groupIndex, rct_object_entry *entry, int* chunkSize) { // Alow chunkSize to be null int tempChunkSize; diff --git a/src/object/EntranceObject.cpp b/src/object/EntranceObject.cpp index d1b0e3a45b..edd1db42b5 100644 --- a/src/object/EntranceObject.cpp +++ b/src/object/EntranceObject.cpp @@ -17,6 +17,12 @@ #include "../core/IStream.hpp" #include "EntranceObject.h" +extern "C" +{ + #include "../drawing/drawing.h" + #include "../localisation/localisation.h" +} + enum OBJ_STRING_ID { OBJ_STRING_ID_NAME, @@ -35,12 +41,13 @@ void EntranceObject::ReadLegacy(IStream * stream) void EntranceObject::Load() { - + _legacyType.string_idx = language_allocate_object_string(GetName()); + _legacyType.image_id = gfx_object_allocate_images(ImageTable.GetImages(), ImageTable.GetCount()); } void EntranceObject::Unload() { - + language_free_object_string(_legacyType.string_idx); } const utf8 * EntranceObject::GetName() diff --git a/src/object/ImageTable.h b/src/object/ImageTable.h index 5514694fb4..788501cf44 100644 --- a/src/object/ImageTable.h +++ b/src/object/ImageTable.h @@ -36,5 +36,7 @@ private: public: ~ImageTable(); - void Read(IStream * stream); + void Read(IStream * stream); + const rct_g1_element * GetImages() const { return _entries.data(); } + uint32 GetCount() const { return _entries.size(); }; }; \ No newline at end of file diff --git a/src/object/Object.h b/src/object/Object.h index a68b19c03c..adeebc0894 100644 --- a/src/object/Object.h +++ b/src/object/Object.h @@ -48,5 +48,6 @@ public: virtual void Load() abstract; virtual void Unload() abstract; - virtual const utf8 * GetName() abstract; + virtual uint8 GetObjectType() { return _objectEntry.flags & 0x0F; } + virtual const utf8 * GetName() abstract; }; diff --git a/src/object/ObjectFactory.cpp b/src/object/ObjectFactory.cpp index 957f10e34b..7cd94070fa 100644 --- a/src/object/ObjectFactory.cpp +++ b/src/object/ObjectFactory.cpp @@ -20,6 +20,7 @@ #include "EntranceObject.h" #include "Object.h" #include "ObjectFactory.h" +#include "StexObject.h" extern "C" { @@ -29,7 +30,7 @@ extern "C" namespace ObjectFactory { - Object * CreateObjectFromLegacyFile(utf8 * path) + Object * CreateObjectFromLegacyFile(const utf8 * path) { Object * result = nullptr; @@ -64,6 +65,9 @@ namespace ObjectFactory case OBJECT_TYPE_PARK_ENTRANCE: result = new EntranceObject(entry); break; + case OBJECT_TYPE_SCENARIO_TEXT: + result = new StexObject(entry); + break; } return result; diff --git a/src/object/ObjectFactory.h b/src/object/ObjectFactory.h index 4d89b7ca6e..1f1ac4647e 100644 --- a/src/object/ObjectFactory.h +++ b/src/object/ObjectFactory.h @@ -22,6 +22,6 @@ class Object; namespace ObjectFactory { - Object * CreateObjectFromLegacyFile(utf8 * path); + Object * CreateObjectFromLegacyFile(const utf8 * path); Object * CreateObject(const rct_object_entry &entry); } diff --git a/src/object/ObjectRepository.cpp b/src/object/ObjectRepository.cpp index 203a1ffe79..1eaf17c1d6 100644 --- a/src/object/ObjectRepository.cpp +++ b/src/object/ObjectRepository.cpp @@ -17,6 +17,7 @@ #include #include "../common.h" +#include "../core/Console.hpp" #include "../core/FileStream.hpp" #include "../core/Guard.hpp" #include "../core/IStream.hpp" @@ -26,11 +27,14 @@ #include "Object.h" #include "ObjectFactory.h" #include "ObjectRepository.h" +#include "StexObject.h" extern "C" { + #include "../localisation/localisation.h" #include "../object.h" #include "../platform/platform.h" + #include "../scenario.h" } constexpr uint16 OBJECT_REPOSITORY_VERSION = 6; @@ -87,6 +91,17 @@ public: return nullptr; } + Object * LoadObject(const rct_object_entry * objectEntry) override + { + Object * object = nullptr; + const ObjectRepositoryItem * item = FindObject(objectEntry); + if (item != nullptr) + { + object = ObjectFactory::CreateObjectFromLegacyFile(item->Path); + } + return object; + } + private: void ClearItems() { @@ -329,4 +344,77 @@ extern "C" { IObjectRepository * objRepo = GetObjectRepository(); } + + int object_load_chunk(int groupIndex, rct_object_entry * entry, int * chunkSize) + { + IObjectRepository * objRepo = GetObjectRepository(); + Object * object = objRepo->LoadObject(entry); + if (object == nullptr) + { + utf8 objName[9] = { 0 }; + Memory::Copy(objName, entry->name, 8); + Console::Error::WriteFormat("[%s]: Object not found or could not be loaded.", objName); + Console::Error::WriteLine(); + return 0; + } + + uint8 objectType = object->GetObjectType(); + void * * chunkList = object_entry_groups[objectType].chunks; + if (groupIndex == -1) + { + for (groupIndex = 0; chunkList[groupIndex] != (void*)-1; groupIndex++) + { + if (groupIndex + 1 >= object_entry_group_counts[objectType]) + { + log_error("Object Load failed due to too many objects of a certain type."); + delete object; + return 0; + } + } + } + chunkList[groupIndex] = object->GetLegacyData(); + + rct_object_entry_extended * extendedEntry = &object_entry_groups[objectType].entries[groupIndex]; + Memory::Copy(extendedEntry, object->GetObjectEntry(), sizeof(rct_object_entry)); + extendedEntry->chunk_size = 0; + + object->Load(); + return 1; + } + + void scenario_translate(scenario_index_entry * scenarioEntry, const rct_object_entry * stexObjectEntry) + { + rct_string_id localisedStringIds[3]; + if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds)) + { + if (localisedStringIds[0] != STR_NONE) + { + String::Set(scenarioEntry->name, sizeof(scenarioEntry->name), language_get_string(localisedStringIds[0])); + } + if (localisedStringIds[2] != STR_NONE) + { + String::Set(scenarioEntry->details, sizeof(scenarioEntry->details), language_get_string(localisedStringIds[2])); + } + } + else + { + // Checks for a scenario string object (possibly for localisation) + if ((stexObjectEntry->flags & 0xFF) != 255) + { + IObjectRepository * objRepo = GetObjectRepository(); + Object * object = objRepo->LoadObject(stexObjectEntry); + if (object != nullptr) + { + StexObject * stexObject = static_cast(object); + const utf8 * scenarioName = stexObject->GetScenarioName(); + const utf8 * scenarioDetails = stexObject->GetScenarioDetails(); + + String::Set(scenarioEntry->name, sizeof(scenarioEntry->name), scenarioName); + String::Set(scenarioEntry->details, sizeof(scenarioEntry->details), scenarioDetails); + + delete object; + } + } + } + } } diff --git a/src/object/ObjectRepository.h b/src/object/ObjectRepository.h index c686a49de7..f64b6e6b86 100644 --- a/src/object/ObjectRepository.h +++ b/src/object/ObjectRepository.h @@ -52,7 +52,8 @@ interface IObjectRepository { virtual ~IObjectRepository() { } - virtual const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) abstract; + virtual const ObjectRepositoryItem * FindObject(const rct_object_entry * objectEntry) abstract; + virtual Object * LoadObject(const rct_object_entry * objectEntry) abstract; }; IObjectRepository * GetObjectRepository(); diff --git a/src/object/StexObject.cpp b/src/object/StexObject.cpp new file mode 100644 index 0000000000..3a8434f732 --- /dev/null +++ b/src/object/StexObject.cpp @@ -0,0 +1,77 @@ +#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 "StexObject.h" + +extern "C" +{ + #include "../localisation/localisation.h" +} + +enum OBJ_STRING_ID +{ + OBJ_STRING_ID_SCENARIO_NAME, + OBJ_STRING_ID_PARK_NAME, + OBJ_STRING_ID_SCENARIO_DETAILS, +}; + +void StexObject::ReadLegacy(IStream * stream) +{ + _legacyType.scenario_name = stream->ReadValue(); + _legacyType.park_name = stream->ReadValue(); + _legacyType.details = stream->ReadValue(); + _legacyType.var_06 = stream->ReadValue(); + stream->Seek(1, STREAM_SEEK_CURRENT); + + StringTable.Read(stream, OBJ_STRING_ID_SCENARIO_NAME); + StringTable.Read(stream, OBJ_STRING_ID_PARK_NAME); + StringTable.Read(stream, OBJ_STRING_ID_SCENARIO_DETAILS); +} + +void StexObject::Load() +{ + _legacyType.scenario_name = language_allocate_object_string(GetScenarioName()); + _legacyType.park_name = language_allocate_object_string(GetParkName()); + _legacyType.details = language_allocate_object_string(GetScenarioDetails()); +} + +void StexObject::Unload() +{ + language_free_object_string(_legacyType.scenario_name); + language_free_object_string(_legacyType.park_name); + language_free_object_string(_legacyType.details); +} + +const utf8 * StexObject::GetName() +{ + return GetScenarioName(); +} + +const utf8 * StexObject::GetScenarioName() +{ + return StringTable.GetString(OBJ_STRING_ID_SCENARIO_NAME); +} + +const utf8 * StexObject::GetScenarioDetails() +{ + return StringTable.GetString(OBJ_STRING_ID_SCENARIO_DETAILS); +} + +const utf8 * StexObject::GetParkName() +{ + return StringTable.GetString(OBJ_STRING_ID_PARK_NAME); +} diff --git a/src/object/StexObject.h b/src/object/StexObject.h new file mode 100644 index 0000000000..3204cc40db --- /dev/null +++ b/src/object/StexObject.h @@ -0,0 +1,45 @@ +#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 "Object.h" + +extern "C" +{ + #include "../scenario.h" +} + +class StexObject : public Object +{ +private: + rct_stex_entry _legacyType; + +public: + explicit StexObject(const rct_object_entry &entry) : Object(entry) { }; + + void * GetLegacyData() override { return &_legacyType; } + + void ReadLegacy(IStream * stream) override; + void Load() override; + void Unload() override; + + const utf8 * GetName() override; + + const utf8 * GetScenarioName(); + const utf8 * GetScenarioDetails(); + const utf8 * GetParkName(); +}; diff --git a/src/scenario.h b/src/scenario.h index dd35641e2a..b78057b8e8 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -490,6 +490,8 @@ bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc); bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc); void scenario_normalise_name(utf8 *name); +void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry); + // RCT1 scenario index map enum { SC_UNIDENTIFIED = 255, diff --git a/src/scenario_list.c b/src/scenario_list.c index c92a9a520e..29819410d6 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -36,7 +36,6 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp); static void scenario_list_sort(); static int scenario_list_sort_by_category(const void *a, const void *b); static int scenario_list_sort_by_index(const void *a, const void *b); -static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry); static bool scenario_scores_load(); static void scenario_scores_legacy_get_path(utf8 *outPath); @@ -183,29 +182,6 @@ static void scenario_list_add(const utf8 *path, uint64 timestamp) scenario_translate(newEntry, &s6Info.entry); } -static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry) -{ - rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds)) { - if (localisedStringIds[0] != STR_NONE) { - safe_strcpy(scenarioEntry->name, language_get_string(localisedStringIds[0]), 64); - } - if (localisedStringIds[2] != STR_NONE) { - safe_strcpy(scenarioEntry->details, language_get_string(localisedStringIds[2]), 256); - } - } else { - // Checks for a scenario string object (possibly for localisation) - if ((stexObjectEntry->flags & 0xFF) != 255) { - if (object_get_scenario_text((rct_object_entry*)stexObjectEntry)) { - rct_stex_entry* stex_entry = gStexTempChunk; - format_string(scenarioEntry->name, stex_entry->scenario_name, NULL); - format_string(scenarioEntry->details, stex_entry->details, NULL); - object_free_scenario_text(); - } - } - } -} - void scenario_list_dispose() { gScenarioListCapacity = 0;