diff --git a/src/openrct2-ui/windows/EditorInventionsList.cpp b/src/openrct2-ui/windows/EditorInventionsList.cpp index 40809bee96..9b79111560 100644 --- a/src/openrct2-ui/windows/EditorInventionsList.cpp +++ b/src/openrct2-ui/windows/EditorInventionsList.cpp @@ -175,18 +175,23 @@ static void move_research_item(rct_research_item *beforeItem); */ static void research_rides_setup(){ // Reset all objects to not required - for (uint8 object_type = OBJECT_TYPE_RIDE; object_type < OBJECT_TYPE_COUNT; object_type++){ - uint8* in_use = Editor::SelectedObjects[object_type]; - for (uint8 num_objects = object_entry_group_counts[object_type]; num_objects != 0; num_objects--){ - *in_use++ = OBJECT_SELECTION_NOT_SELECTED_OR_REQUIRED; + for (uint8 objectType = OBJECT_TYPE_RIDE; objectType < OBJECT_TYPE_COUNT; objectType++) + { + auto maxObjects = object_entry_group_counts[objectType]; + for (sint32 i = 0; i < maxObjects; i++) + { + Editor::ClearSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_ALL); } } // Set research required for rides in use - for (uint16 rideIndex = 0; rideIndex < 255; rideIndex++){ - Ride * ride = get_ride(rideIndex); - if (ride->type == RIDE_TYPE_NULL)continue; - Editor::SelectedObjects[OBJECT_TYPE_RIDE][ride->subtype] |= OBJECT_SELECTION_FLAG_SELECTED; + for (uint16 rideIndex = 0; rideIndex < MAX_RIDES; rideIndex++) + { + auto ride = get_ride(rideIndex); + if (ride->type != RIDE_TYPE_NULL) + { + Editor::SetSelectedObject(OBJECT_TYPE_RIDE, ride->subtype, OBJECT_SELECTION_FLAG_SELECTED); + } } for (rct_research_item* research = gResearchItems; research->rawValue != RESEARCHED_ITEMS_END; research++) @@ -216,7 +221,8 @@ static void research_rides_setup(){ continue; // If master ride not in use - if (!(Editor::SelectedObjects[OBJECT_TYPE_RIDE][rideType] & OBJECT_SELECTION_FLAG_SELECTED)) + auto flags = Editor::GetSelectedObjectFlags(OBJECT_TYPE_RIDE, rideType); + if (!(flags & OBJECT_SELECTION_FLAG_SELECTED)) continue; for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) @@ -237,7 +243,8 @@ static void research_rides_setup(){ if (!master_found){ // If not in use - if (!(Editor::SelectedObjects[OBJECT_TYPE_RIDE][object_index] & OBJECT_SELECTION_FLAG_SELECTED)) { + auto flags = Editor::GetSelectedObjectFlags(OBJECT_TYPE_RIDE, object_index); + if (!(flags & OBJECT_SELECTION_FLAG_SELECTED)) { continue; } @@ -679,12 +686,11 @@ static void window_editor_inventions_list_paint(rct_window *w, rct_drawpixelinfo if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE) objectEntryType = OBJECT_TYPE_RIDE; - void * chunk = object_entry_groups[objectEntryType].chunks[researchItem->entryIndex]; - + auto chunk = object_entry_get_chunk(objectEntryType, researchItem->entryIndex); if (chunk == nullptr) return; - rct_object_entry * entry = &object_entry_groups[objectEntryType].entries[researchItem->entryIndex].entry; + auto entry = object_entry_get_entry(objectEntryType, researchItem->entryIndex); // Draw preview widget = &w->widgets[WIDX_PREVIEW]; diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 66034628cb..8399e54caf 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -385,8 +385,7 @@ rct_window * window_editor_object_selection_open() if (window != nullptr) return window; - if (!sub_6AB211()) - return nullptr; + sub_6AB211(); reset_selected_object_count_and_size(); window = window_create_centred( @@ -1227,7 +1226,7 @@ static void window_editor_object_selection_manage_tracks() gS6Info.editor_step = EDITOR_STEP_TRACK_DESIGNS_MANAGER; sint32 entry_index = 0; - for (; (object_entry_groups[0].chunks[entry_index]) == nullptr; ++entry_index); + for (; object_entry_get_chunk(OBJECT_TYPE_RIDE, entry_index) == nullptr; entry_index++); rct_ride_entry* ride_entry = get_ride_entry(entry_index); uint8 ride_type = ride_entry_get_first_non_null_ride_type(ride_entry); @@ -1419,7 +1418,7 @@ static bool filter_chunks(const ObjectRepositoryItem * item) static void filter_update_counts() { if (!_FILTER_ALL || strlen(_filter_string) > 0) { - uint8 *selectionFlags = _objectSelectionFlags; + const auto &selectionFlags = _objectSelectionFlags; for (sint32 i = 0; i < 11; i++) { _filter_object_counts[i] = 0; } @@ -1431,12 +1430,11 @@ static void filter_update_counts() if (filter_source(item) && filter_string(item) && filter_chunks(item) && - filter_selected(*selectionFlags) + filter_selected(selectionFlags[i]) ) { uint8 objectType = item->ObjectEntry.flags & 0xF; _filter_object_counts[objectType]++; } - selectionFlags++; } } } diff --git a/src/openrct2-ui/windows/EditorObjectiveOptions.cpp b/src/openrct2-ui/windows/EditorObjectiveOptions.cpp index 52196e25f4..d174a74a29 100644 --- a/src/openrct2-ui/windows/EditorObjectiveOptions.cpp +++ b/src/openrct2-ui/windows/EditorObjectiveOptions.cpp @@ -814,12 +814,7 @@ static void window_editor_objective_options_main_textinput(rct_window *w, rct_wi */ static void window_editor_objective_options_main_invalidate(rct_window *w) { - rct_widget *widgets; - rct_stex_entry *stex; - - stex = g_stexEntries[0]; - - widgets = window_editor_objective_options_widgets[w->page]; + auto widgets = window_editor_objective_options_widgets[w->page]; if (w->widgets != widgets) { w->widgets = widgets; window_init_scroll_widgets(w); @@ -827,6 +822,7 @@ static void window_editor_objective_options_main_invalidate(rct_window *w) window_editor_objective_options_set_pressed_tab(w); + auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); if (stex == nullptr) w->disabled_widgets &= ~((1 << WIDX_PARK_NAME) | (1 << WIDX_SCENARIO_NAME)); else @@ -877,7 +873,6 @@ static void window_editor_objective_options_main_invalidate(rct_window *w) */ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpixelinfo *dpi) { - rct_stex_entry *stex; sint32 x, y, width; rct_string_id stringId; uint32 arg; @@ -885,8 +880,6 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi window_draw_widgets(w, dpi); window_editor_objective_options_draw_tab_images(w, dpi); - stex = g_stexEntries[0]; - // Objective label x = w->x + 8; y = w->y + w->widgets[WIDX_OBJECTIVE].top; @@ -983,6 +976,7 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi y = w->y + w->widgets[WIDX_PARK_NAME].top; width = w->widgets[WIDX_PARK_NAME].left - 16; + auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); if (stex != nullptr) { set_format_arg(0, rct_string_id, stex->park_name); } else { diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp index a9df9db13f..1bac704866 100644 --- a/src/openrct2-ui/windows/NewRide.cpp +++ b/src/openrct2-ui/windows/NewRide.cpp @@ -349,7 +349,7 @@ static ride_list_item * window_new_ride_iterate_over_ride_group(uint8 rideType, { uint8 rideEntryIndex = *rideEntryIndexPtr++; char rideEntryName[DAT_NAME_LENGTH + 1]; - memcpy(rideEntryName,object_entry_groups[OBJECT_TYPE_RIDE].entries[rideEntryIndex].name,8); + memcpy(rideEntryName, object_entry_get_entry(OBJECT_TYPE_RIDE, rideEntryIndex)->name, 8); rideEntryName[DAT_NAME_LENGTH] = 0; // Skip if vehicle type is not invented yet diff --git a/src/openrct2/Editor.cpp b/src/openrct2/Editor.cpp index ddc9875cf3..88a5f2d6be 100644 --- a/src/openrct2/Editor.cpp +++ b/src/openrct2/Editor.cpp @@ -14,6 +14,8 @@ *****************************************************************************/ #pragma endregion +#include +#include #include "Context.h" #include "Editor.h" #include "EditorObjectSelectionSession.h" @@ -38,32 +40,7 @@ namespace Editor { - static uint8 _editorSelectedRides[MAX_RIDE_OBJECTS]; - static uint8 _editorSelectedSmallScenery[MAX_SMALL_SCENERY_OBJECTS]; - static uint8 _editorSelectedLargeScenery[MAX_LARGE_SCENERY_OBJECTS]; - static uint8 _editorSelectedWalls[MAX_WALL_SCENERY_OBJECTS]; - static uint8 _editorSelectedBanners[MAX_BANNER_OBJECTS]; - static uint8 _editorSelectedFootpaths[MAX_PATH_OBJECTS]; - static uint8 _editorSelectedFootpathAdditions[MAX_PATH_ADDITION_OBJECTS]; - static uint8 _editorSelectedSceneryGroups[MAX_SCENERY_GROUP_OBJECTS]; - static uint8 _editorSelectedParkEntrances[MAX_PARK_ENTRANCE_OBJECTS]; - static uint8 _editorSelectedWaters[MAX_WATER_OBJECTS]; - static uint8 _editorSelectedStexs[MAX_SCENARIO_TEXT_OBJECTS]; - - uint8 * SelectedObjects[OBJECT_TYPE_COUNT] = - { - _editorSelectedRides, - _editorSelectedSmallScenery, - _editorSelectedLargeScenery, - _editorSelectedWalls, - _editorSelectedBanners, - _editorSelectedFootpaths, - _editorSelectedFootpathAdditions, - _editorSelectedSceneryGroups, - _editorSelectedParkEntrances, - _editorSelectedWaters, - _editorSelectedStexs, - }; + static std::array, OBJECT_TYPE_COUNT> _editorSelectedObjectFlags; static void ConvertSaveToScenarioCallback(sint32 result, const utf8 * path); static void SetAllLandOwned(); @@ -806,6 +783,37 @@ namespace Editor window_invalidate_by_class(WC_EDITOR_SCENARIO_OPTIONS); *ebx = 0; } + + uint8 GetSelectedObjectFlags(sint32 objectType, size_t index) + { + uint8 result = 0; + auto &list = _editorSelectedObjectFlags[objectType]; + if (list.size() > index) + { + result = list[index]; + } + return result; + } + + void ClearSelectedObject(sint32 objectType, size_t index, uint32 flags) + { + auto &list = _editorSelectedObjectFlags[objectType]; + if (list.size() <= index) + { + list.resize(index + 1); + } + list[index] &= ~flags; + } + + void SetSelectedObject(sint32 objectType, size_t index, uint32 flags) + { + auto &list = _editorSelectedObjectFlags[objectType]; + if (list.size() <= index) + { + list.resize(index + 1); + } + list[index] |= flags; + } } void editor_open_windows_for_current_step() diff --git a/src/openrct2/Editor.h b/src/openrct2/Editor.h index 8cefe57662..1972c010d8 100644 --- a/src/openrct2/Editor.h +++ b/src/openrct2/Editor.h @@ -25,8 +25,6 @@ namespace Editor { - extern uint8 * SelectedObjects[OBJECT_TYPE_COUNT]; - void Load(); void ConvertSaveToScenario(); void LoadTrackDesigner(); @@ -38,6 +36,10 @@ namespace Editor void OpenWindowsForCurrentStep(); void GameCommandEditScenarioOptions(sint32*, sint32*, sint32*, sint32*, sint32*, sint32*, sint32*); + + uint8 GetSelectedObjectFlags(sint32 objectType, size_t index); + void ClearSelectedObject(sint32 objectType, size_t index, uint32 flags); + void SetSelectedObject(sint32 objectType, size_t index, uint32 flags); } typedef enum diff --git a/src/openrct2/EditorObjectSelectionSession.cpp b/src/openrct2/EditorObjectSelectionSession.cpp index 7dbdfbd532..6052161575 100644 --- a/src/openrct2/EditorObjectSelectionSession.cpp +++ b/src/openrct2/EditorObjectSelectionSession.cpp @@ -14,6 +14,7 @@ *****************************************************************************/ #pragma endregion +#include #include "Context.h" #include "core/Util.hpp" #include "Editor.h" @@ -30,7 +31,7 @@ #include "world/LargeScenery.h" bool _maxObjectsWasHit; -uint8 * _objectSelectionFlags = nullptr; +std::vector _objectSelectionFlags; sint32 _numSelectedObjectsForType[OBJECT_TYPE_COUNT]; static sint32 _numAvailableObjectsForType[OBJECT_TYPE_COUNT]; @@ -107,16 +108,14 @@ static void setup_track_designer_objects() */ void setup_in_use_selection_flags() { - for (uint8 object_type = 0; object_type < OBJECT_TYPE_COUNT; object_type++){ - for (uint16 i = 0; i < object_entry_group_counts[object_type]; i++){ - Editor::SelectedObjects[object_type][i] = OBJECT_SELECTION_NOT_SELECTED_OR_REQUIRED; - } - } - - for (uint8 object_type = 0; object_type < OBJECT_TYPE_COUNT; object_type++){ - for (uint16 i = 0; i < object_entry_group_counts[object_type]; i++){ - if (object_entry_groups[object_type].chunks[i] != nullptr) { - Editor::SelectedObjects[object_type][i] |= OBJECT_SELECTION_FLAG_2; + for (uint8 objectType = 0; objectType < OBJECT_TYPE_COUNT; objectType++) + { + for (sint32 i = 0; i < object_entry_group_counts[objectType]; i++) + { + Editor::ClearSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_ALL); + if (object_entry_get_chunk(objectType, i) != nullptr) + { + Editor::SetSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_2); } } } @@ -136,17 +135,17 @@ void setup_in_use_selection_flags() type = iter.element->properties.path.type; type >>= 4; assert(type < object_entry_group_counts[OBJECT_TYPE_PATHS]); - Editor::SelectedObjects[OBJECT_TYPE_PATHS][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_PATHS, type, OBJECT_SELECTION_FLAG_SELECTED); if (footpath_element_has_path_scenery(iter.element)) { uint8 path_additions = footpath_element_get_path_scenery_index(iter.element); - Editor::SelectedObjects[OBJECT_TYPE_PATH_BITS][path_additions] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_PATH_BITS, path_additions, OBJECT_SELECTION_FLAG_SELECTED); } break; case TILE_ELEMENT_TYPE_SMALL_SCENERY: type = iter.element->properties.scenery.type; assert(type < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]); - Editor::SelectedObjects[OBJECT_TYPE_SMALL_SCENERY][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_SMALL_SCENERY, type, OBJECT_SELECTION_FLAG_SELECTED); break; case TILE_ELEMENT_TYPE_ENTRANCE: if (iter.element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE) @@ -155,27 +154,27 @@ void setup_in_use_selection_flags() if (iter.element->properties.entrance.index != 0) break; - Editor::SelectedObjects[OBJECT_TYPE_PARK_ENTRANCE][0] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_PARK_ENTRANCE, 0, OBJECT_SELECTION_FLAG_SELECTED); type = iter.element->properties.entrance.path_type; assert(type < object_entry_group_counts[OBJECT_TYPE_PATHS]); - Editor::SelectedObjects[OBJECT_TYPE_PATHS][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_PATHS, type, OBJECT_SELECTION_FLAG_SELECTED); break; case TILE_ELEMENT_TYPE_WALL: type = iter.element->properties.wall.type; assert(type < object_entry_group_counts[OBJECT_TYPE_WALLS]); - Editor::SelectedObjects[OBJECT_TYPE_WALLS][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_WALLS, type, OBJECT_SELECTION_FLAG_SELECTED); break; case TILE_ELEMENT_TYPE_LARGE_SCENERY: type = scenery_large_get_type(iter.element); assert(type < object_entry_group_counts[OBJECT_TYPE_LARGE_SCENERY]); - Editor::SelectedObjects[OBJECT_TYPE_LARGE_SCENERY][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_LARGE_SCENERY, type, OBJECT_SELECTION_FLAG_SELECTED); break; case TILE_ELEMENT_TYPE_BANNER: banner = &gBanners[iter.element->properties.banner.index]; type = banner->type; assert(type < object_entry_group_counts[OBJECT_TYPE_BANNERS]); - Editor::SelectedObjects[OBJECT_TYPE_BANNERS][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_BANNERS, type, OBJECT_SELECTION_FLAG_SELECTED); break; } } while (tile_element_iterator_next(&iter)); @@ -184,7 +183,7 @@ void setup_in_use_selection_flags() Ride* ride = get_ride(ride_index); if (ride->type != RIDE_TYPE_NULL) { uint8 type = ride->subtype; - Editor::SelectedObjects[OBJECT_TYPE_RIDE][type] |= OBJECT_SELECTION_FLAG_SELECTED; + Editor::SetSelectedObject(OBJECT_TYPE_RIDE, type, OBJECT_SELECTION_FLAG_SELECTED); } } @@ -197,12 +196,15 @@ void setup_in_use_selection_flags() uint8 entryType, entryIndex; if (find_object_in_entry_group(&item->ObjectEntry, &entryType, &entryIndex)) { - if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_SELECTED) { + auto flags = Editor::GetSelectedObjectFlags(entryType, entryIndex); + if (flags & OBJECT_SELECTION_FLAG_SELECTED) + { *selectionFlags |= OBJECT_SELECTION_FLAG_IN_USE | - OBJECT_SELECTION_FLAG_SELECTED; + OBJECT_SELECTION_FLAG_SELECTED; } - if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_2) { + if (flags & OBJECT_SELECTION_FLAG_2) + { *selectionFlags |= OBJECT_SELECTION_FLAG_SELECTED; } } @@ -213,14 +215,10 @@ void setup_in_use_selection_flags() * * rct2: 0x006AB211 */ -bool sub_6AB211() +void sub_6AB211() { sint32 numObjects = (sint32)object_repository_get_items_count(); - _objectSelectionFlags = (uint8*)calloc(numObjects, sizeof(uint8)); - if (_objectSelectionFlags == nullptr){ - log_error("Failed to allocate memory for object flag list."); - return false; - } + _objectSelectionFlags = std::vector(numObjects); for (uint8 objectType = 0; objectType < 11; objectType++) { _numSelectedObjectsForType[objectType] = 0; @@ -254,7 +252,6 @@ bool sub_6AB211() } reset_selected_object_count_and_size(); - return true; } /** @@ -263,7 +260,8 @@ bool sub_6AB211() */ void editor_object_flags_free() { - SafeFree(_objectSelectionFlags); + _objectSelectionFlags.clear(); + _objectSelectionFlags.shrink_to_fit(); } /** @@ -276,7 +274,7 @@ static void remove_selected_objects_from_research(const rct_object_entry* instal return; if (entry_type == OBJECT_TYPE_RIDE){ - rct_ride_entry* rideEntry = (rct_ride_entry*)object_entry_groups[entry_type].chunks[entry_index]; + auto rideEntry = (rct_ride_entry *)object_entry_get_entry(entry_type, entry_index); for (auto rideType : rideEntry->ride_type) { @@ -492,12 +490,7 @@ bool editor_check_object_group_at_least_one_selected(sint32 checkObjectType) sint32 editor_remove_unused_objects() { - bool createSelectionFlags = (_objectSelectionFlags == nullptr); - if (createSelectionFlags && !sub_6AB211()) - { - return 0; - } - + sub_6AB211(); setup_in_use_selection_flags(); sint32 numObjects = (sint32)object_repository_get_items_count(); @@ -522,11 +515,7 @@ sint32 editor_remove_unused_objects() } } unload_unselected_objects(); - - if (createSelectionFlags) - { - editor_object_flags_free(); - } + editor_object_flags_free(); auto intent = Intent(INTENT_ACTION_REFRESH_SCENERY); context_broadcast_intent(&intent); diff --git a/src/openrct2/EditorObjectSelectionSession.h b/src/openrct2/EditorObjectSelectionSession.h index 8eb526007f..349169a783 100644 --- a/src/openrct2/EditorObjectSelectionSession.h +++ b/src/openrct2/EditorObjectSelectionSession.h @@ -16,17 +16,18 @@ #pragma once +#include #include "common.h" #include "object/Object.h" extern bool _maxObjectsWasHit; -extern uint8 * _objectSelectionFlags; +extern std::vector _objectSelectionFlags; extern sint32 _numSelectedObjectsForType[OBJECT_TYPE_COUNT]; bool editor_check_object_group_at_least_one_selected(sint32 objectType); void editor_object_flags_free(); void unload_unselected_objects(); -bool sub_6AB211(); +void sub_6AB211(); void reset_selected_object_count_and_size(); sint32 window_editor_object_selection_select_object(uint8 bh, sint32 flags, const rct_object_entry *entry); diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index c744ce23a7..784561e8ed 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -177,7 +177,7 @@ enum */ void update_palette_effects() { - rct_water_type * water_type = (rct_water_type *) object_entry_groups[OBJECT_TYPE_WATER].chunks[0]; + auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0); if (gClimateLightningFlash == 1) { diff --git a/src/openrct2/drawing/Drawing.cpp b/src/openrct2/drawing/Drawing.cpp index 4c2e0d3c04..19c63b26ab 100644 --- a/src/openrct2/drawing/Drawing.cpp +++ b/src/openrct2/drawing/Drawing.cpp @@ -537,7 +537,7 @@ void load_palette() return; } - rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0]; + auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0); uint32 palette = 0x5FC; diff --git a/src/openrct2/interface/Console.cpp b/src/openrct2/interface/Console.cpp index 241a6399cd..4bd1d3a8ac 100644 --- a/src/openrct2/interface/Console.cpp +++ b/src/openrct2/interface/Console.cpp @@ -1196,7 +1196,8 @@ static sint32 cc_object_count(const utf8 **argv, sint32 argc) { sint32 entryGroupIndex = 0; for (; entryGroupIndex < object_entry_group_counts[i]; entryGroupIndex++){ - if (object_entry_groups[i].chunks[entryGroupIndex] == nullptr){ + if (object_entry_get_chunk(i, entryGroupIndex) == nullptr) + { break; } } diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index cbec22fa75..ddd5e16627 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -48,6 +48,7 @@ typedef enum OBJECT_SELECTION_FLAG_6 = (1 << 5), OBJECT_SELECTION_FLAG_7 = (1 << 6), OBJECT_SELECTION_FLAG_8 = (1 << 7), + OBJECT_SELECTION_FLAG_ALL = 0xFF, } OBJECT_SELECTION_FLAGS; #define OBJECT_SELECTION_NOT_SELECTED_OR_REQUIRED 0 @@ -87,26 +88,9 @@ typedef struct rct_object_entry { } rct_object_entry; assert_struct_size(rct_object_entry, 0x10); -/** - * Object entry structure extended. - * size: 0x14 - */ -typedef struct rct_object_entry_extended { - union { - rct_object_entry entry; - struct { - uint32 flags; - char name[8]; - uint32 checksum; - uint32 chunk_size; - }; - }; -} rct_object_entry_extended; -assert_struct_size(rct_object_entry_extended, 0x14); - typedef struct rct_object_entry_group { void **chunks; - rct_object_entry_extended *entries; + rct_object_entry *entries; } rct_object_entry_group; #ifdef PLATFORM_32BIT assert_struct_size(rct_object_entry_group, 8); @@ -218,8 +202,6 @@ enum OBJECT_ERROR : uint32 extern sint32 object_entry_group_counts[]; extern sint32 object_entry_group_encoding[]; -extern const rct_object_entry_group object_entry_groups[]; - void object_list_load(); bool object_entry_is_empty(const rct_object_entry *entry); @@ -232,3 +214,6 @@ const rct_object_entry * object_list_find_by_name(const char *name); const rct_object_entry * object_list_find(rct_object_entry *entry); void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry); + +void * object_entry_get_chunk(sint32 objectType, size_t index); +const rct_object_entry * object_entry_get_entry(sint32 objectType, size_t index); diff --git a/src/openrct2/object/ObjectList.cpp b/src/openrct2/object/ObjectList.cpp index e58a49977b..cc64cbf5dc 100644 --- a/src/openrct2/object/ObjectList.cpp +++ b/src/openrct2/object/ObjectList.cpp @@ -20,6 +20,7 @@ #include "../object/Object.h" #include "ObjectList.h" #include "ObjectRepository.h" +#include "ObjectManager.h" #include "../util/SawyerCoding.h" #include "../util/Util.h" @@ -53,46 +54,6 @@ sint32 object_entry_group_encoding[] = { CHUNK_ENCODING_RLE, CHUNK_ENCODING_ROTATE }; - - rct_ride_entry *gRideEntries[MAX_RIDE_OBJECTS]; - rct_small_scenery_entry *gSmallSceneryEntries[MAX_SMALL_SCENERY_OBJECTS]; - rct_large_scenery_entry *gLargeSceneryEntries[MAX_LARGE_SCENERY_OBJECTS]; - rct_wall_scenery_entry *gWallSceneryEntries[MAX_WALL_SCENERY_OBJECTS]; - rct_banner *gBannerSceneryEntries[MAX_BANNER_OBJECTS]; - rct_footpath_entry *gFootpathEntries[MAX_PATH_OBJECTS]; - rct_path_bit_scenery_entry *gFootpathAdditionEntries[MAX_PATH_ADDITION_OBJECTS]; - rct_scenery_group_entry *gSceneryGroupEntries[MAX_SCENERY_GROUP_OBJECTS]; - rct_entrance_type *gParkEntranceEntries[MAX_PARK_ENTRANCE_OBJECTS]; - rct_water_type *gWaterEntries[MAX_WATER_OBJECTS]; - rct_stex_entry *gStexEntries[MAX_SCENARIO_TEXT_OBJECTS]; - - static rct_object_entry_extended _objectEntriesRides[MAX_RIDE_OBJECTS]; - static rct_object_entry_extended _objectEntriesSmallScenery[MAX_SMALL_SCENERY_OBJECTS]; - static rct_object_entry_extended _objectEntriesLargeScenery[MAX_LARGE_SCENERY_OBJECTS]; - static rct_object_entry_extended _objectEntriesWalls[MAX_WALL_SCENERY_OBJECTS]; - static rct_object_entry_extended _objectEntriesBanners[MAX_BANNER_OBJECTS]; - static rct_object_entry_extended _objectEntriesFootpaths[MAX_PATH_OBJECTS]; - static rct_object_entry_extended _objectEntriesFootpathAdditions[MAX_PATH_ADDITION_OBJECTS]; - static rct_object_entry_extended _objectEntriesSceneryGroups[MAX_SCENERY_GROUP_OBJECTS]; - static rct_object_entry_extended _objectEntriesParkEntrances[MAX_PARK_ENTRANCE_OBJECTS]; - static rct_object_entry_extended _objectEntriesWaters[MAX_WATER_OBJECTS]; - static rct_object_entry_extended _objectEntriesStexs[MAX_SCENARIO_TEXT_OBJECTS]; - - -// 0x98D97C chunk address', 0x98D980 object_entries -const rct_object_entry_group object_entry_groups[] = { - (void**)(gRideEntries ), _objectEntriesRides, // rides - (void**)(gSmallSceneryEntries ), _objectEntriesSmallScenery, // small scenery 0x009AD1A4, 0xF2FA3C - (void**)(gLargeSceneryEntries ), _objectEntriesLargeScenery, // large scenery 0x009AD594, 0xF40DEC - (void**)(gWallSceneryEntries ), _objectEntriesWalls, // walls 0x009AD794, 0xF417EC - (void**)(gBannerSceneryEntries ), _objectEntriesBanners, // banners 0x009AD994, 0xF421EC - (void**)(gFootpathEntries ), _objectEntriesFootpaths, // paths 0x009ADA14, 0xF4246C - (void**)(gFootpathAdditionEntries ), _objectEntriesFootpathAdditions, // path bits 0x009ADA54, 0xF425AC - (void**)(gSceneryGroupEntries ), _objectEntriesSceneryGroups, // scenery sets 0x009ADA90, 0xF426D8 - (void**)(gParkEntranceEntries ), _objectEntriesParkEntrances, // park entrance 0x009ADADC, 0xF42854 - (void**)(gWaterEntries ), _objectEntriesWaters, // water 0x009ADAE0, 0xF42868 - (void**)(gStexEntries ), _objectEntriesStexs, // scenario text 0x009ADAE4, 0xF4287C -}; // clang-format on bool object_entry_is_empty(const rct_object_entry *entry) @@ -133,26 +94,27 @@ void object_create_identifier_name(char* string_buffer, size_t size, const rct_o */ bool find_object_in_entry_group(const rct_object_entry * entry, uint8 * entry_type, uint8 * entry_index) { - if ((entry->flags & 0xF) >= Util::CountOf(object_entry_groups)) { - return false; - } - *entry_type = entry->flags & 0xF; - rct_object_entry_group entry_group = object_entry_groups[*entry_type]; - for (*entry_index = 0; - *entry_index < object_entry_group_counts[*entry_type]; - ++(*entry_index), entry_group.chunks++, entry_group.entries++) + sint32 objectType = object_entry_get_type(entry); + if (objectType >= OBJECT_TYPE_COUNT) { - if (*entry_group.chunks == nullptr) - continue; - - if (object_entry_compare((rct_object_entry*)entry_group.entries, entry)) - break; + return false; } - if (*entry_index == object_entry_group_counts[*entry_type]) - return false; - - return true; + auto maxObjects = object_entry_group_counts[objectType]; + for (sint32 i = 0; i < maxObjects; i++) + { + if (object_entry_get_chunk(objectType, i) != nullptr) + { + auto thisEntry = object_entry_get_entry(*entry_type, i); + if (object_entry_compare(thisEntry, entry)) + { + *entry_type = objectType; + *entry_index = i; + return true; + } + } + } + return false; } void get_type_entry_index(size_t index, uint8 * outObjectType, uint8 * outEntryIndex) @@ -177,17 +139,14 @@ const rct_object_entry * get_loaded_object_entry(size_t index) uint8 objectType, entryIndex; get_type_entry_index(index, &objectType, &entryIndex); - rct_object_entry * entry = (rct_object_entry *)&(object_entry_groups[objectType].entries[entryIndex]); - return entry; + return object_entry_get_entry(objectType, entryIndex); } void * get_loaded_object_chunk(size_t index) { uint8 objectType, entryIndex; get_type_entry_index(index, &objectType, &entryIndex); - - void *entry = object_entry_groups[objectType].chunks[entryIndex]; - return entry; + return object_entry_get_chunk(objectType, entryIndex); } void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry) @@ -196,3 +155,28 @@ void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_obj memcpy(buffer, entry->name, bufferSize - 1); buffer[bufferSize - 1] = 0; } + +void * object_entry_get_chunk(sint32 objectType, size_t index) +{ + size_t objectIndex = index; + for (sint32 i = 0; i < objectType; i++) + { + objectIndex += object_entry_group_counts[i]; + } + + void * result = nullptr; + auto objectMgr = GetObjectManager(); + auto obj = objectMgr->GetLoadedObject(objectIndex); + if (obj != nullptr) + { + result = obj->GetLegacyData(); + } + return result; +} + +const rct_object_entry * object_entry_get_entry(sint32 objectType, size_t index) +{ + auto objectMgr = GetObjectManager(); + auto obj = objectMgr->GetLoadedObject(objectType, index); + return obj->GetObjectEntry(); +} diff --git a/src/openrct2/object/ObjectList.h b/src/openrct2/object/ObjectList.h index 69f826dd4a..c8eb729ba5 100644 --- a/src/openrct2/object/ObjectList.h +++ b/src/openrct2/object/ObjectList.h @@ -8,21 +8,8 @@ #include "../world/Water.h" #include "ObjectLimits.h" -extern rct_ride_entry *gRideEntries[MAX_RIDE_OBJECTS]; -extern rct_small_scenery_entry *gSmallSceneryEntries[MAX_SMALL_SCENERY_OBJECTS]; -extern rct_large_scenery_entry *gLargeSceneryEntries[MAX_LARGE_SCENERY_OBJECTS]; -extern rct_wall_scenery_entry *gWallSceneryEntries[MAX_WALL_SCENERY_OBJECTS]; -extern rct_banner *gBannerSceneryEntries[MAX_BANNER_OBJECTS]; -extern rct_footpath_entry *gFootpathEntries[MAX_PATH_OBJECTS]; -extern rct_path_bit_scenery_entry *gFootpathAdditionEntries[MAX_PATH_ADDITION_OBJECTS]; -extern rct_scenery_group_entry *gSceneryGroupEntries[MAX_SCENERY_GROUP_OBJECTS]; -extern rct_entrance_type *gParkEntranceEntries[MAX_PARK_ENTRANCE_OBJECTS]; -extern rct_water_type *gWaterEntries[MAX_WATER_OBJECTS]; -extern rct_stex_entry *gStexEntries[MAX_SCENARIO_TEXT_OBJECTS]; - void get_type_entry_index(size_t index, uint8 * outObjectType, uint8 * outEntryIndex); const rct_object_entry * get_loaded_object_entry(size_t index); void * get_loaded_object_chunk(size_t index); uint8 object_entry_get_type(const rct_object_entry * objectEntry); uint8 object_entry_get_source_game(const rct_object_entry * objectEntry); - diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index 1621875047..bed3128eaf 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -35,8 +35,8 @@ class ObjectManager final : public IObjectManager { private: - IObjectRepository * _objectRepository; - Object * * _loadedObjects = nullptr; + IObjectRepository * _objectRepository; + std::vector _loadedObjects; public: explicit ObjectManager(IObjectRepository * objectRepository) @@ -44,31 +44,51 @@ public: Guard::ArgumentNotNull(objectRepository); _objectRepository = objectRepository; - _loadedObjects = Memory::AllocateArray(OBJECT_ENTRY_COUNT); - for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) - { - _loadedObjects[i] = nullptr; - } + _loadedObjects.resize(OBJECT_ENTRY_COUNT); - UpdateLegacyLoadedObjectList(); UpdateSceneryGroupIndexes(); reset_type_to_ride_entry_index_map(); } ~ObjectManager() override { - SetNewLoadedObjectList(nullptr); + UnloadAll(); } Object * GetLoadedObject(size_t index) override { - if (_loadedObjects == nullptr) + if (index >= OBJECT_ENTRY_COUNT) + { +#ifdef DEBUG + log_warning("Object index %u exceeds maximum of %d.", index, OBJECT_ENTRY_COUNT); +#endif + return nullptr; + } + if (index >= _loadedObjects.size()) { return nullptr; } return _loadedObjects[index]; } + Object * GetLoadedObject(sint32 objectType, size_t index) override + { + if (index >= (size_t)object_entry_group_counts[objectType]) + { +#ifdef DEBUG + log_warning("Object index %u exceeds maximum for type type %d.", index, objectType); +#endif + return nullptr; + } + + size_t objectIndex = index; + for (sint32 i = 0; i < objectType; i++) + { + objectIndex += object_entry_group_counts[i]; + } + return GetLoadedObject(objectIndex); + } + Object * GetLoadedObject(const rct_object_entry * entry) override { Object * loadedObject = nullptr; @@ -107,8 +127,11 @@ public: loadedObject = GetOrLoadObject(ori); if (loadedObject != nullptr) { + if (_loadedObjects.size() <= (size_t)slot) + { + _loadedObjects.resize(slot + 1); + } _loadedObjects[slot] = loadedObject; - UpdateLegacyLoadedObjectList(); UpdateSceneryGroupIndexes(); reset_type_to_ride_entry_index_map(); } @@ -121,32 +144,28 @@ public: bool LoadObjects(const rct_object_entry * entries, size_t count) override { // Find all the required objects - size_t numRequiredObjects; - auto requiredObjects = new const ObjectRepositoryItem *[OBJECT_ENTRY_COUNT]; - if (!GetRequiredObjects(entries, requiredObjects, &numRequiredObjects)) + bool missingObjects; + auto requiredObjects = GetRequiredObjects(entries, &missingObjects); + if (missingObjects) { - delete[] requiredObjects; return false; } // Create a new list of loaded objects - size_t numNewLoadedObjects; - Object * * loadedObjects = LoadObjects(requiredObjects, &numNewLoadedObjects); + size_t numNewLoadedObjects = 0; + auto loadedObjects = LoadObjects(requiredObjects, &numNewLoadedObjects); - delete[] requiredObjects; - - if (loadedObjects == nullptr) + if (!std::get<0>(loadedObjects)) { UnloadAll(); return false; } else { - SetNewLoadedObjectList(loadedObjects); - UpdateLegacyLoadedObjectList(); + SetNewLoadedObjectList(std::get<1>(loadedObjects)); UpdateSceneryGroupIndexes(); reset_type_to_ride_entry_index_map(); - log_verbose("%u / %u new objects loaded", numNewLoadedObjects, numRequiredObjects); + log_verbose("%u / %u new objects loaded", numNewLoadedObjects, requiredObjects.size()); return true; } } @@ -175,7 +194,6 @@ public: if (numObjectsUnloaded > 0) { - UpdateLegacyLoadedObjectList(); UpdateSceneryGroupIndexes(); reset_type_to_ride_entry_index_map(); } @@ -183,35 +201,26 @@ public: void UnloadAll() override { - if (_loadedObjects != nullptr) + for (auto object : _loadedObjects) { - for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) - { - UnloadObject(_loadedObjects[i]); - } + UnloadObject(object); } - UpdateLegacyLoadedObjectList(); UpdateSceneryGroupIndexes(); reset_type_to_ride_entry_index_map(); } void ResetObjects() override { - if (_loadedObjects != nullptr) + for (auto loadedObject : _loadedObjects) { - for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) + if (loadedObject != nullptr) { - Object * loadedObject = _loadedObjects[i]; - if (loadedObject != nullptr) - { - loadedObject->Unload(); - loadedObject->Load(); - } + loadedObject->Unload(); + loadedObject->Load(); } - UpdateLegacyLoadedObjectList(); - UpdateSceneryGroupIndexes(); - reset_type_to_ride_entry_index_map(); } + UpdateSceneryGroupIndexes(); + reset_type_to_ride_entry_index_map(); } std::vector GetPackableObjects() override @@ -257,16 +266,13 @@ public: private: sint32 FindSpareSlot(uint8 objectType) { - if (_loadedObjects != nullptr) + sint32 firstIndex = GetIndexFromTypeEntry(objectType, 0); + sint32 endIndex = firstIndex + object_entry_group_counts[objectType]; + for (sint32 i = firstIndex; i < endIndex; i++) { - sint32 firstIndex = GetIndexFromTypeEntry(objectType, 0); - sint32 endIndex = firstIndex + object_entry_group_counts[objectType]; - for (sint32 i = firstIndex; i < endIndex; i++) + if (_loadedObjects.size() > (size_t)i && _loadedObjects[i] == nullptr) { - if (_loadedObjects[i] == nullptr) - { - return i; - } + return i; } } return -1; @@ -276,24 +282,18 @@ private: { Guard::ArgumentNotNull(object, GUARD_LINE); - size_t result = SIZE_MAX; - if (_loadedObjects != nullptr) + auto result = std::numeric_limits().max(); + auto it = std::find(_loadedObjects.begin(), _loadedObjects.end(), object); + if (it != _loadedObjects.end()) { - for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) - { - if (_loadedObjects[i] == object) - { - result = i; - break; - } - } + result = std::distance(_loadedObjects.begin(), it); } return result; } - void SetNewLoadedObjectList(Object * * newLoadedObjects) + void SetNewLoadedObjectList(const std::vector &newLoadedObjects) { - if (newLoadedObjects == nullptr) + if (newLoadedObjects.size() == 0) { UnloadAll(); } @@ -301,7 +301,6 @@ private: { UnloadObjectsExcept(newLoadedObjects); } - Memory::Free(_loadedObjects); _loadedObjects = newLoadedObjects; } @@ -316,36 +315,27 @@ private: _objectRepository->UnregisterLoadedObject(ori, object); } - object->Unload(); - delete object; - // Because it's possible to have the same loaded object for multiple // slots, we have to make sure find and set all of them to nullptr - if (_loadedObjects != nullptr) + for (auto &obj : _loadedObjects) { - for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) + if (obj == object) { - if (_loadedObjects[i] == object) - { - _loadedObjects[i] = nullptr; - } + obj = nullptr; } } + + object->Unload(); + delete object; } } - void UnloadObjectsExcept(Object * * newLoadedObjects) + void UnloadObjectsExcept(const std::vector &newLoadedObjects) { - if (_loadedObjects == nullptr) - { - return; - } - // Build a hash set for quick checking auto exceptSet = std::unordered_set(); - for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) + for (auto object : newLoadedObjects) { - Object * object = newLoadedObjects[i]; if (object != nullptr) { exceptSet.insert(object); @@ -355,9 +345,8 @@ private: // Unload objects that are not in the hash set size_t totalObjectsLoaded = 0; size_t numObjectsUnloaded = 0; - for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) + for (auto object : _loadedObjects) { - Object * object = _loadedObjects[i]; if (object != nullptr) { totalObjectsLoaded++; @@ -372,78 +361,45 @@ private: log_verbose("%u / %u objects unloaded", numObjectsUnloaded, totalObjectsLoaded); } - void UpdateLegacyLoadedObjectList() - { - for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) - { - Object * loadedObject = nullptr; - if (_loadedObjects != nullptr) - { - loadedObject = _loadedObjects[i]; - } - - uint8 objectType, entryIndex; - get_type_entry_index(i, &objectType, &entryIndex); - - rct_object_entry_extended * legacyEntry = &object_entry_groups[objectType].entries[entryIndex]; - void * * legacyChunk = &object_entry_groups[objectType].chunks[entryIndex]; - if (loadedObject == nullptr) - { - *legacyEntry = { 0 }; - *legacyChunk = nullptr; - } - else - { - legacyEntry->entry = *loadedObject->GetObjectEntry(); - legacyEntry->chunk_size = 0; - *legacyChunk = loadedObject->GetLegacyData(); - } - } - } - void UpdateSceneryGroupIndexes() { - if (_loadedObjects != nullptr) + for (auto loadedObject : _loadedObjects) { - for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) + if (loadedObject != nullptr) { - Object * loadedObject = _loadedObjects[i]; - if (loadedObject != nullptr) - { - rct_scenery_entry * sceneryEntry; - switch (loadedObject->GetObjectType()) { - case OBJECT_TYPE_SMALL_SCENERY: - sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); - sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); - break; - case OBJECT_TYPE_LARGE_SCENERY: - sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); - sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); - break; - case OBJECT_TYPE_WALLS: - sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); - sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); - break; - case OBJECT_TYPE_BANNERS: - sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); - sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); - break; - case OBJECT_TYPE_PATH_BITS: - sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); - sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); - break; - case OBJECT_TYPE_SCENERY_GROUP: - auto sgObject = dynamic_cast(loadedObject); - sgObject->UpdateEntryIndexes(); - break; - } + rct_scenery_entry * sceneryEntry; + switch (loadedObject->GetObjectType()) { + case OBJECT_TYPE_SMALL_SCENERY: + sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); + sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); + break; + case OBJECT_TYPE_LARGE_SCENERY: + sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); + sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); + break; + case OBJECT_TYPE_WALLS: + sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); + sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); + break; + case OBJECT_TYPE_BANNERS: + sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); + sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); + break; + case OBJECT_TYPE_PATH_BITS: + sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData(); + sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject); + break; + case OBJECT_TYPE_SCENERY_GROUP: + auto sgObject = dynamic_cast(loadedObject); + sgObject->UpdateEntryIndexes(); + break; } } - - // HACK Scenery window will lose its tabs after changing the scenery group indexing - // for now just close it, but it will be better to later tell it to invalidate the tabs - window_close_by_class(WC_SCENERY); } + + // HACK Scenery window will lose its tabs after changing the scenery group indexing + // for now just close it, but it will be better to later tell it to invalidate the tabs + window_close_by_class(WC_SCENERY); } uint8 GetPrimarySceneryGroupEntryIndex(Object * loadedObject) @@ -517,12 +473,10 @@ private: return invalidEntries; } - bool GetRequiredObjects(const rct_object_entry * entries, - const ObjectRepositoryItem * * requiredObjects, - size_t * outNumRequiredObjects) + std::vector GetRequiredObjects(const rct_object_entry * entries, bool * missingObjects) { - bool missingObjects = false; - size_t numRequiredObjects = 0; + std::vector requiredObjects; + *missingObjects = false; for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) { const rct_object_entry * entry = &entries[i]; @@ -532,29 +486,23 @@ private: ori = _objectRepository->FindObject(entry); if (ori == nullptr && object_entry_get_type(entry) != OBJECT_TYPE_SCENARIO_TEXT) { - missingObjects = true; + *missingObjects = true; ReportMissingObject(entry); } - numRequiredObjects++; } - requiredObjects[i] = ori; + requiredObjects.push_back(ori); } - - if (outNumRequiredObjects != nullptr) - { - *outNumRequiredObjects = numRequiredObjects; - } - return !missingObjects; + return requiredObjects; } - Object * * LoadObjects(const ObjectRepositoryItem * * requiredObjects, size_t * outNewObjectsLoaded) + std::pair> LoadObjects(std::vector &requiredObjects, size_t * outNewObjectsLoaded) { size_t newObjectsLoaded = 0; - Object * * loadedObjects = Memory::AllocateArray(OBJECT_ENTRY_COUNT); - for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++) + std::vector loadedObjects; + loadedObjects.reserve(OBJECT_ENTRY_COUNT); + for (auto ori : requiredObjects) { Object * loadedObject = nullptr; - const ObjectRepositoryItem * ori = requiredObjects[i]; if (ori != nullptr) { loadedObject = ori->LoadedObject; @@ -564,20 +512,19 @@ private: if (loadedObject == nullptr) { ReportObjectLoadProblem(&ori->ObjectEntry); - Memory::Free(loadedObjects); - return nullptr; + return std::make_pair(false, std::vector()); } else { newObjectsLoaded++; } } } - loadedObjects[i] = loadedObject; + loadedObjects.push_back(loadedObject); } if (outNewObjectsLoaded != nullptr) { *outNewObjectsLoaded = newObjectsLoaded; } - return loadedObjects; + return std::make_pair(true, loadedObjects); } Object * GetOrLoadObject(const ObjectRepositoryItem * ori) diff --git a/src/openrct2/object/ObjectManager.h b/src/openrct2/object/ObjectManager.h index bd2a1be382..b34cfb31cc 100644 --- a/src/openrct2/object/ObjectManager.h +++ b/src/openrct2/object/ObjectManager.h @@ -29,6 +29,7 @@ interface IObjectManager virtual ~IObjectManager() { } virtual Object * GetLoadedObject(size_t index) abstract; + virtual Object * GetLoadedObject(sint32 objectType, 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; diff --git a/src/openrct2/paint/tile_element/Entrance.cpp b/src/openrct2/paint/tile_element/Entrance.cpp index eafd2949bf..82febf5a72 100644 --- a/src/openrct2/paint/tile_element/Entrance.cpp +++ b/src/openrct2/paint/tile_element/Entrance.cpp @@ -221,7 +221,7 @@ static void park_entrance_paint(paint_session * session, uint8 direction, sint32 sub_98197C(session, image_id, 0, 0, 32, 0x1C, 0, height, 0, 2, height, get_current_rotation()); } - entrance = (rct_entrance_type*)object_entry_groups[OBJECT_TYPE_PARK_ENTRANCE].chunks[0]; + entrance = (rct_entrance_type *)object_entry_get_chunk(OBJECT_TYPE_PARK_ENTRANCE, 0); if (entrance == nullptr) { return; @@ -268,7 +268,7 @@ static void park_entrance_paint(paint_session * session, uint8 direction, sint32 break; case 1: case 2: - entrance = (rct_entrance_type*)object_entry_groups[OBJECT_TYPE_PARK_ENTRANCE].chunks[0]; + entrance = (rct_entrance_type *)object_entry_get_chunk(OBJECT_TYPE_PARK_ENTRANCE, 0); if (entrance == nullptr) { return; diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index f1eca3636a..778d1093fc 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -35,6 +35,7 @@ #include "../management/NewsItem.h" #include "../network/network.h" #include "../object/ObjectList.h" +#include "../object/ObjectManager.h" #include "../OpenRCT2.h" #include "../peep/Peep.h" #include "../peep/Staff.h" @@ -233,13 +234,17 @@ Ride *get_ride(sint32 index) rct_ride_entry * get_ride_entry(sint32 index) { - if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE]) + rct_ride_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) { - log_error("invalid index %d for ride type", index); - return nullptr; + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_RIDE, index); + if (obj != nullptr) + { + result = (rct_ride_entry *)obj->GetLegacyData(); + } } - - return gRideEntries[index]; + return result; } void get_ride_entry_name(char *name, sint32 index) @@ -250,7 +255,7 @@ void get_ride_entry_name(char *name, sint32 index) return; } - const char *entryName = object_entry_groups[OBJECT_TYPE_RIDE].entries[index].name; + const auto entryName = object_entry_get_entry(OBJECT_TYPE_RIDE, index)->name; memcpy(name, entryName, 8); name[8] = '\0'; } diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index abf3087bd4..58f7d4fce3 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -492,7 +492,7 @@ static void track_design_mirror_scenery(rct_track_td6 * td6) } } - rct_scenery_entry * scenery_entry = (rct_scenery_entry *) object_entry_groups[entry_type].chunks[entry_index]; + rct_scenery_entry * scenery_entry = (rct_scenery_entry *)object_entry_get_chunk(entry_type, entry_index); switch (entry_type) { case OBJECT_TYPE_LARGE_SCENERY: diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 5ba9e7d198..285a2542ef 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -261,7 +261,7 @@ static void track_design_save_push_tile_element(sint32 x, sint32 y, rct_tile_ele * * rct2: 0x006D2FA7 */ -static void track_design_save_push_tile_element_desc(rct_object_entry *entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) +static void track_design_save_push_tile_element_desc(const rct_object_entry * entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) { rct_td6_scenery_element *item = &_trackSavedTileElementsDesc[_trackSavedTileElementsDescCount++]; item->scenery_object = *entry; @@ -276,7 +276,7 @@ static void track_design_save_push_tile_element_desc(rct_object_entry *entry, si static void track_design_save_add_scenery(sint32 x, sint32 y, rct_tile_element *tileElement) { sint32 entryType = tileElement->properties.scenery.type; - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_SMALL_SCENERY, entryType); uint8 flags = 0; flags |= tileElement->type & 3; @@ -296,7 +296,7 @@ static void track_design_save_add_large_scenery(sint32 x, sint32 y, rct_tile_ele sint32 direction, sequence; sint32 entryType = scenery_large_get_type(tileElement); - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_LARGE_SCENERY, entryType); sceneryTiles = get_large_scenery_entry(entryType)->large_scenery.tiles; z = tileElement->base_height; @@ -336,7 +336,7 @@ static void track_design_save_add_large_scenery(sint32 x, sint32 y, rct_tile_ele static void track_design_save_add_wall(sint32 x, sint32 y, rct_tile_element *tileElement) { sint32 entryType = tileElement->properties.wall.type; - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_WALLS].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_WALLS, entryType); uint8 flags = 0; flags |= tileElement->type & 3; @@ -352,7 +352,7 @@ static void track_design_save_add_wall(sint32 x, sint32 y, rct_tile_element *til static void track_design_save_add_footpath(sint32 x, sint32 y, rct_tile_element *tileElement) { sint32 entryType = tileElement->properties.path.type >> 4; - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_PATHS].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_PATHS, entryType); uint8 flags = 0; flags |= tileElement->properties.path.edges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK; @@ -427,7 +427,7 @@ static void track_design_save_pop_tile_element(sint32 x, sint32 y, rct_tile_elem * * rct2: 0x006D2FDD */ -static void track_design_save_pop_tile_element_desc(rct_object_entry *entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) +static void track_design_save_pop_tile_element_desc(const rct_object_entry *entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) { size_t removeIndex = SIZE_MAX; for (size_t i = 0; i < _trackSavedTileElementsDescCount; i++) { @@ -457,7 +457,7 @@ static void track_design_save_pop_tile_element_desc(rct_object_entry *entry, sin static void track_design_save_remove_scenery(sint32 x, sint32 y, rct_tile_element *tileElement) { sint32 entryType = tileElement->properties.scenery.type; - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_SMALL_SCENERY, entryType); uint8 flags = 0; flags |= tileElement->type & 3; @@ -477,7 +477,7 @@ static void track_design_save_remove_large_scenery(sint32 x, sint32 y, rct_tile_ sint32 direction, sequence; sint32 entryType = scenery_large_get_type(tileElement); - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_LARGE_SCENERY, entryType); sceneryTiles = get_large_scenery_entry(entryType)->large_scenery.tiles; z = tileElement->base_height; @@ -517,7 +517,7 @@ static void track_design_save_remove_large_scenery(sint32 x, sint32 y, rct_tile_ static void track_design_save_remove_wall(sint32 x, sint32 y, rct_tile_element *tileElement) { sint32 entryType = tileElement->properties.wall.type; - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_WALLS].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_WALLS, entryType); uint8 flags = 0; flags |= tileElement->type & 3; @@ -533,7 +533,7 @@ static void track_design_save_remove_wall(sint32 x, sint32 y, rct_tile_element * static void track_design_save_remove_footpath(sint32 x, sint32 y, rct_tile_element *tileElement) { sint32 entryType = tileElement->properties.path.type >> 4; - rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_PATHS].entries[entryType]; + auto entry = object_entry_get_entry(OBJECT_TYPE_PATHS, entryType); uint8 flags = 0; flags |= tileElement->properties.path.edges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK; @@ -718,7 +718,7 @@ static rct_track_td6 *track_design_save_to_td6(uint8 rideIndex) rct_track_td6 *td6 = (rct_track_td6 *)calloc(1, sizeof(rct_track_td6)); Ride *ride = get_ride(rideIndex); td6->type = ride->type; - rct_object_entry_extended *object = &object_entry_groups[OBJECT_TYPE_RIDE].entries[ride->subtype]; + auto object = object_entry_get_entry(OBJECT_TYPE_RIDE, ride->subtype); // Note we are only copying rct_object_entry in size and // not the extended as we don't need the chunk size. diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index c5ca968336..f67fa4d20f 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -134,7 +134,7 @@ void scenario_begin() } } else { - rct_stex_entry* stex = g_stexEntries[0]; + auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); if (stex != nullptr) { char *buffer = gCommonStringFormatBuffer; @@ -332,7 +332,7 @@ static void scenario_week_update() ride_check_all_reachable(); ride_update_favourited_stat(); - rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0]; + auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0); if (month <= MONTH_APRIL && water_type != nullptr && water_type->flags & WATER_FLAGS_ALLOW_DUCKS) { // 100 attempts at finding some water to create a few ducks at @@ -643,13 +643,13 @@ bool scenario_prepare_for_save() { gS6Info.entry.flags = 255; - rct_stex_entry* stex = g_stexEntries[0]; + auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0); if (stex != nullptr) { char buffer[256]; format_string(buffer, 256, stex->scenario_name, nullptr); safe_strcpy(gS6Info.name, buffer, sizeof(gS6Info.name)); - memcpy(&gS6Info.entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry)); + memcpy(&gS6Info.entry, object_entry_get_entry(OBJECT_TYPE_SCENARIO_TEXT, 0), sizeof(rct_object_entry)); } if (gS6Info.name[0] == 0) diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index 3975ed880a..2e15588f00 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -84,8 +84,6 @@ typedef struct rct_stex_entry { } rct_stex_entry; assert_struct_size(rct_stex_entry, 7); -#define g_stexEntries ((rct_stex_entry**)object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].chunks) - // This will be useful for backwards compatibility typedef struct rct_s6_data { // SC6[0] diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index c5359c4447..ead8fb4aee 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -21,6 +21,7 @@ #include "../localisation/Localisation.h" #include "../network/network.h" #include "../object/ObjectList.h" +#include "../object/ObjectManager.h" #include "../OpenRCT2.h" #include "../ride/Station.h" #include "../ride/Track.h" @@ -2273,7 +2274,17 @@ void footpath_remove_edges_at(sint32 x, sint32 y, rct_tile_element *tileElement) rct_footpath_entry *get_footpath_entry(sint32 entryIndex) { - return gFootpathEntries[entryIndex]; + rct_footpath_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_PATHS, entryIndex); + if (obj != nullptr) + { + result = (rct_footpath_entry *)obj->GetLegacyData(); + } + } + return result; } uint8 footpath_get_edges(const rct_tile_element * element) diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index 227c355868..5e199e1018 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -269,8 +269,8 @@ static void mapgen_place_trees() for (sint32 i = 0; i < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]; i++) { - rct_scenery_entry * sceneryEntry = get_small_scenery_entry(i); - rct_object_entry_extended * entry = &object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[i]; + auto sceneryEntry = get_small_scenery_entry(i); + auto entry = object_entry_get_entry(OBJECT_TYPE_SMALL_SCENERY, i); if (sceneryEntry == nullptr) continue; diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index 6e6c3901e7..e6098fcb31 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -20,6 +20,7 @@ #include "../localisation/Localisation.h" #include "../network/network.h" #include "../object/ObjectList.h" +#include "../object/ObjectManager.h" #include "../scenario/Scenario.h" #include "Climate.h" #include "Footpath.h" @@ -279,50 +280,92 @@ void scenery_remove_ghost_tool_placement(){ rct_scenery_entry *get_small_scenery_entry(sint32 entryIndex) { - if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]) { - return nullptr; + rct_scenery_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_SMALL_SCENERY, entryIndex); + if (obj != nullptr) + { + result = (rct_scenery_entry *)obj->GetLegacyData(); + } } - return (rct_scenery_entry*)gSmallSceneryEntries[entryIndex]; + return result; } rct_scenery_entry *get_large_scenery_entry(sint32 entryIndex) { - if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_LARGE_SCENERY]) { - return nullptr; + rct_scenery_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_LARGE_SCENERY, entryIndex); + if (obj != nullptr) + { + result = (rct_scenery_entry *)obj->GetLegacyData(); + } } - return (rct_scenery_entry*)gLargeSceneryEntries[entryIndex]; + return result; } rct_scenery_entry *get_wall_entry(sint32 entryIndex) { - if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_WALLS]) { - return nullptr; + rct_scenery_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_WALLS, entryIndex); + if (obj != nullptr) + { + result = (rct_scenery_entry *)obj->GetLegacyData(); + } } - return (rct_scenery_entry*)gWallSceneryEntries[entryIndex]; + return result; } rct_scenery_entry *get_banner_entry(sint32 entryIndex) { - if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_BANNERS]) { - return nullptr; + rct_scenery_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_BANNERS, entryIndex); + if (obj != nullptr) + { + result = (rct_scenery_entry *)obj->GetLegacyData(); + } } - return (rct_scenery_entry*)gBannerSceneryEntries[entryIndex]; + return result; } rct_scenery_entry *get_footpath_item_entry(sint32 entryIndex) { - if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_PATH_BITS]) { - return nullptr; + rct_scenery_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_PATH_BITS, entryIndex); + if (obj != nullptr) + { + result = (rct_scenery_entry *)obj->GetLegacyData(); + } } - return (rct_scenery_entry*)gFootpathAdditionEntries[entryIndex]; + return result; } rct_scenery_group_entry *get_scenery_group_entry(sint32 entryIndex) { - if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_SCENERY_GROUP]) { - return nullptr; + rct_scenery_group_entry * result = nullptr; + auto objMgr = GetObjectManager(); + if (objMgr != nullptr) + { + auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_SCENERY_GROUP, entryIndex); + if (obj != nullptr) + { + result = (rct_scenery_group_entry *)obj->GetLegacyData(); + } } - return (rct_scenery_group_entry*)gSceneryGroupEntries[entryIndex]; + return result; } sint32 get_scenery_id_from_entry_index(uint8 objectType, sint32 entryIndex)