From 3557c7c8eb8586b793a5f20cf311328e66f3d249 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 7 May 2016 13:58:36 +0100 Subject: [PATCH 01/11] add S6 importer and chunk loading --- openrct2.vcxproj | 2 + openrct2.vcxproj.filters | 2 + src/rct2/S6Importer.cpp | 130 +++++++++++++++++++++++++++++++++++++++ src/rct2/S6Importer.h | 45 ++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 src/rct2/S6Importer.cpp create mode 100644 src/rct2/S6Importer.h diff --git a/openrct2.vcxproj b/openrct2.vcxproj index fc17260493..51cb591bc9 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -112,6 +112,7 @@ + @@ -370,6 +371,7 @@ + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index 8a5673ba04..c7fa8868ba 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -270,6 +270,7 @@ + @@ -382,6 +383,7 @@ + diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp new file mode 100644 index 0000000000..351bd33621 --- /dev/null +++ b/src/rct2/S6Importer.cpp @@ -0,0 +1,130 @@ +#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/Exception.hpp" +#include "../core/IStream.hpp" +#include "S6Importer.h" + +extern "C" +{ + #include "../util/sawyercoding.h" +} + +S6Importer::S6Importer() +{ + memset(&_s6, 0, sizeof(_s6)); +} + +void S6Importer::LoadSavedGame(const utf8 * path) +{ + SDL_RWops * rw = SDL_RWFromFile(path, "rb"); + if (rw == nullptr) { + throw IOException("Unable to open SV6."); + } + + LoadSavedGame(rw); + + SDL_RWclose(rw); + + _s6Path = path; +} + +void S6Importer::LoadScenario(const utf8 * path) +{ + SDL_RWops * rw = SDL_RWFromFile(path, "rb"); + if (rw == nullptr) { + throw IOException("Unable to open SV6."); + } + + LoadScenario(rw); + + SDL_RWclose(rw); + + _s6Path = path; +} + +void S6Importer::LoadSavedGame(SDL_RWops *rw) +{ + sawyercoding_read_chunk(rw, (uint8*)&_s6.header); + + // Read packed objects + // TODO try to contain this more and not store objects until later + if (_s6.header.num_packed_objects > 0) { + int j = 0; + for (uint16 i = 0; i < _s6.header.num_packed_objects; i++) + { + j += object_load_packed(rw); + } + if (j > 0) + { + object_list_load(); + } + } + + sawyercoding_read_chunk(rw, (uint8*)&_s6.objects); + sawyercoding_read_chunk(rw, (uint8*)&_s6.elapsed_months); + sawyercoding_read_chunk(rw, (uint8*)&_s6.map_elements); + sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_010E63B8); + sawyercoding_read_chunk(rw, (uint8*)&_s6.guests_in_park); + sawyercoding_read_chunk(rw, (uint8*)&_s6.expenditure_table); + sawyercoding_read_chunk(rw, (uint8*)&_s6.last_guests_in_park); + sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_01357BD0); + sawyercoding_read_chunk(rw, (uint8*)&_s6.park_rating); + sawyercoding_read_chunk(rw, (uint8*)&_s6.park_rating_history); + sawyercoding_read_chunk(rw, (uint8*)&_s6.active_research_types); + sawyercoding_read_chunk(rw, (uint8*)&_s6.balance_history); + sawyercoding_read_chunk(rw, (uint8*)&_s6.current_expenditure); + sawyercoding_read_chunk(rw, (uint8*)&_s6.weekly_profit_history); + sawyercoding_read_chunk(rw, (uint8*)&_s6.park_value); + sawyercoding_read_chunk(rw, (uint8*)&_s6.park_value_history); + sawyercoding_read_chunk(rw, (uint8*)&_s6.completed_company_value); +} + +void S6Importer::LoadScenario(SDL_RWops *rw) +{ + sawyercoding_read_chunk(rw, (uint8*)&_s6.header); + + // Read packed objects + // TODO try to contain this more and not store objects until later + if (_s6.header.num_packed_objects > 0) { + int j = 0; + for (uint16 i = 0; i < _s6.header.num_packed_objects; i++) + { + j += object_load_packed(rw); + } + if (j > 0) + { + object_list_load(); + } + } + + sawyercoding_read_chunk(rw, (uint8*)&_s6.objects); + sawyercoding_read_chunk(rw, (uint8*)&_s6.elapsed_months); + sawyercoding_read_chunk(rw, (uint8*)&_s6.map_elements); + sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_010E63B8); + sawyercoding_read_chunk(rw, (uint8*)&_s6.guests_in_park); + sawyercoding_read_chunk(rw, (uint8*)&_s6.last_guests_in_park); + sawyercoding_read_chunk(rw, (uint8*)&_s6.park_rating); + sawyercoding_read_chunk(rw, (uint8*)&_s6.active_research_types); + sawyercoding_read_chunk(rw, (uint8*)&_s6.current_expenditure); + sawyercoding_read_chunk(rw, (uint8*)&_s6.park_value); + sawyercoding_read_chunk(rw, (uint8*)&_s6.completed_company_value); +} + +void S6Importer::Import() +{ + +} diff --git a/src/rct2/S6Importer.h b/src/rct2/S6Importer.h new file mode 100644 index 0000000000..f0da502f82 --- /dev/null +++ b/src/rct2/S6Importer.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 "../common.h" +#include "../core/List.hpp" + +extern "C" +{ + #include "../scenario.h" +} + +/** + * Class to import RollerCoaster Tycoon 2 scenarios (*.SC6) and saved games (*.SV6). + */ +class S6Importer +{ +public: + S6Importer(); + + void LoadSavedGame(const utf8 * path); + void LoadSavedGame(SDL_RWops *rw); + void LoadScenario(const utf8 * path); + void LoadScenario(SDL_RWops *rw); + void Import(); + +private: + const utf8 * _s6Path; + rct_s6_data _s6; + uint8 _gameVersion; +}; From 30467a1467103a0bb14640b53ad775ad806d82d9 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 7 May 2016 16:20:10 +0100 Subject: [PATCH 02/11] copy over game variables and refactor a few --- src/management/news_item.h | 2 + src/rct2/S6Importer.cpp | 219 +++++++++++++++++++++++++++++++++++++ src/ride/ride_ratings.c | 18 +-- src/ride/ride_ratings.h | 17 +++ src/scenario.h | 67 ++++-------- 5 files changed, 262 insertions(+), 61 deletions(-) diff --git a/src/management/news_item.h b/src/management/news_item.h index 992def6738..cf4e348231 100644 --- a/src/management/news_item.h +++ b/src/management/news_item.h @@ -49,6 +49,8 @@ typedef struct { #define MAX_NEWS_ITEMS 60 +extern rct_news_item *gNewsItems; + void news_item_init_queue(); void news_item_update_current(); void news_item_close_current(); diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index 351bd33621..e71f772d5d 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -20,7 +20,20 @@ extern "C" { + #include "../localisation/date.h" + #include "../localisation/localisation.h" + #include "../management/finance.h" + #include "../management/marketing.h" + #include "../management/news_item.h" + #include "../management/research.h" + #include "../peep/staff.h" + #include "../ride/ride.h" + #include "../ride/ride_ratings.h" + #include "../scenario.h" #include "../util/sawyercoding.h" + #include "../world/climate.h" + #include "../world/map_animation.h" + #include "../world/park.h" } S6Importer::S6Importer() @@ -126,5 +139,211 @@ void S6Importer::LoadScenario(SDL_RWops *rw) void S6Importer::Import() { + gDateMonthsElapsed = _s6.elapsed_months; + gDateMonthTicks = _s6.current_day; + RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32) = _s6.scenario_ticks; + gScenarioSrand0 = _s6.scenario_srand_0; + gScenarioSrand1 = _s6.scenario_srand_1; + memcpy(gMapElements, _s6.map_elements, sizeof(_s6.map_elements)); + + RCT2_GLOBAL(0x0010E63B8, uint32) = _s6.dword_010E63B8; + memcpy(g_sprite_list, _s6.sprites, sizeof(_s6.sprites)); + + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_NEXT_INDEX, uint16) = _s6.sprites_next_index; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_VEHICLE, uint16) = _s6.sprites_start_vehicle; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16) = _s6.sprites_start_peep; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16) = _s6.sprites_start_textfx; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_LITTER, uint16) = _s6.sprites_start_litter; + // pad_013573C6 + RCT2_GLOBAL(0x13573C8, uint16) = _s6.word_013573C8; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_VEHICLE, uint16) = _s6.sprites_next_index; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_PEEP, uint16) = _s6.sprites_count_peep; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_MISC, uint16) = _s6.sprites_count_misc; + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_LITTER, uint16) = _s6.sprites_count_litter; + // pad_013573D2 + gParkName = _s6.park_name; + // pad_013573D6 + gParkNameArgs = _s6.park_name_args; + gInitialCash = _s6.initial_cash; + gBankLoan = _s6.current_loan; + gParkFlags = _s6.park_flags; + gParkEntranceFee = _s6.park_entrance_fee; + // rct1_park_entrance_x + // rct1_park_entrance_y + // pad_013573EE + // rct1_park_entrance_z + memcpy(gPeepSpawns, _s6.peep_spawns, sizeof(_s6.peep_spawns)); + gGuestChangeModifier = _s6.guest_count_change_modifier; + gResearchFundingLevel = _s6.current_research_level; + // pad_01357400 + memcpy(RCT2_ADDRESS(0x01357404, uint32), _s6.ride_types_researched, sizeof(_s6.ride_types_researched)); + memcpy(RCT2_ADDRESS(0x01357424, uint32), _s6.ride_entries_researched, sizeof(_s6.ride_entries_researched)); + memcpy(RCT2_ADDRESS(0x01357444, uint32), _s6.dword_01357444, sizeof(_s6.dword_01357444)); + memcpy(RCT2_ADDRESS(0x01357644, uint32), _s6.dword_01357644, sizeof(_s6.dword_01357644)); + + gNumGuestsInPark = _s6.guests_in_park; + gNumGuestsHeadingForPark = _s6.guests_heading_for_park; + + memcpy(RCT2_ADDRESS(RCT2_ADDRESS_EXPENDITURE_TABLE, money32), _s6.expenditure_table, sizeof(_s6.expenditure_table)); + memcpy(RCT2_ADDRESS(0x01357880, uint32), _s6.dword_01357880, sizeof(_s6.dword_01357880)); + RCT2_GLOBAL(RCT2_ADDRESS_MONTHLY_RIDE_INCOME, money32) = _s6.monthly_ride_income; + RCT2_GLOBAL(0x01357898, money32) = _s6.dword_01357898; + RCT2_GLOBAL(0x0135789C, money32) = _s6.dword_0135789C; + RCT2_GLOBAL(0x013578A0, money32) = _s6.dword_013578A0; + memcpy(RCT2_ADDRESS(0x013578A4, money32), _s6.dword_013578A4, sizeof(_s6.dword_013578A4)); + + RCT2_GLOBAL(RCT2_ADDRESS_LAST_GUESTS_IN_PARK, uint16) = _s6.last_guests_in_park; + // pad_01357BCA + gStaffHandymanColour = _s6.handyman_colour; + gStaffMechanicColour = _s6.mechanic_colour; + gStaffSecurityColour = _s6.security_colour; + + memcpy(RCT2_ADDRESS(0x01357BD0, uint32), _s6.dword_01357BD0, sizeof(_s6.dword_01357BD0)); + + gParkRating = _s6.park_rating; + + memcpy(gParkRatingHistory, _s6.park_rating_history, sizeof(_s6.park_rating_history)); + memcpy(gGuestsInParkHistory, _s6.guests_in_park_history, sizeof(_s6.guests_in_park_history)); + + gResearchPriorities = _s6.active_research_types; + gResearchProgressStage = _s6.research_progress_stage; + RCT2_GLOBAL(RCT2_ADDRESS_LAST_RESEARCHED_ITEM_SUBJECT, uint32) = _s6.last_researched_item_subject; + // pad_01357CF8 + gResearchNextItem = _s6.next_research_item; + gResearchProgress = _s6.research_progress; + gResearchNextCategory = _s6.next_research_category; + gResearchExpectedDay = _s6.next_research_expected_day; + gResearchExpectedMonth = _s6.next_research_expected_month; + gGuestInitialHappiness = _s6.guest_initial_happiness; + gParkSize = _s6.park_size; + _guestGenerationProbability = _s6.guest_generation_probability; + gTotalRideValue = _s6.total_ride_value; + gMaxBankLoan = _s6.maximum_loan; + gGuestInitialCash = _s6.guest_initial_cash; + gGuestInitialHunger = _s6.guest_initial_hunger; + gGuestInitialThirst = _s6.guest_initial_thirst; + gScenarioObjectiveType = _s6.objective_type; + gScenarioObjectiveYear = _s6.objective_year; + // pad_013580FA + gScenarioObjectiveCurrency = _s6.objective_currency; + gScenarioObjectiveNumGuests = _s6.objective_guests; + memcpy(gMarketingCampaignDaysLeft, _s6.campaign_weeks_left, sizeof(_s6.campaign_weeks_left)); + memcpy(gMarketingCampaignRideIndex, _s6.campaign_ride_index, sizeof(_s6.campaign_ride_index)); + + memcpy(gCashHistory, _s6.balance_history, sizeof(_s6.balance_history)); + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_EXPENDITURE, money32) = _s6.current_expenditure; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, money32) = _s6.current_profit; + RCT2_GLOBAL(0x01358334, uint32) = _s6.dword_01358334; + RCT2_GLOBAL(0x01358338, uint16) = _s6.word_01358338; + // pad_0135833A + + memcpy(gWeeklyProfitHistory, _s6.weekly_profit_history, sizeof(_s6.weekly_profit_history)); + + gParkValue = _s6.park_value; + + memcpy(gParkValueHistory, _s6.park_value_history, sizeof(_s6.park_value_history)); + + gScenarioCompletedCompanyValue = _s6.completed_company_value; + RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, money32) = _s6.total_admissions; + RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, money32) = _s6.income_from_admissions; + gCompanyValue = _s6.company_value; + memcpy(RCT2_ADDRESS(0x01358750, uint8), _s6.byte_01358750, sizeof(_s6.byte_01358750)); + memcpy(gCurrentAwards, _s6.awards, sizeof(_s6.awards)); + gLandPrice = _s6.land_price; + gConstructionRightsPrice = _s6.construction_rights_price; + RCT2_GLOBAL(0x01358774, uint16) = _s6.word_01358774; + // pad_01358776 + memcpy(RCT2_ADDRESS(0x01358778, uint32), _s6.dword_01358778, sizeof(_s6.dword_01358778)); + _gameVersion = _s6.game_version_number; + RCT2_GLOBAL(0x013587C0, uint32) = _s6.dword_013587C0; + RCT2_GLOBAL(RCT2_ADDRESS_LOAN_HASH, uint32) = _s6.loan_hash; + RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, uint16) = _s6.ride_count; + // pad_013587CA + RCT2_GLOBAL(0x013587D0, uint32) = _s6.dword_013587D0; + // pad_013587D4 + memcpy(gScenarioCompletedBy, _s6.scenario_completed_name, sizeof(_s6.scenario_completed_name)); + gCashEncrypted = _s6.cash; + // pad_013587FC + RCT2_GLOBAL(0x0135882E, uint16) = _s6.word_0135882E; + gMapSizeUnits = _s6.map_size_units; + gMapSizeMinus2 = _s6.map_size_minus_2; + gMapSize = _s6.map_size; + gMapSizeMaxXY = _s6.map_max_xy; + RCT2_GLOBAL(RCT2_ADDRESS_SAME_PRICE_THROUGHOUT, uint32) = _s6.same_price_throughout; + _suggestedGuestMaximum = _s6.suggested_max_guests; + gScenarioParkRatingWarningDays = _s6.park_rating_warning_days; + RCT2_GLOBAL(0x01358840, uint16) = _s6.word_01358840; + // rct1_water_colour + // pad_01358842 + memcpy(gResearchItems, _s6.research_items, sizeof(_s6.research_items)); + RCT2_GLOBAL(0x01359208, uint16) = _s6.word_01359208; + memcpy(gScenarioName, _s6.scenario_name, sizeof(_s6.scenario_name)); + memcpy(gScenarioDetails, _s6.scenario_description, sizeof(_s6.scenario_description)); + gBankLoanInterestRate = _s6.current_interest_rate; + // pad_0135934B + RCT2_GLOBAL(RCT2_ADDRESS_SAME_PRICE_THROUGHOUT_EXTENDED, uint32) = _s6.same_price_throughout_extended; + memcpy(gParkEntranceX, _s6.park_entrance_x, sizeof(_s6.park_entrance_x)); + memcpy(gParkEntranceY, _s6.park_entrance_y, sizeof(_s6.park_entrance_y)); + memcpy(gParkEntranceZ, _s6.park_entrance_z, sizeof(_s6.park_entrance_z)); + memcpy(gParkEntranceDirection, _s6.park_entrance_direction, sizeof(_s6.park_entrance_direction)); + memcpy(RCT2_ADDRESS(0x0135936C, char), _s6.scenario_filename, sizeof(_s6.scenario_filename)); + memcpy(RCT2_ADDRESS(0x0135946C, uint8), _s6.saved_expansion_pack_names, sizeof(_s6.saved_expansion_pack_names)); + memcpy(gBanners, _s6.banners, sizeof(_s6.banners)); + memcpy(gUserStrings, _s6.custom_strings, sizeof(_s6.custom_strings)); + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) = _s6.game_ticks_1; + memcpy(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride*), _s6.rides, sizeof(_s6.rides)); + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_AGE, uint16) = _s6.saved_age; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, uint16) = _s6.saved_view_x; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, uint16) = _s6.saved_view_y; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) = _s6.saved_view_zoom_and_rotation; + memcpy(RCT2_ADDRESS(gAnimatedObjects, rct_map_animation), _s6.map_animations, sizeof(_s6.map_animations)); + // rct1_map_animations + RCT2_GLOBAL(0x0138B580, uint16) = _s6.num_map_animations; + // pad_0138B582 + + _rideRatingsProximityX = _s6.ride_ratings_proximity_x; + _rideRatingsProximityY = _s6.ride_ratings_proximity_y; + _rideRatingsProximityZ = _s6.ride_ratings_proximity_z; + _rideRatingsProximityStartX = _s6.ride_ratings_proximity_start_x; + _rideRatingsProximityStartY = _s6.ride_ratings_proximity_start_y; + _rideRatingsProximityStartZ = _s6.ride_ratings_proximity_start_z; + _rideRatingsCurrentRide = _s6.ride_ratings_current_ride; + _rideRatingsState = _s6.ride_ratings_state; + _rideRatingsProximityTrackType = _s6.ride_ratings_proximity_track_type; + _rideRatingsProximityBaseHeight = _s6.ride_ratings_proximity_base_height; + _rideRatingsProximityTotal = _s6.ride_ratings_proximity_total; + memcpy(_proximityScores, _s6.ride_ratings_proximity_scores, sizeof(_s6.ride_ratings_proximity_scores)); + _rideRatingsNumBrakes = _s6.ride_ratings_num_brakes; + _rideRatingsNumReversers = _s6.ride_ratings_num_reversers; + RCT2_GLOBAL(0x00138B5CE, uint16) = _s6.word_0138B5CE; + memcpy(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement), _s6.ride_measurements, sizeof(_s6.ride_measurements)); + RCT2_GLOBAL(0x013B0E6C, uint32) = _s6.next_guest_index; + gGrassSceneryTileLoopPosition = _s6.grass_and_scenery_tilepos; + memcpy(gStaffPatrolAreas, _s6.patrol_areas, sizeof(_s6.patrol_areas)); + memcpy(gStaffModes, _s6.staff_modes, sizeof(_s6.staff_modes)); + // unk_13CA73E + // pad_13CA73F + RCT2_GLOBAL(0x013CA740, uint8) = _s6.byte_13CA740; + gClimate = _s6.climate; + // pad_13CA741; + memcpy(RCT2_ADDRESS(0x013CA742, uint8), _s6.byte_13CA742, sizeof(_s6.byte_13CA742)); + // pad_013CA747 + gClimateUpdateTimer = _s6.climate_update_timer; + gClimateCurrentWeather = _s6.current_weather; + gClimateNextWeather = _s6.next_weather; + gClimateNextTemperature = _s6.temperature; + gClimateCurrentWeatherEffect = _s6.current_weather_effect; + gClimateNextWeatherEffect = _s6.next_weather_effect; + gClimateCurrentWeatherGloom = _s6.current_weather_gloom; + gClimateNextWeatherGloom = _s6.next_weather_gloom; + gClimateCurrentRainLevel = _s6.current_rain_level; + gClimateNextRainLevel = _s6.next_rain_level; + memcpy(gNewsItems, _s6.news_items, sizeof(_s6.news_items)); + // pad_13CE730 + // rct1_scenario_flags + gWidePathTileLoopX = _s6.wide_path_tile_loop_x; + gWidePathTileLoopY = _s6.wide_path_tile_loop_y; + // pad_13CE778 } diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 79be12b056..e8261a268a 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -64,19 +64,7 @@ enum { typedef void (*ride_ratings_calculation)(rct_ride *ride); -#define _rideRatingsProximityX RCT2_GLOBAL(0x0138B584, uint16) -#define _rideRatingsProximityY RCT2_GLOBAL(0x0138B586, uint16) -#define _rideRatingsProximityZ RCT2_GLOBAL(0x0138B588, uint16) -#define _rideRatingsCurrentRide RCT2_GLOBAL(0x0138B590, uint8) -#define _rideRatingsState RCT2_GLOBAL(0x0138B591, uint8) -#define _rideRatingsProximityTrackType RCT2_GLOBAL(0x0138B592, uint8) -#define _rideRatingsProximityBaseHeight RCT2_GLOBAL(0x0138B593, uint8) -#define _rideRatingsProximityTotal RCT2_GLOBAL(0x0138B594, uint16) -#define _rideRatingsProximityStartX RCT2_GLOBAL(0x0138B58A, uint16) -#define _rideRatingsProximityStartY RCT2_GLOBAL(0x0138B58C, uint16) -#define _rideRatingsProximityStartZ RCT2_GLOBAL(0x0138B58E, uint16) - -static uint16 *_proximityScores = (uint16*)0x0138B596; +uint16 *_proximityScores = (uint16*)0x0138B596; static const ride_ratings_calculation ride_ratings_calculate_func_table[91]; @@ -605,8 +593,8 @@ static void ride_ratings_score_close_proximity(rct_map_element *inputMapElement) case TRACK_ELEM_BRAKES: RCT2_GLOBAL(0x0138B5CA, uint16)++; break; - case 211: - case 212: + case TRACK_ELEM_LEFT_REVERSER: + case TRACK_ELEM_RIGHT_REVERSER: RCT2_GLOBAL(0x0138B5CC, uint16)++; break; } diff --git a/src/ride/ride_ratings.h b/src/ride/ride_ratings.h index a589c7fcfe..7c8e3579ff 100644 --- a/src/ride/ride_ratings.h +++ b/src/ride/ride_ratings.h @@ -20,6 +20,23 @@ #include "../common.h" #include "ride.h" +#define _rideRatingsProximityX RCT2_GLOBAL(0x0138B584, uint16) +#define _rideRatingsProximityY RCT2_GLOBAL(0x0138B586, uint16) +#define _rideRatingsProximityZ RCT2_GLOBAL(0x0138B588, uint16) +#define _rideRatingsCurrentRide RCT2_GLOBAL(0x0138B590, uint8) +#define _rideRatingsState RCT2_GLOBAL(0x0138B591, uint8) +#define _rideRatingsProximityTrackType RCT2_GLOBAL(0x0138B592, uint8) +#define _rideRatingsProximityBaseHeight RCT2_GLOBAL(0x0138B593, uint8) +#define _rideRatingsProximityTotal RCT2_GLOBAL(0x0138B594, uint16) +#define _rideRatingsProximityStartX RCT2_GLOBAL(0x0138B58A, uint16) +#define _rideRatingsProximityStartY RCT2_GLOBAL(0x0138B58C, uint16) +#define _rideRatingsProximityStartZ RCT2_GLOBAL(0x0138B58E, uint16) + +#define _rideRatingsNumBrakes RCT2_GLOBAL(0x0138B5CA, uint16) +#define _rideRatingsNumReversers RCT2_GLOBAL(0x0138B5CC, uint16) + +extern uint16 *_proximityScores; + void ride_ratings_update_all(); #endif diff --git a/src/scenario.h b/src/scenario.h index b6266b46fc..bb5a45fff8 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -26,6 +26,7 @@ #include "platform/platform.h" #include "world/banner.h" #include "world/map.h" +#include "world/map_animation.h" #include "world/sprite.h" /** @@ -126,7 +127,7 @@ typedef struct { // SC6[4] uint16 elapsed_months; uint16 current_day; - uint32 dword_F663AC; + uint32 scenario_ticks; uint32 scenario_srand_0; uint32 scenario_srand_1; @@ -155,10 +156,10 @@ typedef struct { money32 current_loan; uint32 park_flags; money16 park_entrance_fee; - uint16 word_013573EA; - uint16 word_013573EC; + uint16 rct1_park_entrance_x; + uint16 rct1_park_entrance_y; uint8 pad_013573EE[2]; - uint8 byte_013573F0; + uint8 rct1_park_entrance_z; uint8 pad_013573F1; rct2_peep_spawn peep_spawns[2]; uint8 guest_count_change_modifier; @@ -176,7 +177,7 @@ typedef struct { // Ignored in scenario money32 expenditure_table[14]; uint32 dword_01357880[5]; - uint32 dword_01357894; + uint32 monthly_ride_income; uint32 dword_01357898; uint32 dword_0135789C; uint32 dword_013578A0; @@ -202,8 +203,8 @@ typedef struct { // SC6[10] uint8 active_research_types; uint8 research_progress_stage; - uint32 dword_01357CF4; - uint8 byte_01357CF8[1000]; + uint32 last_researched_item_subject; + uint8 pad_01357CF8[1000]; uint32 next_research_item; uint16 research_progress; uint8 next_research_category; @@ -294,12 +295,12 @@ typedef struct { char custom_strings[0x8000]; uint32 game_ticks_1; rct_ride rides[255]; - uint16 word_01388698; + uint16 saved_age; uint16 saved_view_x; uint16 saved_view_y; uint16 saved_view_zoom_and_rotation; - uint8 map_animations[6000]; - uint8 byte_01389E10[6000]; + rct_map_animation map_animations[1000]; + rct_map_animation rct1_map_animations[1000]; uint16 num_map_animations; uint8 pad_0138B582[2]; uint16 ride_ratings_proximity_x; @@ -313,46 +314,20 @@ typedef struct { uint8 ride_ratings_proximity_track_type; uint8 ride_ratings_proximity_base_height; uint16 ride_ratings_proximity_total; - uint16 word_0138B596; - uint16 word_0138B598; - uint16 word_0138B59A; - uint16 word_0138B59C; - uint16 word_0138B59E; - uint16 word_0138B5A0; - uint16 word_0138B5A2; - uint16 word_0138B5A4; - uint16 word_0138B5A6; - uint16 word_0138B5A8; - uint16 word_0138B5AA; - uint16 word_0138B5AC; - uint16 word_0138B5AE; - uint16 word_0138B5B0; - uint16 word_0138B5B2; - uint16 word_0138B5B4; - uint16 word_0138B5B6; - uint16 word_0138B5B8; - uint16 word_0138B5BA; - uint16 word_0138B5BC; - uint16 word_0138B5BE; - uint16 word_0138B5C0; - uint16 word_0138B5C2; - uint16 word_0138B5C4; - uint16 word_0138B5C6; - uint16 word_0138B5C8; - uint16 word_0138B5CA; - uint16 word_0138B5CC; - uint16 word_0138B5CE[31]; - uint8 ride_measurements[0x25860]; + uint16 ride_ratings_proximity_scores[26]; + uint16 ride_ratings_num_brakes; + uint16 ride_ratings_num_reversers; + uint16 word_0138B5CE; + uint16 pad_0138B5D0[60]; + rct_ride_measurement ride_measurements[8]; uint32 next_guest_index; uint16 grass_and_scenery_tilepos; uint32 patrol_areas[0x6600]; // 512 bytes per staff peep - uint8 byte_13CA672[116]; - uint8 byte_13CA6E6[84]; - uint8 byte_13CA73A[4]; + uint8 staff_modes[204]; uint8 unk_13CA73E; uint8 pad_13CA73F; uint8 byte_13CA740; - uint8 byte_13CA741; + uint8 pad_13CA741; uint8 byte_13CA742[4]; uint8 climate; uint8 pad_013CA747; @@ -368,8 +343,8 @@ typedef struct { uint8 current_rain_level; uint8 next_rain_level; rct_news_item news_items[61]; - uint8 byte_13CE730[64]; - uint32 dword_13CE770; + uint8 pad_13CE730[64]; + uint32 rct1_scenario_flags; uint16 wide_path_tile_loop_x; uint16 wide_path_tile_loop_y; uint8 pad_13CE778[434]; From 3bb1d478132921cfdaa80c2704738c5b5e7c0c6d Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 7 May 2016 17:37:50 +0100 Subject: [PATCH 03/11] use new S6Importer for loading saved games --- src/game.c | 69 ----------------------------------------- src/object.h | 3 +- src/object_list.c | 35 +++++++++++---------- src/rct2/S6Importer.cpp | 53 +++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 86 deletions(-) diff --git a/src/game.c b/src/game.c index 26b06f3e15..ed0ae704bd 100644 --- a/src/game.c +++ b/src/game.c @@ -733,75 +733,6 @@ void game_convert_strings_to_rct2(rct_s6_data *s6) } } -/** - * - * rct2: 0x00675E1B - */ -int game_load_sv6(SDL_RWops* rw) -{ - int i, j; - - if (!sawyercoding_validate_checksum(rw)) { - log_error("invalid checksum"); - - gErrorType = ERROR_TYPE_FILE_LOAD; - gGameCommandErrorTitle = STR_FILE_CONTAINS_INVALID_DATA; - return 0; - } - - rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4; - rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - - // Read first chunk - sawyercoding_read_chunk(rw, (uint8*)s6Header); - if (s6Header->type == S6_TYPE_SAVEDGAME) { - // Read packed objects - if (s6Header->num_packed_objects > 0) { - j = 0; - for (i = 0; i < s6Header->num_packed_objects; i++) - j += object_load_packed(rw); - if (j > 0) - object_list_load(); - } - } - - uint8 load_success = object_read_and_load_entries(rw); - - // Read flags (16 bytes) - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR); - - // Read map elements - memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element)); - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS); - - // Read game data, including sprites - sawyercoding_read_chunk(rw, (uint8*)0x010E63B8); - - if (!load_success){ - set_load_objects_fail_reason(); - if (gInputFlags & INPUT_FLAG_5){ - //call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless - gInputFlags &= ~INPUT_FLAG_5; - } - - return 0;//This never gets called - } - - // The rest is the same as in scenario_load - reset_loaded_objects(); - map_update_tile_pointers(); - reset_0x69EBE4(); - openrct2_reset_object_tween_locations(); - game_convert_strings_to_utf8(); - game_fix_save_vars(); // OpenRCT2 fix broken save games - - // #2407: Resetting screen time to not open a save prompt shortly after loading a park. - gScreenAge = 0; - - gLastAutoSaveTick = SDL_GetTicks(); - return 1; -} - // OpenRCT2 workaround to recalculate some values which are saved redundantly in the save to fix corrupted files. // For example recalculate guest count by looking at all the guests instead of trusting the value in the file. void game_fix_save_vars() { diff --git a/src/object.h b/src/object.h index 39c49a6ffb..d01c7df67f 100644 --- a/src/object.h +++ b/src/object.h @@ -104,7 +104,8 @@ extern void *gLastLoadedObjectChunkData; int object_load_entry(const utf8 *path, rct_object_entry *outEntry); void object_list_load(); void set_load_objects_fail_reason(); -int object_read_and_load_entries(SDL_RWops* rw); +bool object_read_and_load_entries(SDL_RWops* rw); +bool object_load_entries(rct_object_entry* entries); int object_load_packed(SDL_RWops* rw); void object_unload_all(); diff --git a/src/object_list.c b/src/object_list.c index e441841654..3281dbc6f8 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -530,28 +530,32 @@ void set_load_objects_fail_reason() * * rct2: 0x006AA0C6 */ -int object_read_and_load_entries(SDL_RWops* rw) +bool object_read_and_load_entries(SDL_RWops* rw) { object_unload_all(); - int i, j; - rct_object_entry *entries; + // Read all the object entries + rct_object_entry *entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry)); + sawyercoding_read_chunk(rw, (uint8*)entries); + bool result = object_load_entries(entries); + free(entries); + return result; +} +bool object_load_entries(rct_object_entry* entries) +{ log_verbose("loading required objects"); - // Read all the object entries - entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry)); - sawyercoding_read_chunk(rw, (uint8*)entries); - - uint8 load_fail = 0; + bool loadFailed = false; // Load each object - for (i = 0; i < OBJECT_ENTRY_COUNT; i++) { - if (!check_object_entry(&entries[i])) + for (int i = 0; i < OBJECT_ENTRY_COUNT; i++) { + if (!check_object_entry(&entries[i])) { continue; + } // Get entry group index int entryGroupIndex = i; - for (j = 0; j < countof(object_entry_group_counts); j++) { + for (int j = 0; j < countof(object_entry_group_counts); j++) { if (entryGroupIndex < object_entry_group_counts[j]) break; entryGroupIndex -= object_entry_group_counts[j]; @@ -561,18 +565,17 @@ int object_read_and_load_entries(SDL_RWops* rw) if (!object_load_chunk(entryGroupIndex, &entries[i], NULL)) { log_error("failed to load entry: %.8s", entries[i].name); memcpy((char*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, &entries[i], sizeof(rct_object_entry)); - load_fail = 1; + loadFailed = true; } } - free(entries); - if (load_fail){ + if (loadFailed) { object_unload_all(); - return 0; + return false; } log_verbose("finished loading required objects"); - return 1; + return true; } diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index e71f772d5d..7d439f5f31 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -20,12 +20,14 @@ extern "C" { + #include "../game.h" #include "../localisation/date.h" #include "../localisation/localisation.h" #include "../management/finance.h" #include "../management/marketing.h" #include "../management/news_item.h" #include "../management/research.h" + #include "../openrct2.h" #include "../peep/staff.h" #include "../ride/ride.h" #include "../ride/ride_ratings.h" @@ -139,6 +141,8 @@ void S6Importer::LoadScenario(SDL_RWops *rw) void S6Importer::Import() { + RCT2_GLOBAL(0x009E34E4, rct_s6_header) = _s6.header; + gDateMonthsElapsed = _s6.elapsed_months; gDateMonthTicks = _s6.current_day; RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32) = _s6.scenario_ticks; @@ -346,4 +350,53 @@ void S6Importer::Import() gWidePathTileLoopX = _s6.wide_path_tile_loop_x; gWidePathTileLoopY = _s6.wide_path_tile_loop_y; // pad_13CE778 + + // Fix and set dynamic variables + if (!object_load_entries(_s6.objects)) { + throw Exception("Unable to load objects."); + } + reset_loaded_objects(); + map_update_tile_pointers(); + reset_0x69EBE4(); + game_convert_strings_to_utf8(); + game_fix_save_vars(); // OpenRCT2 fix broken save games +} + +extern "C" +{ + /** + * + * rct2: 0x00675E1B + */ + int game_load_sv6(SDL_RWops* rw) + { + if (!sawyercoding_validate_checksum(rw)) { + log_error("invalid checksum"); + + gErrorType = ERROR_TYPE_FILE_LOAD; + gGameCommandErrorTitle = STR_FILE_CONTAINS_INVALID_DATA; + return 0; + } + + bool result = false; + auto s6Importer = new S6Importer(); + try + { + s6Importer->LoadSavedGame(rw); + s6Importer->Import(); + + openrct2_reset_object_tween_locations(); + result = true; + } + catch (Exception ex) + { + set_load_objects_fail_reason(); + } + delete s6Importer; + + // #2407: Resetting screen time to not open a save prompt shortly after loading a park. + gScreenAge = 0; + gLastAutoSaveTick = SDL_GetTicks(); + return result; + } } From 9a61d8c8858142b599654fdae5db6cfde79170e7 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 7 May 2016 22:47:29 +0100 Subject: [PATCH 04/11] add importing of scenarios --- src/rct2/S6Importer.cpp | 100 +++++++++++++++++++++++++++++++------- src/scenario.c | 103 ---------------------------------------- src/scenario.h | 2 +- 3 files changed, 84 insertions(+), 121 deletions(-) diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index 7d439f5f31..9e7e6e58a7 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -20,6 +20,7 @@ extern "C" { + #include "../config.h" #include "../game.h" #include "../localisation/date.h" #include "../localisation/localisation.h" @@ -38,6 +39,13 @@ extern "C" #include "../world/park.h" } +class ObjectLoadException : public Exception +{ +public: + ObjectLoadException() : Exception("Unable to load objects.") { } + ObjectLoadException(const char * message) : Exception(message) { } +}; + S6Importer::S6Importer() { memset(&_s6, 0, sizeof(_s6)); @@ -50,6 +58,15 @@ void S6Importer::LoadSavedGame(const utf8 * path) throw IOException("Unable to open SV6."); } + if (!sawyercoding_validate_checksum(rw)) + { + gErrorType = ERROR_TYPE_FILE_LOAD; + gGameCommandErrorTitle = STR_FILE_CONTAINS_INVALID_DATA; + + log_error("failed to load saved game, invalid checksum"); + throw IOException("Invalid SV6 checksum."); + } + LoadSavedGame(rw); SDL_RWclose(rw); @@ -64,6 +81,17 @@ void S6Importer::LoadScenario(const utf8 * path) throw IOException("Unable to open SV6."); } + if (!gConfigGeneral.allow_loading_with_incorrect_checksum && !sawyercoding_validate_checksum(rw)) + { + SDL_RWclose(rw); + + gErrorType = ERROR_TYPE_FILE_LOAD; + gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA; + + log_error("failed to load scenario, invalid checksum"); + throw IOException("Invalid SC6 checksum."); + } + LoadScenario(rw); SDL_RWclose(rw); @@ -73,7 +101,13 @@ void S6Importer::LoadScenario(const utf8 * path) void S6Importer::LoadSavedGame(SDL_RWops *rw) { + auto meh = SDL_RWtell(rw); + sawyercoding_read_chunk(rw, (uint8*)&_s6.header); + if (_s6.header.type != S6_TYPE_SAVEDGAME) + { + throw Exception("Data is not a saved game."); + } // Read packed objects // TODO try to contain this more and not store objects until later @@ -93,24 +127,17 @@ void S6Importer::LoadSavedGame(SDL_RWops *rw) sawyercoding_read_chunk(rw, (uint8*)&_s6.elapsed_months); sawyercoding_read_chunk(rw, (uint8*)&_s6.map_elements); sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_010E63B8); - sawyercoding_read_chunk(rw, (uint8*)&_s6.guests_in_park); - sawyercoding_read_chunk(rw, (uint8*)&_s6.expenditure_table); - sawyercoding_read_chunk(rw, (uint8*)&_s6.last_guests_in_park); - sawyercoding_read_chunk(rw, (uint8*)&_s6.dword_01357BD0); - sawyercoding_read_chunk(rw, (uint8*)&_s6.park_rating); - sawyercoding_read_chunk(rw, (uint8*)&_s6.park_rating_history); - sawyercoding_read_chunk(rw, (uint8*)&_s6.active_research_types); - sawyercoding_read_chunk(rw, (uint8*)&_s6.balance_history); - sawyercoding_read_chunk(rw, (uint8*)&_s6.current_expenditure); - sawyercoding_read_chunk(rw, (uint8*)&_s6.weekly_profit_history); - sawyercoding_read_chunk(rw, (uint8*)&_s6.park_value); - sawyercoding_read_chunk(rw, (uint8*)&_s6.park_value_history); - sawyercoding_read_chunk(rw, (uint8*)&_s6.completed_company_value); } void S6Importer::LoadScenario(SDL_RWops *rw) { sawyercoding_read_chunk(rw, (uint8*)&_s6.header); + if (_s6.header.type != S6_TYPE_SCENARIO) + { + throw Exception("Data is not a scenario."); + } + + sawyercoding_read_chunk(rw, (uint8*)&_s6.info); // Read packed objects // TODO try to contain this more and not store objects until later @@ -353,7 +380,7 @@ void S6Importer::Import() // Fix and set dynamic variables if (!object_load_entries(_s6.objects)) { - throw Exception("Unable to load objects."); + throw ObjectLoadException(); } reset_loaded_objects(); map_update_tile_pointers(); @@ -368,9 +395,10 @@ extern "C" * * rct2: 0x00675E1B */ - int game_load_sv6(SDL_RWops* rw) + int game_load_sv6(SDL_RWops * rw) { - if (!sawyercoding_validate_checksum(rw)) { + if (!sawyercoding_validate_checksum(rw)) + { log_error("invalid checksum"); gErrorType = ERROR_TYPE_FILE_LOAD; @@ -388,7 +416,7 @@ extern "C" openrct2_reset_object_tween_locations(); result = true; } - catch (Exception ex) + catch (ObjectLoadException) { set_load_objects_fail_reason(); } @@ -399,4 +427,42 @@ extern "C" gLastAutoSaveTick = SDL_GetTicks(); return result; } + + /** + * + * rct2: 0x00676053 + * scenario (ebx) + */ + int scenario_load(const char * path) + { + bool result = false; + auto s6Importer = new S6Importer(); + try + { + s6Importer->LoadScenario(path); + s6Importer->Import(); + + openrct2_reset_object_tween_locations(); + result = true; + } + catch (ObjectLoadException) + { + set_load_objects_fail_reason(); + } + catch (IOException) + { + gErrorType = ERROR_TYPE_FILE_LOAD; + gErrorStringId = STR_UNABLE_TO_LOAD_FILE; + } + catch (Exception) + { + gErrorType = ERROR_TYPE_FILE_LOAD; + gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA; + } + delete s6Importer; + + gScreenAge = 0; + gLastAutoSaveTick = SDL_GetTicks(); + return result; + } } diff --git a/src/scenario.c b/src/scenario.c index 69c84f9721..75591e9672 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -95,109 +95,6 @@ bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *i return false; } -/** - * - * rct2: 0x00676053 - * scenario (ebx) - */ -int scenario_load(const char *path) -{ - log_verbose("loading scenario, %s", path); - - SDL_RWops* rw; - int i, j; - rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4; - rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - - rw = SDL_RWFromFile(path, "rb"); - if (rw != NULL) { - if (!sawyercoding_validate_checksum(rw) && !gConfigGeneral.allow_loading_with_incorrect_checksum) { - SDL_RWclose(rw); - gErrorType = ERROR_TYPE_FILE_LOAD; - gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA; - - log_error("failed to load scenario, invalid checksum"); - return 0; - } - - // Read first chunk - sawyercoding_read_chunk(rw, (uint8*)s6Header); - if (s6Header->type == S6_TYPE_SCENARIO) { - // Read second chunk - sawyercoding_read_chunk(rw, (uint8*)s6Info); - - // Read packed objects - if (s6Header->num_packed_objects > 0) { - j = 0; - for (i = 0; i < s6Header->num_packed_objects; i++) - j += object_load_packed(rw); - if (j > 0) - object_list_load(); - } - - uint8 load_success = object_read_and_load_entries(rw); - - // Read flags (16 bytes). Loads: - // RCT2_ADDRESS_CURRENT_MONTH_YEAR - // RCT2_ADDRESS_CURRENT_MONTH_TICKS - // RCT2_ADDRESS_SCENARIO_TICKS - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR); - - // Read map elements - memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element)); - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS); - - // Read game data, including sprites - sawyercoding_read_chunk(rw, (uint8*)0x010E63B8); - - // Read number of guests in park and something else - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_GUESTS_IN_PARK); - - // Read ? - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_LAST_GUESTS_IN_PARK); - - // Read park rating - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_PARK_RATING); - - // Read ? - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES); - - // Read ? - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_EXPENDITURE); - - // Read ? - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_PARK_VALUE); - - // Read more game data, including research items and rides - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_COMPLETED_COMPANY_VALUE); - - SDL_RWclose(rw); - if (!load_success){ - log_error("failed to load all entries."); - set_load_objects_fail_reason(); - return 0; - } - - reset_loaded_objects(); - map_update_tile_pointers(); - reset_0x69EBE4(); - openrct2_reset_object_tween_locations(); - game_convert_strings_to_utf8(); - game_fix_save_vars(); // OpenRCT2 fix broken save games - - gLastAutoSaveTick = SDL_GetTicks(); - return 1; - } - - SDL_RWclose(rw); - } - - log_error("failed to find scenario file."); - gErrorType = ERROR_TYPE_FILE_LOAD; - gErrorStringId = STR_FILE_CONTAINS_INVALID_DATA; - return 0; -} - int scenario_load_and_play_from_path(const char *path) { window_close_construction_windows(); diff --git a/src/scenario.h b/src/scenario.h index bb5a45fff8..95b121f6b7 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -318,7 +318,7 @@ typedef struct { uint16 ride_ratings_num_brakes; uint16 ride_ratings_num_reversers; uint16 word_0138B5CE; - uint16 pad_0138B5D0[60]; + uint8 pad_0138B5D0[60]; rct_ride_measurement ride_measurements[8]; uint32 next_guest_index; uint16 grass_and_scenery_tilepos; From 4eb7a7ee0e28b4da46ce0ab9559e6ec97ac4f274 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 8 May 2016 01:22:32 +0100 Subject: [PATCH 05/11] add S6 exporter --- openrct2.vcxproj | 2 + openrct2.vcxproj.filters | 2 + src/rct2/S6Exporter.cpp | 332 +++++++++++++++++++++++++++++++++++++++ src/rct2/S6Exporter.h | 46 ++++++ src/rct2/S6Importer.cpp | 8 +- src/rct2/S6Importer.h | 1 - src/scenario.c | 98 +----------- src/scenario.h | 5 + 8 files changed, 395 insertions(+), 99 deletions(-) create mode 100644 src/rct2/S6Exporter.cpp create mode 100644 src/rct2/S6Exporter.h diff --git a/openrct2.vcxproj b/openrct2.vcxproj index 51cb591bc9..f030bcdc6a 100644 --- a/openrct2.vcxproj +++ b/openrct2.vcxproj @@ -112,6 +112,7 @@ + @@ -371,6 +372,7 @@ + diff --git a/openrct2.vcxproj.filters b/openrct2.vcxproj.filters index c7fa8868ba..9f4c8a18c3 100644 --- a/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -271,6 +271,7 @@ + @@ -384,6 +385,7 @@ + diff --git a/src/rct2/S6Exporter.cpp b/src/rct2/S6Exporter.cpp new file mode 100644 index 0000000000..56166030e5 --- /dev/null +++ b/src/rct2/S6Exporter.cpp @@ -0,0 +1,332 @@ +#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/Exception.hpp" +#include "../core/IStream.hpp" +#include "../core/String.hpp" +#include "S6Exporter.h" + +extern "C" +{ + #include "../config.h" + #include "../game.h" + #include "../interface/viewport.h" + #include "../interface/window.h" + #include "../localisation/date.h" + #include "../localisation/localisation.h" + #include "../management/finance.h" + #include "../management/marketing.h" + #include "../management/news_item.h" + #include "../management/research.h" + #include "../object.h" + #include "../openrct2.h" + #include "../peep/staff.h" + #include "../ride/ride.h" + #include "../ride/ride_ratings.h" + #include "../scenario.h" + #include "../util/sawyercoding.h" + #include "../world/climate.h" + #include "../world/map_animation.h" + #include "../world/park.h" +} + +S6Exporter::S6Exporter() +{ + memset(&_s6, 0, sizeof(_s6)); +} + +void S6Exporter::SaveGame(const utf8 * path) +{ + SDL_RWops * rw = SDL_RWFromFile(path, "rb"); + if (rw == nullptr) + { + throw IOException("Unable to write to destination file."); + } + + SaveGame(rw); + + SDL_RWclose(rw); +} + +void S6Exporter::SaveGame(SDL_RWops *rw) +{ + Save(rw, false); +} + +void S6Exporter::SaveScenario(const utf8 * path) +{ + SDL_RWops * rw = SDL_RWFromFile(path, "rb"); + if (rw == nullptr) + { + throw IOException("Unable to write to destination file."); + } + + SaveGame(rw); + + SDL_RWclose(rw); +} + +void S6Exporter::SaveScenario(SDL_RWops *rw) +{ + Save(rw, true); +} + +void S6Exporter::Save(SDL_RWops * rw, bool isScenario) +{ + _s6.header.type = isScenario ? S6_TYPE_SAVEDGAME : S6_TYPE_SCENARIO; + _s6.header.num_packed_objects = scenario_get_num_packed_objects_to_write(); + _s6.header.version = S6_RCT2_VERSION; + _s6.header.magic_number = S6_MAGIC_NUMBER; + + uint8 * buffer = (uint8 *)malloc(0x600000); + if (buffer == NULL) + { + log_error("Unable to allocate enough space for a write buffer."); + throw Exception("Unable to allocate memory."); + } + + sawyercoding_chunk_header chunkHeader; + int encodedLength; + + // 0: Write header chunk + chunkHeader.encoding = CHUNK_ENCODING_ROTATE; + chunkHeader.length = sizeof(rct_s6_header); + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.header, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 1: Write scenario info chunk + if (_s6.header.type == S6_TYPE_SCENARIO) + { + chunkHeader.encoding = CHUNK_ENCODING_ROTATE; + chunkHeader.length = sizeof(rct_s6_info); + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.info, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + } + + // 2: Write packed objects + if (_s6.header.num_packed_objects > 0) + { + if (!scenario_write_packed_objects(rw)) + { + free(buffer); + throw Exception("Unable to pack objects."); + } + } + + // 3: Write available objects chunk + chunkHeader.encoding = CHUNK_ENCODING_ROTATE; + chunkHeader.length = 721 * sizeof(rct_object_entry); + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)_s6.objects, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 4: Misc fields (data, rand...) chunk + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 16; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.elapsed_months, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 5: Map elements + sprites and other fields chunk + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 0x180000; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)_s6.map_elements, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + if (_s6.header.type == S6_TYPE_SCENARIO) + { + // 6: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 0x27104C; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.dword_010E63B8, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 7: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 4; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.guests_in_park, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 8: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 8; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.last_guests_in_park, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 9: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 2; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.park_rating, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 10: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 1082; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.active_research_types, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 11: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 16; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.current_expenditure, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 12: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 4; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.park_value, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + + // 13: + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 0x761E8; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.completed_company_value, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + } + else + { + // 6: Everything else... + chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; + chunkHeader.length = 0x2E8570; + encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&_s6.dword_010E63B8, chunkHeader); + SDL_RWwrite(rw, buffer, encodedLength, 1); + } + + free(buffer); + + // Determine number of bytes written + size_t fileSize = (size_t)SDL_RWtell(rw); + SDL_RWseek(rw, 0, RW_SEEK_SET); + + // Read all written bytes back into a single buffer + buffer = (uint8 *)malloc(fileSize); + SDL_RWread(rw, buffer, fileSize, 1); + uint32 checksum = sawyercoding_calculate_checksum(buffer, fileSize); + free(buffer); + + // Append the checksum + SDL_RWseek(rw, fileSize, RW_SEEK_SET); + SDL_RWwrite(rw, &checksum, sizeof(uint32), 1); +} + +void S6Exporter::Export() +{ + _s6.info = *(RCT2_ADDRESS(0x0141F570, rct_s6_info)); + + for (int i = 0; i < 721; i++) + { + rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]); + + if (gObjectList[i] == (void *)0xFFFFFFFF) + { + memset(&_s6.objects[i], 0xFF, sizeof(rct_object_entry)); + } + else + { + _s6.objects[i] = *((rct_object_entry*)entry); + } + } + + _s6.elapsed_months = gDateMonthsElapsed; + _s6.current_day = gDateMonthTicks; + _s6.scenario_ticks = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32); + _s6.scenario_srand_0 = gScenarioSrand0; + _s6.scenario_srand_1 = gScenarioSrand1; + + memcpy(&_s6.elapsed_months, (void*)0x00F663A8, 16); + memcpy(_s6.map_elements, (void*)0x00F663B8, 0x180000); + memcpy(&_s6.dword_010E63B8, (void*)0x010E63B8, 0x2E8570); + + String::Set(_s6.scenario_filename, sizeof(_s6.scenario_filename), _scenarioFileName); + + scenario_fix_ghosts(&_s6); + game_convert_strings_to_rct2(&_s6); +} + +extern "C" +{ + // Save game state without modifying any of the state for multiplayer + int scenario_save_network(SDL_RWops * rw) + { + // Set saved view + sint16 viewX, viewY; + uint8 viewZoom, viewRotation; + rct_window * w = window_get_main(); + if (w != nullptr) + { + rct_viewport *viewport = w->viewport; + + viewX = viewport->view_width / 2 + viewport->view_x; + viewY = viewport->view_height / 2 + viewport->view_y; + viewZoom = viewport->zoom; + viewRotation = get_current_rotation(); + } + else + { + viewX = 0; + viewY = 0; + viewZoom = 0; + viewRotation = 0; + } + + gSavedViewX = viewX; + gSavedViewY = viewY; + gSavedViewZoom = viewZoom; + gSavedViewRotation = viewRotation; + + bool result = false; + auto s6exporter = new S6Exporter(); + try + { + s6exporter->Export(); + s6exporter->SaveGame(rw); + result = true; + } + catch (Exception) + { + } + delete s6exporter; + + if (!result) + { + return 0; + } + + reset_loaded_objects(); + + // Write other data not in normal save files + SDL_WriteLE32(rw, gGamePaused); + SDL_WriteLE32(rw, _guestGenerationProbability); + SDL_WriteLE32(rw, _suggestedGuestMaximum); + SDL_WriteU8(rw, gCheatsSandboxMode); + SDL_WriteU8(rw, gCheatsDisableClearanceChecks); + SDL_WriteU8(rw, gCheatsDisableSupportLimits); + SDL_WriteU8(rw, gCheatsDisableTrainLengthLimit); + SDL_WriteU8(rw, gCheatsShowAllOperatingModes); + SDL_WriteU8(rw, gCheatsShowVehiclesFromOtherTrackTypes); + SDL_WriteU8(rw, gCheatsFastLiftHill); + SDL_WriteU8(rw, gCheatsDisableBrakesFailure); + SDL_WriteU8(rw, gCheatsDisableAllBreakdowns); + SDL_WriteU8(rw, gCheatsUnlockAllPrices); + SDL_WriteU8(rw, gCheatsBuildInPauseMode); + SDL_WriteU8(rw, gCheatsIgnoreRideIntensity); + SDL_WriteU8(rw, gCheatsDisableVandalism); + SDL_WriteU8(rw, gCheatsDisableLittering); + SDL_WriteU8(rw, gCheatsNeverendingMarketing); + SDL_WriteU8(rw, gCheatsFreezeClimate); + + gfx_invalidate_screen(); + return 1; + } +} diff --git a/src/rct2/S6Exporter.h b/src/rct2/S6Exporter.h new file mode 100644 index 0000000000..7eddc93b13 --- /dev/null +++ b/src/rct2/S6Exporter.h @@ -0,0 +1,46 @@ +#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include "../common.h" + +extern "C" +{ + #include "../scenario.h" +} + +/** + * Class to export RollerCoaster Tycoon 2 scenarios (*.SC6) and saved games (*.SV6). + */ +class S6Exporter +{ +public: + bool ExportObjects; + + S6Exporter(); + + void SaveGame(const utf8 * path); + void SaveGame(SDL_RWops *rw); + void SaveScenario(const utf8 * path); + void SaveScenario(SDL_RWops *rw); + void Export(); + +private: + rct_s6_data _s6; + + void Save(SDL_RWops *rw, bool isScenario); +}; diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index 9e7e6e58a7..e7f3f84b71 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -54,7 +54,8 @@ S6Importer::S6Importer() void S6Importer::LoadSavedGame(const utf8 * path) { SDL_RWops * rw = SDL_RWFromFile(path, "rb"); - if (rw == nullptr) { + if (rw == nullptr) + { throw IOException("Unable to open SV6."); } @@ -77,7 +78,8 @@ void S6Importer::LoadSavedGame(const utf8 * path) void S6Importer::LoadScenario(const utf8 * path) { SDL_RWops * rw = SDL_RWFromFile(path, "rb"); - if (rw == nullptr) { + if (rw == nullptr) + { throw IOException("Unable to open SV6."); } @@ -452,7 +454,7 @@ extern "C" catch (IOException) { gErrorType = ERROR_TYPE_FILE_LOAD; - gErrorStringId = STR_UNABLE_TO_LOAD_FILE; + gErrorStringId = STR_GAME_SAVE_FAILED; } catch (Exception) { diff --git a/src/rct2/S6Importer.h b/src/rct2/S6Importer.h index f0da502f82..49d6a329b4 100644 --- a/src/rct2/S6Importer.h +++ b/src/rct2/S6Importer.h @@ -17,7 +17,6 @@ #pragma once #include "../common.h" -#include "../core/List.hpp" extern "C" { diff --git a/src/scenario.c b/src/scenario.c index 75591e9672..8a8e70f7fc 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -55,7 +55,7 @@ const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT] = { }; static char _scenarioPath[MAX_PATH]; -static const char *_scenarioFileName = ""; +const char *_scenarioFileName = ""; char *gScenarioName = RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_NAME, char); char *gScenarioDetails = RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char); @@ -789,9 +789,9 @@ static void sub_674BCF() } /** - * Modifys the given S6 data so that ghost elements, rides with no track elements or unused banners / user strings are saved. + * Modifies the given S6 data so that ghost elements, rides with no track elements or unused banners / user strings are saved. */ -static void scenario_fix_ghosts(rct_s6_data *s6) +void scenario_fix_ghosts(rct_s6_data *s6) { // Remove all ghost elements size_t mapElementTotalSize = MAX_MAP_ELEMENTS * sizeof(rct_map_element); @@ -928,98 +928,6 @@ int scenario_save(SDL_RWops* rw, int flags) return 1; } -// Save game state without modifying any of the state for multiplayer -int scenario_save_network(SDL_RWops* rw) -{ - rct_window *w; - rct_viewport *viewport; - int viewX, viewY, viewZoom, viewRotation; - - /*map_reorganise_elements(); - reset_0x69EBE4(); - sprite_clear_all_unused(); - sub_677552(); - sub_674BCF();*/ - - // Set saved view - w = window_get_main(); - if (w != NULL) { - viewport = w->viewport; - - viewX = viewport->view_width / 2 + viewport->view_x; - viewY = viewport->view_height / 2 + viewport->view_y; - viewZoom = viewport->zoom; - viewRotation = get_current_rotation(); - } else { - viewX = 0; - viewY = 0; - viewZoom = 0; - viewRotation = 0; - } - - gSavedViewX = viewX; - gSavedViewY = viewY; - gSavedViewZoom = viewZoom; - gSavedViewRotation = viewRotation; - - // Prepare S6 - rct_s6_data *s6 = malloc(sizeof(rct_s6_data)); - s6->header.type = S6_TYPE_SAVEDGAME; - s6->header.num_packed_objects = scenario_get_num_packed_objects_to_write(); - s6->header.version = S6_RCT2_VERSION; - s6->header.magic_number = S6_MAGIC_NUMBER; - - memcpy(&s6->info, (rct_s6_info*)0x0141F570, sizeof(rct_s6_info)); - - for (int i = 0; i < 721; i++) { - rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]); - - if (gObjectList[i] == (void *)0xFFFFFFFF) { - memset(&s6->objects[i], 0xFF, sizeof(rct_object_entry)); - } else { - s6->objects[i] = *((rct_object_entry*)entry); - } - } - - memcpy(&s6->elapsed_months, (void*)0x00F663A8, 16); - memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000); - memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570); - - safe_strcpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); - - scenario_fix_ghosts(s6); - game_convert_strings_to_rct2(s6); - scenario_save_s6(rw, s6); - - free(s6); - - reset_loaded_objects(); - - // Write other data not in normal save files - SDL_WriteLE32(rw, gGamePaused); - SDL_WriteLE32(rw, _guestGenerationProbability); - SDL_WriteLE32(rw, _suggestedGuestMaximum); - SDL_WriteU8(rw, gCheatsSandboxMode); - SDL_WriteU8(rw, gCheatsDisableClearanceChecks); - SDL_WriteU8(rw, gCheatsDisableSupportLimits); - SDL_WriteU8(rw, gCheatsDisableTrainLengthLimit); - SDL_WriteU8(rw, gCheatsShowAllOperatingModes); - SDL_WriteU8(rw, gCheatsShowVehiclesFromOtherTrackTypes); - SDL_WriteU8(rw, gCheatsFastLiftHill); - SDL_WriteU8(rw, gCheatsDisableBrakesFailure); - SDL_WriteU8(rw, gCheatsDisableAllBreakdowns); - SDL_WriteU8(rw, gCheatsUnlockAllPrices); - SDL_WriteU8(rw, gCheatsBuildInPauseMode); - SDL_WriteU8(rw, gCheatsIgnoreRideIntensity); - SDL_WriteU8(rw, gCheatsDisableVandalism); - SDL_WriteU8(rw, gCheatsDisableLittering); - SDL_WriteU8(rw, gCheatsNeverendingMarketing); - SDL_WriteU8(rw, gCheatsFreezeClimate); - - gfx_invalidate_screen(); - return 1; -} - bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6) { uint8 *buffer; diff --git a/src/scenario.h b/src/scenario.h index 95b121f6b7..35f3235606 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -455,6 +455,8 @@ extern char gScenarioSavePath[MAX_PATH]; extern int gFirstTimeSave; extern uint32 gLastAutoSaveTick; +extern const char *_scenarioFileName; + bool scenario_scores_save(); void scenario_load_list(); void scenario_list_dispose(); @@ -473,6 +475,9 @@ int scenario_prepare_for_save(); int scenario_save(SDL_RWops* rw, int flags); int scenario_save_network(SDL_RWops* rw); bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6); +int scenario_get_num_packed_objects_to_write(); +int scenario_write_packed_objects(SDL_RWops* rw); +void scenario_fix_ghosts(rct_s6_data *s6); void scenario_set_filename(const char *value); void scenario_failure(); void scenario_success(); From a86bc57a9605b5a6b67f18d876c39e81f85e9fac Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 8 May 2016 16:02:00 +0100 Subject: [PATCH 06/11] use S6Exporter for scenario_save --- src/interface/viewport.c | 23 ++++++++ src/interface/viewport.h | 2 + src/rct2/S6Exporter.cpp | 102 ++++++++++++++++++++++++++--------- src/rct2/S6Exporter.h | 1 + src/rct2/S6Importer.cpp | 3 ++ src/scenario.c | 111 +-------------------------------------- src/scenario.h | 1 + 7 files changed, 109 insertions(+), 134 deletions(-) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 26b5fec266..19fbb254ad 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -1668,3 +1668,26 @@ sint16 get_height_marker_offset() // Height labels in metres return 2 * 256; } + +void viewport_set_saved_view() +{ + sint16 viewX = 0; + sint16 viewY = 0; + uint8 viewZoom = 0; + uint8 viewRotation = 0; + + rct_window * w = window_get_main(); + if (w != NULL) { + rct_viewport *viewport = w->viewport; + + viewX = viewport->view_width / 2 + viewport->view_x; + viewY = viewport->view_height / 2 + viewport->view_y; + viewZoom = viewport->zoom; + viewRotation = get_current_rotation(); + } + + gSavedViewX = viewX; + gSavedViewY = viewY; + gSavedViewZoom = viewZoom; + gSavedViewRotation = viewRotation; +} diff --git a/src/interface/viewport.h b/src/interface/viewport.h index 6a9dc679de..d890ec9175 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -148,4 +148,6 @@ void screen_get_map_xy_side_with_z(sint16 screenX, sint16 screenY, sint16 z, sin uint8 get_current_rotation(); sint16 get_height_marker_offset(); +void viewport_set_saved_view(); + #endif diff --git a/src/rct2/S6Exporter.cpp b/src/rct2/S6Exporter.cpp index 56166030e5..baecf6ed39 100644 --- a/src/rct2/S6Exporter.cpp +++ b/src/rct2/S6Exporter.cpp @@ -45,6 +45,8 @@ extern "C" S6Exporter::S6Exporter() { + ExportObjects = false; + RemoveTracklessRides = false; memset(&_s6, 0, sizeof(_s6)); } @@ -86,11 +88,13 @@ void S6Exporter::SaveScenario(SDL_RWops *rw) void S6Exporter::Save(SDL_RWops * rw, bool isScenario) { - _s6.header.type = isScenario ? S6_TYPE_SAVEDGAME : S6_TYPE_SCENARIO; + _s6.header.type = isScenario ? S6_TYPE_SCENARIO : S6_TYPE_SAVEDGAME; _s6.header.num_packed_objects = scenario_get_num_packed_objects_to_write(); _s6.header.version = S6_RCT2_VERSION; _s6.header.magic_number = S6_MAGIC_NUMBER; + _s6.game_version_number = 201028; + uint8 * buffer = (uint8 *)malloc(0x600000); if (buffer == NULL) { @@ -250,41 +254,91 @@ void S6Exporter::Export() String::Set(_s6.scenario_filename, sizeof(_s6.scenario_filename), _scenarioFileName); + if (RemoveTracklessRides) + { + scenario_remove_trackless_rides(&_s6); + } + scenario_fix_ghosts(&_s6); game_convert_strings_to_rct2(&_s6); } extern "C" { - // Save game state without modifying any of the state for multiplayer - int scenario_save_network(SDL_RWops * rw) - { - // Set saved view - sint16 viewX, viewY; - uint8 viewZoom, viewRotation; - rct_window * w = window_get_main(); - if (w != nullptr) - { - rct_viewport *viewport = w->viewport; + enum { + S6_SAVE_FLAG_EXPORT = 1 << 0, + S6_SAVE_FLAG_SCENARIO = 1 << 1, + S6_SAVE_FLAG_AUTOMATIC = 1 << 31, + }; - viewX = viewport->view_width / 2 + viewport->view_x; - viewY = viewport->view_height / 2 + viewport->view_y; - viewZoom = viewport->zoom; - viewRotation = get_current_rotation(); + /** + * + * rct2: 0x006754F5 + * @param flags bit 0: pack objects, 1: save as scenario + */ + int scenario_save(SDL_RWops* rw, int flags) + { + if (flags & S6_SAVE_FLAG_SCENARIO) + { + log_verbose("saving scenario"); } else { - viewX = 0; - viewY = 0; - viewZoom = 0; - viewRotation = 0; + log_verbose("saving game"); } - gSavedViewX = viewX; - gSavedViewY = viewY; - gSavedViewZoom = viewZoom; - gSavedViewRotation = viewRotation; - + if (!(flags & S6_SAVE_FLAG_AUTOMATIC)) + { + window_close_construction_windows(); + } + + map_reorganise_elements(); + reset_0x69EBE4(); + sprite_clear_all_unused(); + + viewport_set_saved_view(); + + bool result = false; + auto s6exporter = new S6Exporter(); + try + { + s6exporter->ExportObjects = (flags & S6_SAVE_FLAG_EXPORT); + s6exporter->RemoveTracklessRides = true; + s6exporter->Export(); + if (flags & S6_SAVE_FLAG_SCENARIO) + { + s6exporter->SaveScenario(rw); + } + else + { + s6exporter->SaveGame(rw); + } + result = true; + } + catch (Exception) + { + } + delete s6exporter; + + if (flags & S6_SAVE_FLAG_EXPORT) + { + reset_loaded_objects(); + } + + gfx_invalidate_screen(); + + if (result && !(flags & S6_SAVE_FLAG_AUTOMATIC)) + { + gScreenAge = 0; + } + return result; + } + + // Save game state without modifying any of the state for multiplayer + int scenario_save_network(SDL_RWops * rw) + { + viewport_set_saved_view(); + bool result = false; auto s6exporter = new S6Exporter(); try diff --git a/src/rct2/S6Exporter.h b/src/rct2/S6Exporter.h index 7eddc93b13..b715c71b22 100644 --- a/src/rct2/S6Exporter.h +++ b/src/rct2/S6Exporter.h @@ -30,6 +30,7 @@ class S6Exporter { public: bool ExportObjects; + bool RemoveTracklessRides; S6Exporter(); diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index e7f3f84b71..01fd34e955 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -422,6 +422,9 @@ extern "C" { set_load_objects_fail_reason(); } + catch (Exception) + { + } delete s6Importer; // #2407: Resetting screen time to not open a save prompt shortly after loading a park. diff --git a/src/scenario.c b/src/scenario.c index 8a8e70f7fc..33eacfe3a4 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -767,27 +767,6 @@ int scenario_write_available_objects(FILE *file) return 1; } -static void sub_677552() -{ - RCT2_GLOBAL(RCT2_ADDRESS_GAME_VERSION_NUMBER, uint32) = 201028; - RCT2_GLOBAL(0x001358778, uint32) = RCT2_GLOBAL(0x009E2D28, uint32); -} - -static void sub_674BCF() -{ - char *savedExpansionPackNames = (char*)0x0135946C; - - for (int i = 0; i < 16; i++) { - char *dst = &savedExpansionPackNames[i * 128]; - if (RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16) & (1 << i)) { - char *src = &(RCT2_ADDRESS(RCT2_ADDRESS_EXPANSION_NAMES, char)[i * 128]); - safe_strcpy(dst, src, 128); - } else { - *dst = 0; - } - } -} - /** * Modifies the given S6 data so that ghost elements, rides with no track elements or unused banners / user strings are saved. */ @@ -822,7 +801,7 @@ void scenario_fix_ghosts(rct_s6_data *s6) } } -static void scenario_remove_trackless_rides(rct_s6_data *s6) +void scenario_remove_trackless_rides(rct_s6_data *s6) { bool rideHasTrack[MAX_RIDES]; ride_all_has_any_track_elements(rideHasTrack); @@ -840,94 +819,6 @@ static void scenario_remove_trackless_rides(rct_s6_data *s6) } } -/** - * - * rct2: 0x006754F5 - * @param flags bit 0: pack objects, 1: save as scenario - */ -int scenario_save(SDL_RWops* rw, int flags) -{ - rct_window *w; - rct_viewport *viewport; - int viewX, viewY, viewZoom, viewRotation; - - if (flags & 2) - log_verbose("saving scenario"); - else - log_verbose("saving game"); - - - if (!(flags & 0x80000000)) - window_close_construction_windows(); - - map_reorganise_elements(); - reset_0x69EBE4(); - sprite_clear_all_unused(); - sub_677552(); - sub_674BCF(); - - // Set saved view - w = window_get_main(); - if (w != NULL) { - viewport = w->viewport; - - viewX = viewport->view_width / 2 + viewport->view_x; - viewY = viewport->view_height / 2 + viewport->view_y; - viewZoom = viewport->zoom; - viewRotation = get_current_rotation(); - } else { - viewX = gSavedViewX; - viewY = gSavedViewY; - viewZoom = gSavedViewZoom; - viewRotation = gSavedViewRotation; - } - - gSavedViewX = viewX; - gSavedViewY = viewY; - gSavedViewZoom = viewZoom; - gSavedViewRotation = viewRotation; - - // Prepare S6 - rct_s6_data *s6 = malloc(sizeof(rct_s6_data)); - s6->header.type = flags & 2 ? S6_TYPE_SCENARIO : S6_TYPE_SAVEDGAME; - s6->header.num_packed_objects = flags & 1 ? scenario_get_num_packed_objects_to_write() : 0; - s6->header.version = S6_RCT2_VERSION; - s6->header.magic_number = S6_MAGIC_NUMBER; - - memcpy(&s6->info, (rct_s6_info*)0x0141F570, sizeof(rct_s6_info)); - - for (int i = 0; i < OBJECT_ENTRY_COUNT; i++) { - rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]); - - if (gObjectList[i] == (void *)0xFFFFFFFF) { - memset(&s6->objects[i], 0xFF, sizeof(rct_object_entry)); - } else { - s6->objects[i] = *((rct_object_entry*)entry); - } - } - - memcpy(&s6->elapsed_months, (void*)0x00F663A8, 16); - memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000); - memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570); - - safe_strcpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); - - scenario_fix_ghosts(s6); - scenario_remove_trackless_rides(s6); - game_convert_strings_to_rct2(s6); - scenario_save_s6(rw, s6); - - free(s6); - - if (flags & 1) - reset_loaded_objects(); - - gfx_invalidate_screen(); - if (!(flags & 0x80000000)) - gScreenAge = 0; - return 1; -} - bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6) { uint8 *buffer; diff --git a/src/scenario.h b/src/scenario.h index 35f3235606..6054eeea0c 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -477,6 +477,7 @@ int scenario_save_network(SDL_RWops* rw); bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6); int scenario_get_num_packed_objects_to_write(); int scenario_write_packed_objects(SDL_RWops* rw); +void scenario_remove_trackless_rides(rct_s6_data *s6); void scenario_fix_ghosts(rct_s6_data *s6); void scenario_set_filename(const char *value); void scenario_failure(); From 09fab986ed0b3c58ee5eec45aa41e8e7f1b3912f Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 8 May 2016 16:40:24 +0100 Subject: [PATCH 07/11] remove old code --- src/scenario.c | 128 ------------------------------------------------- src/scenario.h | 1 - 2 files changed, 129 deletions(-) diff --git a/src/scenario.c b/src/scenario.c index 33eacfe3a4..0cbde6c7a1 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -819,134 +819,6 @@ void scenario_remove_trackless_rides(rct_s6_data *s6) } } -bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6) -{ - uint8 *buffer; - sawyercoding_chunk_header chunkHeader; - int encodedLength; - long fileSize; - uint32 checksum; - - buffer = malloc(0x600000); - if (buffer == NULL) { - log_error("Unable to allocate enough space for a write buffer."); - return false; - } - - // 0: Write header chunk - chunkHeader.encoding = CHUNK_ENCODING_ROTATE; - chunkHeader.length = sizeof(rct_s6_header); - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->header, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 1: Write scenario info chunk - if (s6->header.type == S6_TYPE_SCENARIO) { - chunkHeader.encoding = CHUNK_ENCODING_ROTATE; - chunkHeader.length = sizeof(rct_s6_info); - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->info, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - } - - // 2: Write packed objects - if (s6->header.num_packed_objects > 0) { - if (!scenario_write_packed_objects(rw)) { - free(buffer); - return false; - } - } - - // 3: Write available objects chunk - chunkHeader.encoding = CHUNK_ENCODING_ROTATE; - chunkHeader.length = 721 * sizeof(rct_object_entry); - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6->objects, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 4: Misc fields (data, rand...) chunk - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 16; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->elapsed_months, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 5: Map elements + sprites and other fields chunk - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 0x180000; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6->map_elements, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - if (s6->header.type == S6_TYPE_SCENARIO) { - // 6: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 0x27104C; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->dword_010E63B8, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 7: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 4; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->guests_in_park, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 8: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 8; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->last_guests_in_park, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 9: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 2; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->park_rating, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 10: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 1082; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->active_research_types, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 11: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 16; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->current_expenditure, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 12: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 4; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->park_value, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - - // 13: - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 0x761E8; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->completed_company_value, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - } else { - // 6: Everything else... - chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED; - chunkHeader.length = 0x2E8570; - encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->dword_010E63B8, chunkHeader); - SDL_RWwrite(rw, buffer, encodedLength, 1); - } - - free(buffer); - - // Determine number of bytes written - fileSize = (long)SDL_RWtell(rw); - SDL_RWseek(rw, 0, RW_SEEK_SET); - - // Read all written bytes back into a single buffer - buffer = malloc(fileSize); - SDL_RWread(rw, buffer, fileSize, 1); - checksum = sawyercoding_calculate_checksum(buffer, fileSize); - free(buffer); - - // Append the checksum - SDL_RWseek(rw, fileSize, RW_SEEK_SET); - SDL_RWwrite(rw, &checksum, sizeof(uint32), 1); - return true; -} - static void scenario_objective_check_guests_by() { uint8 objectiveYear = gScenarioObjectiveYear; diff --git a/src/scenario.h b/src/scenario.h index 6054eeea0c..f78aae82f5 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -474,7 +474,6 @@ unsigned int scenario_rand_max(unsigned int max); int scenario_prepare_for_save(); int scenario_save(SDL_RWops* rw, int flags); int scenario_save_network(SDL_RWops* rw); -bool scenario_save_s6(SDL_RWops* rw, rct_s6_data *s6); int scenario_get_num_packed_objects_to_write(); int scenario_write_packed_objects(SDL_RWops* rw); void scenario_remove_trackless_rides(rct_s6_data *s6); From bc7d1343da03e07945f5903efca96ed22334738d Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 8 May 2016 16:48:42 +0100 Subject: [PATCH 08/11] fix crash, just always reset loaded objects --- src/rct2/S6Exporter.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/rct2/S6Exporter.cpp b/src/rct2/S6Exporter.cpp index baecf6ed39..f57b4610a6 100644 --- a/src/rct2/S6Exporter.cpp +++ b/src/rct2/S6Exporter.cpp @@ -320,11 +320,7 @@ extern "C" } delete s6exporter; - if (flags & S6_SAVE_FLAG_EXPORT) - { - reset_loaded_objects(); - } - + reset_loaded_objects(); gfx_invalidate_screen(); if (result && !(flags & S6_SAVE_FLAG_AUTOMATIC)) From 2ab41b547a81c518e5903ac173feae96c5cbffaf Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 8 May 2016 17:21:55 +0100 Subject: [PATCH 09/11] use S6Importer for network load game --- src/game.c | 78 ----------------------------------------- src/rct2/S6Importer.cpp | 63 ++++++++++++++++++++++++++++++++- src/rct2/S6Importer.h | 2 ++ 3 files changed, 64 insertions(+), 79 deletions(-) diff --git a/src/game.c b/src/game.c index ed0ae704bd..6d7f5fb42a 100644 --- a/src/game.c +++ b/src/game.c @@ -766,84 +766,6 @@ void game_fix_save_vars() { } } -// Load game state for multiplayer -int game_load_network(SDL_RWops* rw) -{ - int i, j; - - rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4; - rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - - // Read first chunk - sawyercoding_read_chunk(rw, (uint8*)s6Header); - if (s6Header->type == S6_TYPE_SAVEDGAME) { - // Read packed objects - if (s6Header->num_packed_objects > 0) { - j = 0; - for (i = 0; i < s6Header->num_packed_objects; i++) - j += object_load_packed(rw); - if (j > 0) - object_list_load(); - } - } - - uint8 load_success = object_read_and_load_entries(rw); - - // Read flags (16 bytes) - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_CURRENT_MONTH_YEAR); - - // Read map elements - memset((void*)RCT2_ADDRESS_MAP_ELEMENTS, 0, MAX_MAP_ELEMENTS * sizeof(rct_map_element)); - sawyercoding_read_chunk(rw, (uint8*)RCT2_ADDRESS_MAP_ELEMENTS); - - // Read game data, including sprites - sawyercoding_read_chunk(rw, (uint8*)0x010E63B8); - - // Read checksum - uint32 checksum; - SDL_RWread(rw, &checksum, sizeof(uint32), 1); - - // Read other data not in normal save files - gGamePaused = SDL_ReadLE32(rw); - _guestGenerationProbability = SDL_ReadLE32(rw); - _suggestedGuestMaximum = SDL_ReadLE32(rw); - gCheatsSandboxMode = SDL_ReadU8(rw); - gCheatsDisableClearanceChecks = SDL_ReadU8(rw); - gCheatsDisableSupportLimits = SDL_ReadU8(rw); - gCheatsDisableTrainLengthLimit = SDL_ReadU8(rw); - gCheatsShowAllOperatingModes = SDL_ReadU8(rw); - gCheatsShowVehiclesFromOtherTrackTypes = SDL_ReadU8(rw); - gCheatsFastLiftHill = SDL_ReadU8(rw); - gCheatsDisableBrakesFailure = SDL_ReadU8(rw); - gCheatsDisableAllBreakdowns = SDL_ReadU8(rw); - gCheatsUnlockAllPrices = SDL_ReadU8(rw); - gCheatsBuildInPauseMode = SDL_ReadU8(rw); - gCheatsIgnoreRideIntensity = SDL_ReadU8(rw); - gCheatsDisableVandalism = SDL_ReadU8(rw); - gCheatsDisableLittering = SDL_ReadU8(rw); - gCheatsNeverendingMarketing = SDL_ReadU8(rw); - gCheatsFreezeClimate = SDL_ReadU8(rw); - - if (!load_success){ - set_load_objects_fail_reason(); - if (gInputFlags & INPUT_FLAG_5){ - //call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless - gInputFlags &= ~INPUT_FLAG_5; - } - - return 0;//This never gets called - } - - // The rest is the same as in scenario load and play - reset_loaded_objects(); - map_update_tile_pointers(); - reset_0x69EBE4(); - openrct2_reset_object_tween_locations(); - game_convert_strings_to_utf8(); - gLastAutoSaveTick = SDL_GetTicks(); - return 1; -} - /** * * rct2: 0x00675E1B diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index 01fd34e955..a70d2f827c 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -48,6 +48,7 @@ public: S6Importer::S6Importer() { + FixIssues = false; memset(&_s6, 0, sizeof(_s6)); } @@ -388,7 +389,10 @@ void S6Importer::Import() map_update_tile_pointers(); reset_0x69EBE4(); game_convert_strings_to_utf8(); - game_fix_save_vars(); // OpenRCT2 fix broken save games + if (FixIssues) + { + game_fix_save_vars(); + } } extern "C" @@ -412,6 +416,7 @@ extern "C" auto s6Importer = new S6Importer(); try { + s6Importer->FixIssues = true; s6Importer->LoadSavedGame(rw); s6Importer->Import(); @@ -444,6 +449,7 @@ extern "C" auto s6Importer = new S6Importer(); try { + s6Importer->FixIssues = true; s6Importer->LoadScenario(path); s6Importer->Import(); @@ -470,4 +476,59 @@ extern "C" gLastAutoSaveTick = SDL_GetTicks(); return result; } + + int game_load_network(SDL_RWops* rw) + { + bool result = false; + auto s6Importer = new S6Importer(); + try + { + s6Importer->LoadSavedGame(rw); + s6Importer->Import(); + + openrct2_reset_object_tween_locations(); + result = true; + } + catch (ObjectLoadException) + { + set_load_objects_fail_reason(); + } + catch (Exception) + { + } + delete s6Importer; + + if (!result) + { + return 0; + } + + // Read checksum + uint32 checksum; + SDL_RWread(rw, &checksum, sizeof(uint32), 1); + + // Read other data not in normal save files + gGamePaused = SDL_ReadLE32(rw); + _guestGenerationProbability = SDL_ReadLE32(rw); + _suggestedGuestMaximum = SDL_ReadLE32(rw); + gCheatsSandboxMode = SDL_ReadU8(rw) != 0; + gCheatsDisableClearanceChecks = SDL_ReadU8(rw) != 0; + gCheatsDisableSupportLimits = SDL_ReadU8(rw) != 0; + gCheatsDisableTrainLengthLimit = SDL_ReadU8(rw) != 0; + gCheatsShowAllOperatingModes = SDL_ReadU8(rw) != 0; + gCheatsShowVehiclesFromOtherTrackTypes = SDL_ReadU8(rw) != 0; + gCheatsFastLiftHill = SDL_ReadU8(rw) != 0; + gCheatsDisableBrakesFailure = SDL_ReadU8(rw) != 0; + gCheatsDisableAllBreakdowns = SDL_ReadU8(rw) != 0; + gCheatsUnlockAllPrices = SDL_ReadU8(rw) != 0; + gCheatsBuildInPauseMode = SDL_ReadU8(rw) != 0; + gCheatsIgnoreRideIntensity = SDL_ReadU8(rw) != 0; + gCheatsDisableVandalism = SDL_ReadU8(rw) != 0; + gCheatsDisableLittering = SDL_ReadU8(rw) != 0; + gCheatsNeverendingMarketing = SDL_ReadU8(rw) != 0; + gCheatsFreezeClimate = SDL_ReadU8(rw) != 0; + + gLastAutoSaveTick = SDL_GetTicks(); + return 1; + } } diff --git a/src/rct2/S6Importer.h b/src/rct2/S6Importer.h index 49d6a329b4..8070dabeae 100644 --- a/src/rct2/S6Importer.h +++ b/src/rct2/S6Importer.h @@ -29,6 +29,8 @@ extern "C" class S6Importer { public: + bool FixIssues; + S6Importer(); void LoadSavedGame(const utf8 * path); From 9d7db7096502bf7baaccfd28cd512c1806e0adc4 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 8 May 2016 18:11:44 +0100 Subject: [PATCH 10/11] export variables individually --- src/addresses.h | 2 +- src/rct2/S6Exporter.cpp | 204 +++++++++++++++++++++++++++++++++++++++- src/rct2/S6Importer.cpp | 2 +- src/ride/ride.c | 2 +- src/scenario.c | 2 +- src/scenario.h | 2 +- 6 files changed, 206 insertions(+), 8 deletions(-) diff --git a/src/addresses.h b/src/addresses.h index 4dbf6177b4..4636f4614f 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -320,8 +320,8 @@ #define RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED 0x013587F8 #define RCT2_ADDRESS_CURRENT_INTEREST_RATE 0x0135934A #define RCT2_ADDRESS_SAME_PRICE_THROUGHOUT 0x01358838 +#define RCT2_ADDRESS_LAST_ENTRANCE_STYLE 0x01358840 #define RCT2_ADDRESS_SAME_PRICE_THROUGHOUT_EXTENDED 0x0135934C - #define RCT2_ADDRESS_GUEST_INITIAL_CASH 0x013580F4 #define RCT2_ADDRESS_GUEST_INITIAL_HAPPINESS 0x013580E9 #define RCT2_ADDRESS_GUEST_INITIAL_HUNGER 0x013580F6 diff --git a/src/rct2/S6Exporter.cpp b/src/rct2/S6Exporter.cpp index f57b4610a6..6356104e70 100644 --- a/src/rct2/S6Exporter.cpp +++ b/src/rct2/S6Exporter.cpp @@ -248,9 +248,207 @@ void S6Exporter::Export() _s6.scenario_srand_0 = gScenarioSrand0; _s6.scenario_srand_1 = gScenarioSrand1; - memcpy(&_s6.elapsed_months, (void*)0x00F663A8, 16); - memcpy(_s6.map_elements, (void*)0x00F663B8, 0x180000); - memcpy(&_s6.dword_010E63B8, (void*)0x010E63B8, 0x2E8570); + memcpy(_s6.map_elements, gMapElements, sizeof(_s6.map_elements)); + + _s6.dword_010E63B8 = RCT2_GLOBAL(0x0010E63B8, uint32); + memcpy(_s6.sprites, g_sprite_list, sizeof(_s6.sprites)); + + _s6.sprites_next_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_NEXT_INDEX, uint16); + _s6.sprites_start_vehicle = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_VEHICLE, uint16); + _s6.sprites_start_peep = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); + _s6.sprites_start_textfx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16); + _s6.sprites_start_litter = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_LITTER, uint16); + // pad_013573C6 + _s6.word_013573C8 = RCT2_GLOBAL(0x13573C8, uint16); + _s6.sprites_next_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_VEHICLE, uint16); + _s6.sprites_count_peep = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_PEEP, uint16); + _s6.sprites_count_misc = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_MISC, uint16); + _s6.sprites_count_litter = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_LITTER, uint16); + // pad_013573D2 + _s6.park_name = gParkName; + // pad_013573D6 + _s6.park_name_args = gParkNameArgs; + _s6.initial_cash = gInitialCash; + _s6.current_loan = gBankLoan; + _s6.park_flags = gParkFlags; + _s6.park_entrance_fee = gParkEntranceFee; + // rct1_park_entrance_x + // rct1_park_entrance_y + // pad_013573EE + // rct1_park_entrance_z + memcpy(_s6.peep_spawns, gPeepSpawns, sizeof(_s6.peep_spawns)); + _s6.guest_count_change_modifier = gGuestChangeModifier; + _s6.current_research_level = gResearchFundingLevel; + // pad_01357400 + memcpy(_s6.ride_types_researched, RCT2_ADDRESS(0x01357404, uint32), sizeof(_s6.ride_types_researched)); + memcpy(_s6.ride_entries_researched, RCT2_ADDRESS(0x01357424, uint32), sizeof(_s6.ride_entries_researched)); + memcpy(_s6.dword_01357444, RCT2_ADDRESS(0x01357444, uint32), sizeof(_s6.dword_01357444)); + memcpy(_s6.dword_01357644, RCT2_ADDRESS(0x01357644, uint32), sizeof(_s6.dword_01357644)); + + _s6.guests_in_park = gNumGuestsInPark; + _s6.guests_heading_for_park = gNumGuestsHeadingForPark; + + memcpy(_s6.expenditure_table, RCT2_ADDRESS(RCT2_ADDRESS_EXPENDITURE_TABLE, money32), sizeof(_s6.expenditure_table)); + memcpy(_s6.dword_01357880, RCT2_ADDRESS(0x01357880, uint32), sizeof(_s6.dword_01357880)); + _s6.monthly_ride_income = RCT2_GLOBAL(RCT2_ADDRESS_MONTHLY_RIDE_INCOME, money32); + _s6.dword_01357898 = RCT2_GLOBAL(0x01357898, money32); + _s6.dword_0135789C = RCT2_GLOBAL(0x0135789C, money32); + _s6.dword_013578A0 = RCT2_GLOBAL(0x013578A0, money32); + memcpy(_s6.dword_013578A4, RCT2_ADDRESS(0x013578A4, money32), sizeof(_s6.dword_013578A4)); + + _s6.last_guests_in_park = RCT2_GLOBAL(RCT2_ADDRESS_LAST_GUESTS_IN_PARK, uint16); + // pad_01357BCA + _s6.handyman_colour = gStaffHandymanColour; + _s6.mechanic_colour = gStaffMechanicColour; + _s6.security_colour = gStaffSecurityColour; + + memcpy(_s6.dword_01357BD0, RCT2_ADDRESS(0x01357BD0, uint32), sizeof(_s6.dword_01357BD0)); + + _s6.park_rating = gParkRating; + + memcpy(_s6.park_rating_history, gParkRatingHistory, sizeof(_s6.park_rating_history)); + memcpy(_s6.guests_in_park_history, gGuestsInParkHistory, sizeof(_s6.guests_in_park_history)); + + _s6.active_research_types = gResearchPriorities; + _s6.research_progress_stage = gResearchProgressStage; + _s6.last_researched_item_subject = RCT2_GLOBAL(RCT2_ADDRESS_LAST_RESEARCHED_ITEM_SUBJECT, uint32); + // pad_01357CF8 + _s6.next_research_item = gResearchNextItem; + _s6.research_progress = gResearchProgress; + _s6.next_research_category = gResearchNextCategory; + _s6.next_research_expected_day = gResearchExpectedDay; + _s6.next_research_expected_month = gResearchExpectedMonth; + _s6.guest_initial_happiness = gGuestInitialHappiness; + _s6.park_size = gParkSize; + _s6.guest_generation_probability = _guestGenerationProbability; + _s6.total_ride_value = gTotalRideValue; + _s6.maximum_loan = gMaxBankLoan; + _s6.guest_initial_cash = gGuestInitialCash; + _s6.guest_initial_hunger = gGuestInitialHunger; + _s6.guest_initial_thirst = gGuestInitialThirst; + _s6.objective_type = gScenarioObjectiveType; + _s6.objective_year = gScenarioObjectiveYear; + // pad_013580FA + _s6.objective_currency = gScenarioObjectiveCurrency; + _s6.objective_guests = gScenarioObjectiveNumGuests; + memcpy(_s6.campaign_weeks_left, gMarketingCampaignDaysLeft, sizeof(_s6.campaign_weeks_left)); + memcpy(_s6.campaign_ride_index, gMarketingCampaignRideIndex, sizeof(_s6.campaign_ride_index)); + + memcpy(_s6.balance_history, gCashHistory, sizeof(_s6.balance_history)); + + _s6.current_expenditure = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_EXPENDITURE, money32); + _s6.current_profit = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, money32); + _s6.dword_01358334 = RCT2_GLOBAL(0x01358334, uint32); + _s6.word_01358338 = RCT2_GLOBAL(0x01358338, uint16); + // pad_0135833A + + memcpy(_s6.weekly_profit_history, gWeeklyProfitHistory, sizeof(_s6.weekly_profit_history)); + + _s6.park_value = gParkValue; + + memcpy(_s6.park_value_history, gParkValueHistory, sizeof(_s6.park_value_history)); + + _s6.completed_company_value = gScenarioCompletedCompanyValue; + _s6.total_admissions = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, money32); + _s6.income_from_admissions = RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, money32); + _s6.company_value = gCompanyValue; + memcpy(_s6.byte_01358750, RCT2_ADDRESS(0x01358750, uint8), sizeof(_s6.byte_01358750)); + memcpy(_s6.awards, gCurrentAwards, sizeof(_s6.awards)); + _s6.land_price = gLandPrice; + _s6.construction_rights_price = gConstructionRightsPrice; + _s6.word_01358774 = RCT2_GLOBAL(0x01358774, uint16); + // pad_01358776 + memcpy(_s6.dword_01358778, RCT2_ADDRESS(0x01358778, uint32), sizeof(_s6.dword_01358778)); + // _s6.game_version_number + _s6.dword_013587C0 = RCT2_GLOBAL(0x013587C0, uint32); + _s6.loan_hash = RCT2_GLOBAL(RCT2_ADDRESS_LOAN_HASH, uint32); + _s6.ride_count = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, uint16); + // pad_013587CA + _s6.dword_013587D0 = RCT2_GLOBAL(0x013587D0, uint32); + // pad_013587D4 + memcpy(_s6.scenario_completed_name, gScenarioCompletedBy, sizeof(_s6.scenario_completed_name)); + _s6.cash = gCashEncrypted; + // pad_013587FC + _s6.word_0135882E = RCT2_GLOBAL(0x0135882E, uint16); + _s6.map_size_units = gMapSizeUnits; + _s6.map_size_minus_2 = gMapSizeMinus2; + _s6.map_size = gMapSize; + _s6.map_max_xy = gMapSizeMaxXY; + _s6.same_price_throughout = RCT2_GLOBAL(RCT2_ADDRESS_SAME_PRICE_THROUGHOUT, uint32); + _s6.suggested_max_guests = _suggestedGuestMaximum; + _s6.park_rating_warning_days = gScenarioParkRatingWarningDays; + _s6.last_entrance_style = RCT2_GLOBAL(RCT2_ADDRESS_LAST_ENTRANCE_STYLE, uint8); + // rct1_water_colour + // pad_01358842 + memcpy(_s6.research_items, gResearchItems, sizeof(_s6.research_items)); + _s6.word_01359208 = RCT2_GLOBAL(0x01359208, uint16); + memcpy(_s6.scenario_name, gScenarioName, sizeof(_s6.scenario_name)); + memcpy(_s6.scenario_description, gScenarioDetails, sizeof(_s6.scenario_description)); + _s6.current_interest_rate = gBankLoanInterestRate; + // pad_0135934B + _s6.same_price_throughout_extended = RCT2_GLOBAL(RCT2_ADDRESS_SAME_PRICE_THROUGHOUT_EXTENDED, uint32); + memcpy(_s6.park_entrance_x, gParkEntranceX, sizeof(_s6.park_entrance_x)); + memcpy(_s6.park_entrance_y, gParkEntranceY, sizeof(_s6.park_entrance_y)); + memcpy(_s6.park_entrance_z, gParkEntranceZ, sizeof(_s6.park_entrance_z)); + memcpy(_s6.park_entrance_direction, gParkEntranceDirection, sizeof(_s6.park_entrance_direction)); + memcpy(_s6.scenario_filename, RCT2_ADDRESS(0x0135936C, char), sizeof(_s6.scenario_filename)); + memcpy(_s6.saved_expansion_pack_names, RCT2_ADDRESS(0x0135946C, uint8), sizeof(_s6.saved_expansion_pack_names)); + memcpy(_s6.banners, gBanners, sizeof(_s6.banners)); + memcpy(_s6.custom_strings, gUserStrings, sizeof(_s6.custom_strings)); + _s6.game_ticks_1 = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); + memcpy(_s6.rides, RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride*), sizeof(_s6.rides)); + _s6.saved_age = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_AGE, uint16); + _s6.saved_view_x = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_X, uint16); + _s6.saved_view_y = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, uint16); + _s6.saved_view_zoom_and_rotation = RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16); + memcpy(_s6.map_animations, RCT2_ADDRESS(gAnimatedObjects, rct_map_animation), sizeof(_s6.map_animations)); + // rct1_map_animations + _s6.num_map_animations = RCT2_GLOBAL(0x0138B580, uint16); + // pad_0138B582 + + _s6.ride_ratings_proximity_x = _rideRatingsProximityX; + _s6.ride_ratings_proximity_y = _rideRatingsProximityY; + _s6.ride_ratings_proximity_z = _rideRatingsProximityZ; + _s6.ride_ratings_proximity_start_x = _rideRatingsProximityStartX; + _s6.ride_ratings_proximity_start_y = _rideRatingsProximityStartY; + _s6.ride_ratings_proximity_start_z = _rideRatingsProximityStartZ; + _s6.ride_ratings_current_ride = _rideRatingsCurrentRide; + _s6.ride_ratings_state = _rideRatingsState; + _s6.ride_ratings_proximity_track_type = _rideRatingsProximityTrackType; + _s6.ride_ratings_proximity_base_height = _rideRatingsProximityBaseHeight; + _s6.ride_ratings_proximity_total = _rideRatingsProximityTotal; + memcpy(_s6.ride_ratings_proximity_scores, _proximityScores, sizeof(_s6.ride_ratings_proximity_scores)); + _s6.ride_ratings_num_brakes = _rideRatingsNumBrakes; + _s6.ride_ratings_num_reversers = _rideRatingsNumReversers; + _s6.word_0138B5CE = RCT2_GLOBAL(0x00138B5CE, uint16); + memcpy(_s6.ride_measurements, RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement), sizeof(_s6.ride_measurements)); + _s6.next_guest_index = RCT2_GLOBAL(0x013B0E6C, uint32); + _s6.grass_and_scenery_tilepos = gGrassSceneryTileLoopPosition; + memcpy(_s6.patrol_areas, gStaffPatrolAreas, sizeof(_s6.patrol_areas)); + memcpy(_s6.staff_modes, gStaffModes, sizeof(_s6.staff_modes)); + // unk_13CA73E + // pad_13CA73F + _s6.byte_13CA740 = RCT2_GLOBAL(0x013CA740, uint8); + _s6.climate = gClimate; + // pad_13CA741; + memcpy(_s6.byte_13CA742, RCT2_ADDRESS(0x013CA742, uint8), sizeof(_s6.byte_13CA742)); + // pad_013CA747 + _s6.climate_update_timer = gClimateUpdateTimer; + _s6.current_weather = gClimateCurrentWeather; + _s6.next_weather = gClimateNextWeather; + _s6.temperature = gClimateNextTemperature; + _s6.current_weather_effect = gClimateCurrentWeatherEffect; + _s6.next_weather_effect = gClimateNextWeatherEffect; + _s6.current_weather_gloom = gClimateCurrentWeatherGloom; + _s6.next_weather_gloom = gClimateNextWeatherGloom; + _s6.current_rain_level = gClimateCurrentRainLevel; + _s6.next_rain_level = gClimateNextRainLevel; + memcpy(_s6.news_items, gNewsItems, sizeof(_s6.news_items)); + // pad_13CE730 + // rct1_scenario_flags + _s6.wide_path_tile_loop_x = gWidePathTileLoopX; + _s6.wide_path_tile_loop_y = gWidePathTileLoopY; + // pad_13CE778 String::Set(_s6.scenario_filename, sizeof(_s6.scenario_filename), _scenarioFileName); diff --git a/src/rct2/S6Importer.cpp b/src/rct2/S6Importer.cpp index a70d2f827c..5e223284dc 100644 --- a/src/rct2/S6Importer.cpp +++ b/src/rct2/S6Importer.cpp @@ -308,7 +308,7 @@ void S6Importer::Import() RCT2_GLOBAL(RCT2_ADDRESS_SAME_PRICE_THROUGHOUT, uint32) = _s6.same_price_throughout; _suggestedGuestMaximum = _s6.suggested_max_guests; gScenarioParkRatingWarningDays = _s6.park_rating_warning_days; - RCT2_GLOBAL(0x01358840, uint16) = _s6.word_01358840; + RCT2_GLOBAL(RCT2_ADDRESS_LAST_ENTRANCE_STYLE, uint8) = _s6.last_entrance_style; // rct1_water_colour // pad_01358842 memcpy(gResearchItems, _s6.research_items, sizeof(_s6.research_items)); diff --git a/src/ride/ride.c b/src/ride/ride.c index 9343184d61..9e79cb04d8 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -6494,7 +6494,7 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in case 6: if (apply) { ride->entrance_style = value; - RCT2_GLOBAL(0x01358840, uint8) = value; + RCT2_GLOBAL(RCT2_ADDRESS_LAST_ENTRANCE_STYLE, uint8) = value; gfx_invalidate_screen(); } break; diff --git a/src/scenario.c b/src/scenario.c index 0cbde6c7a1..e16144933c 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -250,7 +250,7 @@ void scenario_begin() duck_remove_all(); park_calculate_size(); staff_reset_stats(); - RCT2_GLOBAL(0x01358840, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_LAST_ENTRANCE_STYLE, uint8) = 0; memset((void*)0x001358102, 0, 20); RCT2_GLOBAL(0x00135882E, uint16) = 0; diff --git a/src/scenario.h b/src/scenario.h index f78aae82f5..ae2aa4de67 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -275,7 +275,7 @@ typedef struct { uint32 same_price_throughout; uint16 suggested_max_guests; uint16 park_rating_warning_days; - uint8 word_01358840; + uint8 last_entrance_style; uint8 rct1_water_colour; uint8 pad_01358842[2]; rct_research_item research_items[500]; From 47840cb4b8cca2d34421cc87b72610d2d0e9cc88 Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Sun, 8 May 2016 22:34:50 +0100 Subject: [PATCH 11/11] update xcode project --- OpenRCT2.xcodeproj/project.pbxproj | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 2cd9a92cb7..2be98385ab 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 008BF72A1CDAA5C30019A2AD /* track_design_index.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7261CDAA5C30019A2AD /* track_design_index.c */; }; 008BF72B1CDAA5C30019A2AD /* track_design_save.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7271CDAA5C30019A2AD /* track_design_save.c */; }; 008BF72C1CDAA5C30019A2AD /* track_design.c in Sources */ = {isa = PBXBuildFile; fileRef = 008BF7281CDAA5C30019A2AD /* track_design.c */; }; - C61FAAE21CD1643A0010C9D8 /* paint_surface.c in Sources */ = {isa = PBXBuildFile; fileRef = C61FAAE01CD1643A0010C9D8 /* paint_surface.c */; }; C650B2191CCABBDD00B4D91C /* S4Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2151CCABBDD00B4D91C /* S4Importer.cpp */; }; C650B21A1CCABBDD00B4D91C /* tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B2171CCABBDD00B4D91C /* tables.cpp */; }; C650B21C1CCABC4400B4D91C /* ConvertCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C650B21B1CCABC4400B4D91C /* ConvertCommand.cpp */; }; @@ -104,6 +103,8 @@ C686F9541CDBC3B7009F9BFC /* submarine_ride.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F9091CDBC3B7009F9BFC /* submarine_ride.c */; }; C686F9551CDBC3B7009F9BFC /* water_coaster.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F90A1CDBC3B7009F9BFC /* water_coaster.c */; }; C686F9581CDBC4C7009F9BFC /* vehicle_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = C686F9561CDBC4C7009F9BFC /* vehicle_paint.c */; }; + C6B5A7D41CDFE4CB00C9C006 /* S6Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6B5A7D01CDFE4CB00C9C006 /* S6Exporter.cpp */; }; + C6B5A7D51CDFE4CB00C9C006 /* S6Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */; }; D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73EE1C2101890080A7B9 /* libcurl.tbd */; }; D41B73F11C21018C0080A7B9 /* libssl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73F01C21018C0080A7B9 /* libssl.tbd */; }; D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B741C1C210A7A0080A7B9 /* libiconv.tbd */; }; @@ -326,8 +327,6 @@ 008BF7271CDAA5C30019A2AD /* track_design_save.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_design_save.c; sourceTree = ""; }; 008BF7281CDAA5C30019A2AD /* track_design.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_design.c; sourceTree = ""; }; 008BF7291CDAA5C30019A2AD /* track_design.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track_design.h; sourceTree = ""; }; - C61FAAE01CD1643A0010C9D8 /* paint_surface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = paint_surface.c; sourceTree = ""; }; - C61FAAE11CD1643A0010C9D8 /* paint_surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = paint_surface.h; sourceTree = ""; }; C650B2151CCABBDD00B4D91C /* S4Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S4Importer.cpp; sourceTree = ""; }; C650B2161CCABBDD00B4D91C /* S4Importer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S4Importer.h; sourceTree = ""; }; C650B2171CCABBDD00B4D91C /* tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tables.cpp; sourceTree = ""; }; @@ -429,6 +428,10 @@ C686F90A1CDBC3B7009F9BFC /* water_coaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = water_coaster.c; sourceTree = ""; }; C686F9561CDBC4C7009F9BFC /* vehicle_paint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle_paint.c; sourceTree = ""; }; C686F9571CDBC4C7009F9BFC /* vehicle_paint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle_paint.h; sourceTree = ""; }; + C6B5A7D01CDFE4CB00C9C006 /* S6Exporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S6Exporter.cpp; sourceTree = ""; }; + C6B5A7D11CDFE4CB00C9C006 /* S6Exporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S6Exporter.h; sourceTree = ""; }; + C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = S6Importer.cpp; sourceTree = ""; }; + C6B5A7D31CDFE4CB00C9C006 /* S6Importer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = S6Importer.h; sourceTree = ""; }; D41B73EE1C2101890080A7B9 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; D41B73F01C21018C0080A7B9 /* libssl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libssl.tbd; path = usr/lib/libssl.tbd; sourceTree = SDKROOT; }; D41B741C1C210A7A0080A7B9 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; @@ -981,6 +984,18 @@ path = water; sourceTree = ""; }; + C6B5A7CF1CDFE4CB00C9C006 /* rct2 */ = { + isa = PBXGroup; + children = ( + C6B5A7D01CDFE4CB00C9C006 /* S6Exporter.cpp */, + C6B5A7D11CDFE4CB00C9C006 /* S6Exporter.h */, + C6B5A7D21CDFE4CB00C9C006 /* S6Importer.cpp */, + C6B5A7D31CDFE4CB00C9C006 /* S6Importer.h */, + ); + name = rct2; + path = src/rct2; + sourceTree = ""; + }; D41B72431C21015A0080A7B9 /* Sources */ = { isa = PBXGroup; children = ( @@ -996,6 +1011,7 @@ D442715B1CC81B3200D84D28 /* peep */, D44271601CC81B3200D84D28 /* platform */, C650B2141CCABBDD00B4D91C /* rct1 */, + C6B5A7CF1CDFE4CB00C9C006 /* rct2 */, D442716E1CC81B3200D84D28 /* ride */, D44271881CC81B3200D84D28 /* util */, D442718E1CC81B3200D84D28 /* windows */, @@ -1874,6 +1890,7 @@ D442720E1CC81B3200D84D28 /* rect.c in Sources */, C686F9171CDBC3B7009F9BFC /* lim_launched_roller_coaster.c in Sources */, C686F9101CDBC3B7009F9BFC /* giga_coaster.c in Sources */, + C6B5A7D41CDFE4CB00C9C006 /* S6Exporter.cpp in Sources */, D44272351CC81B3200D84D28 /* twitch.cpp in Sources */, D44272691CC81B3200D84D28 /* loadsave.c in Sources */, D44272061CC81B3200D84D28 /* textinputbuffer.c in Sources */, @@ -1973,6 +1990,7 @@ D442727A1CC81B3200D84D28 /* research.c in Sources */, D442722E1CC81B3200D84D28 /* award.c in Sources */, D44272861CC81B3200D84D28 /* staff_fire_prompt.c in Sources */, + C6B5A7D51CDFE4CB00C9C006 /* S6Importer.cpp in Sources */, D44272221CC81B3200D84D28 /* widget.c in Sources */, D44271F71CC81B3200D84D28 /* mixer.cpp in Sources */, D442723D1CC81B3200D84D28 /* osx.m in Sources */,