diff --git a/src/openrct2/cheats.c b/src/openrct2/cheats.c index f4308ba725..48ec7a62f9 100644 --- a/src/openrct2/cheats.c +++ b/src/openrct2/cheats.c @@ -21,6 +21,7 @@ #include "localisation/date.h" #include "management/finance.h" #include "network/network.h" +#include "util/util.h" #include "world/climate.h" #include "world/footpath.h" #include "world/scenery.h" @@ -235,8 +236,7 @@ static void cheat_no_money(bool enabled) static void cheat_set_money(money32 amount) { - money32 money = clamp(INT_MIN, amount, INT_MAX); - gCashEncrypted = ENCRYPT_MONEY(money); + gCashEncrypted = ENCRYPT_MONEY(amount); window_invalidate_by_class(WC_FINANCES); window_invalidate_by_class(WC_BOTTOM_TOOLBAR); @@ -245,19 +245,7 @@ static void cheat_set_money(money32 amount) static void cheat_add_money(money32 amount) { money32 currentMoney = DECRYPT_MONEY(gCashEncrypted); - if (amount >= 0) { - if (currentMoney < INT_MAX - amount) - currentMoney += amount; - else - currentMoney = INT_MAX; - } - else { - money32 absAmount = amount * -1; - if (currentMoney > INT_MIN + absAmount) - currentMoney -= absAmount; - else - currentMoney = INT_MIN; - } + currentMoney = add_clamp_money32(currentMoney, amount); gCashEncrypted = ENCRYPT_MONEY(currentMoney); diff --git a/src/openrct2/common.h b/src/openrct2/common.h index e33c5f5df8..1a1d89dafe 100644 --- a/src/openrct2/common.h +++ b/src/openrct2/common.h @@ -220,16 +220,7 @@ typedef uint16 rct_string_id; #define RESTRICT #endif -#ifdef __cplusplus #define assert_struct_size(x, y) static_assert(sizeof(x) == (y), "Improper struct size") -#else - // Visual Studio does not know _Static_assert - #if !defined(_MSC_VER) - #define assert_struct_size(x, y) _Static_assert(sizeof(x) == (y), "Improper struct size") - #else - #define assert_struct_size(x, y) - #endif // !defined(_MSC_VER) -#endif #ifdef PLATFORM_X86 #ifndef FASTCALL diff --git a/src/openrct2/interface/window.c b/src/openrct2/interface/window.c index 1a366d7357..39eec54670 100644 --- a/src/openrct2/interface/window.c +++ b/src/openrct2/interface/window.c @@ -15,6 +15,7 @@ #pragma endregion #include "../audio/audio.h" +#include "../core/Guard.hpp" #include "../drawing/drawing.h" #include "../editor.h" #include "../game.h" @@ -1274,12 +1275,13 @@ void window_push_others_below(rct_window *w1) */ rct_window *window_get_main() { - rct_window* w; + rct_window* w = NULL; for (w = g_window_list; w < RCT2_NEW_WINDOW; w++) if (w->classification == WC_MAIN_WINDOW) return w; + openrct2_assert(w != NULL, "Failed to get main window"); return NULL; } diff --git a/src/openrct2/intro.c b/src/openrct2/intro.c index 7f8ff7a158..2863216ad2 100644 --- a/src/openrct2/intro.c +++ b/src/openrct2/intro.c @@ -75,8 +75,6 @@ void intro_update() break; case INTRO_STATE_DEVELOPER_BEGIN: - _introStateCounter += 5; - // Set the Y for the Chris Sawyer logo _introStateCounter = -116; diff --git a/src/openrct2/management/finance.c b/src/openrct2/management/finance.c index a5fcdd1ebf..57c50c844e 100644 --- a/src/openrct2/management/finance.c +++ b/src/openrct2/management/finance.c @@ -76,12 +76,7 @@ void finance_payment(money32 amount, rct_expenditure_type type) money32 new_money; //overflow check - if (amount < 0 && cur_money >= INT_MAX + amount) - new_money = INT_MAX; - else if (amount >= 0 && cur_money < INT_MIN + amount) - new_money = INT_MIN; - else - new_money = cur_money - amount; + new_money = add_clamp_money32(cur_money, -amount); gCashEncrypted = ENCRYPT_MONEY(new_money); gExpenditureTable[type] -= amount; diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h index b226cca4f6..a2e7091b6d 100644 --- a/src/openrct2/network/network.h +++ b/src/openrct2/network/network.h @@ -55,7 +55,7 @@ extern "C" { // This define specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "3" +#define NETWORK_STREAM_VERSION "4" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION #ifdef __cplusplus diff --git a/src/openrct2/network/twitch.cpp b/src/openrct2/network/twitch.cpp index 869b8968df..3ddf3e5a4a 100644 --- a/src/openrct2/network/twitch.cpp +++ b/src/openrct2/network/twitch.cpp @@ -199,7 +199,7 @@ namespace Twitch _twitchState = TWITCH_STATE_JOINING; _twitchIdle = false; - http_request_t request; + http_request_t request = { 0 }; request.url = url; request.method = HTTP_METHOD_GET; request.body = nullptr; @@ -276,7 +276,7 @@ namespace Twitch _twitchState = TWITCH_STATE_WAITING; _twitchIdle = false; - http_request_t request; + http_request_t request = { 0 }; request.url = url; request.method = HTTP_METHOD_GET; request.body = NULL; @@ -307,7 +307,7 @@ namespace Twitch _twitchState = TWITCH_STATE_WAITING; _twitchIdle = false; - http_request_t request; + http_request_t request = { 0 }; request.url = url; request.method = HTTP_METHOD_GET; request.body = nullptr; diff --git a/src/openrct2/peep/peep.c b/src/openrct2/peep/peep.c index 164c03733f..aeef199b52 100644 --- a/src/openrct2/peep/peep.c +++ b/src/openrct2/peep/peep.c @@ -1375,16 +1375,24 @@ static sint32 checkForPath(rct_peep *peep){ return 0; } +static uint8 peep_get_action_sprite_type(rct_peep* peep) +{ + if (peep->action >= PEEP_ACTION_NONE_1){ // PEEP_ACTION_NONE_1 or PEEP_ACTION_NONE_2 + return PeepSpecialSpriteToSpriteTypeMap[peep->special_sprite]; + } else if (peep->action < countof(PeepActionToSpriteTypeMap)) { + return PeepActionToSpriteTypeMap[peep->action]; + } else { + openrct2_assert(peep->action >= countof(PeepActionToSpriteTypeMap) && peep->action < PEEP_ACTION_NONE_1, + "Invalid peep action %u", peep->action); + return 0; + } +} + void sub_693B58(rct_peep* peep){ - uint8 action_sprite_type; if (peep->sprite_type >= countof(g_peep_animation_entries)) { return; } - if (peep->action >= PEEP_ACTION_NONE_1){ // PEEP_ACTION_NONE_1 or PEEP_ACTION_NONE_2 - action_sprite_type = PeepSpecialSpriteToSpriteTypeMap[peep->special_sprite]; - } else { - action_sprite_type = PeepActionToSpriteTypeMap[peep->action]; - } + uint8 action_sprite_type = peep_get_action_sprite_type(peep); if (action_sprite_type == peep->action_sprite_type)return; invalidate_sprite_2((rct_sprite*)peep); @@ -9913,11 +9921,18 @@ static sint32 guest_path_find_park_entrance(rct_peep* peep, rct_map_element *map * * rct2: 0x006A72C5 * param dist is not used. + * + * In case where the map element at (x, y) is invalid or there is no entrance + * or queue leading to it the function will not update its arguments. */ static void get_ride_queue_end(sint16 *x, sint16 *y, sint16 *z){ rct_xy16 result = { 0, 0 }; rct_map_element *mapElement = map_get_first_element_at(*x / 32, *y / 32); + if (mapElement == NULL) { + return; + } + bool found = false; do{ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE) diff --git a/src/openrct2/peep/staff.c b/src/openrct2/peep/staff.c index 6725f712e4..d197541e21 100644 --- a/src/openrct2/peep/staff.c +++ b/src/openrct2/peep/staff.c @@ -406,7 +406,7 @@ void game_command_set_staff_order(sint32 *eax, sint32 *ebx, sint32 *ecx, sint32 if(order_id & 0x80){ // change costume uint8 sprite_type = order_id & ~0x80; sprite_type += 4; - if (sprite_type > countof(peep_slow_walking_types)) { + if (sprite_type >= countof(peep_slow_walking_types)) { log_error("Invalid change costume order for sprite_type %u", sprite_type); *ebx = MONEY32_UNDEFINED; return; diff --git a/src/openrct2/ride/ride.c b/src/openrct2/ride/ride.c index cc62c01396..4bf2218982 100644 --- a/src/openrct2/ride/ride.c +++ b/src/openrct2/ride/ride.c @@ -765,7 +765,7 @@ sint32 ride_find_track_gap(rct_xy_element *input, rct_xy_element *output) { rct_window *w; rct_ride *ride; - track_circuit_iterator it, slowIt; + track_circuit_iterator it = { 0 }, slowIt; sint32 rideIndex; assert(map_element_get_type(input->element) == MAP_ELEMENT_TYPE_TRACK); @@ -5194,7 +5194,7 @@ static sint32 ride_is_valid_for_test(sint32 rideIndex, sint32 goingToBeOpen, sin { sint32 stationIndex; rct_ride *ride; - rct_xy_element trackElement, problematicTrackElement; + rct_xy_element trackElement, problematicTrackElement = { 0 }; ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_NULL) @@ -5323,7 +5323,7 @@ static sint32 ride_is_valid_for_open(sint32 rideIndex, sint32 goingToBeOpen, sin { sint32 stationIndex; rct_ride *ride; - rct_xy_element trackElement, problematicTrackElement; + rct_xy_element trackElement, problematicTrackElement = { 0 }; ride = get_ride(rideIndex); diff --git a/src/openrct2/ride/vehicle.c b/src/openrct2/ride/vehicle.c index 1428255b48..41cc13061b 100644 --- a/src/openrct2/ride/vehicle.c +++ b/src/openrct2/ride/vehicle.c @@ -28,6 +28,7 @@ #include "../world/map_animation.h" #include "../world/scenery.h" #include "../world/sprite.h" +#include "../util/util.h" #include "cable_lift.h" #include "ride.h" #include "ride_data.h" @@ -1244,7 +1245,7 @@ static void vehicle_update_measurements(rct_vehicle *vehicle) } if (ride->average_speed_test_timeout == 0 && velocity > 0x8000){ - ride->average_speed += velocity; + ride->average_speed = add_clamp_sint32(ride->average_speed, velocity); ride->time[test_segment]++; } diff --git a/src/openrct2/util/util.c b/src/openrct2/util/util.c index 4a99733acb..27b6116861 100644 --- a/src/openrct2/util/util.c +++ b/src/openrct2/util/util.c @@ -494,3 +494,43 @@ uint8 *util_zlib_deflate(const uint8 *data, size_t data_in_size, size_t *data_ou buffer = realloc(buffer, *data_out_size); return buffer; } + +// Type-independant code left as macro to reduce duplicate code. +#define add_clamp_body(value, value_to_add, min_cap, max_cap) \ + if ((value_to_add > 0) && (value > (max_cap - value_to_add))) { \ + value = max_cap; \ + } \ + else if ((value_to_add < 0) && (value < (min_cap - value_to_add))) { \ + value = min_cap; \ + } \ + else { \ + value += value_to_add; \ + } + +sint8 add_clamp_sint8(sint8 value, sint8 value_to_add) +{ + add_clamp_body(value, value_to_add, INT8_MIN, INT8_MAX); + return value; +} + +sint16 add_clamp_sint16(sint16 value, sint16 value_to_add) +{ + add_clamp_body(value, value_to_add, INT16_MIN, INT16_MAX); + return value; +} + +sint32 add_clamp_sint32(sint32 value, sint32 value_to_add) +{ + add_clamp_body(value, value_to_add, INT32_MIN, INT32_MAX); + return value; +} + +money32 add_clamp_money32(money32 value, money32 value_to_add) +{ + // This function is intended only for clarity, as money32 + // is technically the same as sint32 + assert_struct_size(money32, sizeof(sint32)); + return add_clamp_sint32(value, value_to_add); +} + +#undef add_clamp_body diff --git a/src/openrct2/util/util.h b/src/openrct2/util/util.h index b0593a9237..388a0467bd 100644 --- a/src/openrct2/util/util.h +++ b/src/openrct2/util/util.h @@ -57,4 +57,9 @@ uint32 util_rand(); uint8 *util_zlib_deflate(const uint8 *data, size_t data_in_size, size_t *data_out_size); uint8 *util_zlib_inflate(uint8 *data, size_t data_in_size, size_t *data_out_size); +sint8 add_clamp_sint8(sint8 value, sint8 value_to_add); +sint16 add_clamp_sint16(sint16 value, sint16 value_to_add); +sint32 add_clamp_sint32(sint32 value, sint32 value_to_add); +money32 add_clamp_money32(money32 value, money32 value_to_add); + #endif diff --git a/src/openrct2/windows/cheats.c b/src/openrct2/windows/cheats.c index babb434b65..c28ea386e9 100644 --- a/src/openrct2/windows/cheats.c +++ b/src/openrct2/windows/cheats.c @@ -495,11 +495,11 @@ static void window_cheats_money_mousedown(sint32 widgetIndex, rct_window *w, rct { switch (widgetIndex) { case WIDX_MONEY_SPINNER_INCREMENT: - _moneySpinnerValue = min(INT_MAX, MONEY_INCREMENT_DIV * (_moneySpinnerValue / MONEY_INCREMENT_DIV + 1)); + _moneySpinnerValue = add_clamp_money32(MONEY_INCREMENT_DIV * (_moneySpinnerValue / MONEY_INCREMENT_DIV), MONEY_INCREMENT_DIV); widget_invalidate_by_class(WC_CHEATS, WIDX_MONEY_SPINNER); break; case WIDX_MONEY_SPINNER_DECREMENT: - _moneySpinnerValue = max(INT_MIN, MONEY_INCREMENT_DIV * (_moneySpinnerValue / MONEY_INCREMENT_DIV - 1)); + _moneySpinnerValue = add_clamp_money32(MONEY_INCREMENT_DIV * (_moneySpinnerValue / MONEY_INCREMENT_DIV), -MONEY_INCREMENT_DIV); widget_invalidate_by_class(WC_CHEATS, WIDX_MONEY_SPINNER); break; case WIDX_ADD_MONEY: diff --git a/src/openrct2/windows/server_list.c b/src/openrct2/windows/server_list.c index 2f6d6c3dc0..63e505797b 100644 --- a/src/openrct2/windows/server_list.c +++ b/src/openrct2/windows/server_list.c @@ -702,7 +702,7 @@ static void fetch_servers() sort_servers(); SDL_UnlockMutex(_mutex); - http_request_t request; + http_request_t request = { 0 }; request.url = masterServerUrl; request.method = HTTP_METHOD_GET; request.body = NULL; diff --git a/src/openrct2/world/map.c b/src/openrct2/world/map.c index 94c75163db..24be817085 100644 --- a/src/openrct2/world/map.c +++ b/src/openrct2/world/map.c @@ -1126,7 +1126,7 @@ void game_command_remove_banner(sint32* eax, sint32* ebx, sint32* ecx, sint32* e rct_banner *banner = &gBanners[map_element->properties.banner.index]; rct_scenery_entry *scenery_entry = get_banner_entry(banner->type); money32 refund = 0; - if (scenery_entry != NULL || scenery_entry != (rct_scenery_entry *)-1) { + if (scenery_entry != NULL && scenery_entry != (rct_scenery_entry *)-1) { refund = -((scenery_entry->banner.price * 3) / 4); }