From 08a5bea762d5f13edbc5bc87a1d6cce84bcd1d10 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sat, 11 Apr 2015 00:31:09 -0600 Subject: [PATCH 01/22] game_command_demolish_ride --- src/game.c | 4 +- src/management/finance.h | 2 +- src/ride/ride.c | 127 +++++++++++++++++++++++++++++++++++++++ src/ride/ride.h | 1 + 4 files changed, 131 insertions(+), 3 deletions(-) diff --git a/src/game.c b/src/game.c index 793e6d61f6..6ad9ba2780 100644 --- a/src/game.c +++ b/src/game.c @@ -881,7 +881,7 @@ static uint32 game_do_command_table[58] = { 0x006C5B69, 0, 0x006B3F0F, - 0x006B49D9, + 0, 0, 0x006B52D4, 0, // 10 @@ -944,7 +944,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_load_or_quit, game_command_emptysub, - game_command_emptysub, + game_command_demolish_ride, game_command_set_ride_status, game_command_emptysub, game_command_set_ride_name, // 10 diff --git a/src/management/finance.h b/src/management/finance.h index ffd8da01d5..547d4d513e 100644 --- a/src/management/finance.h +++ b/src/management/finance.h @@ -26,7 +26,7 @@ typedef int rct_expenditure_type; enum { - RCT_EXPENDITURE_TYPE_RIDE_CONSRUCTION, + RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION, RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS, RCT_EXPENDITURE_TYPE_LAND_PURCHASE, RCT_EXPENDITURE_TYPE_LANDSCAPING, diff --git a/src/ride/ride.c b/src/ride/ride.c index 97c0ef68d2..2b334d0a65 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -27,12 +27,14 @@ #include "../localisation/date.h" #include "../localisation/localisation.h" #include "../management/finance.h" +#include "../management/marketing.h" #include "../management/news_item.h" #include "../peep/peep.h" #include "../peep/staff.h" #include "../scenario.h" #include "../util/util.h" #include "../windows/error.h" +#include "../world/banner.h" #include "../world/map.h" #include "../world/sprite.h" #include "ride.h" @@ -3590,6 +3592,131 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi *ebx = 0; } +/** + * + * rct2: 0x006B49D9 + */ +void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + uint8 *bl = (uint8*)ebx; + uint8 ride_id = *(uint8*)edx; + + RCT2_GLOBAL(0x009DEA5E, uint16) = 0; + RCT2_GLOBAL(0x009DEA60, uint16) = 0; + RCT2_GLOBAL(0x009DEA62, uint16) = 0; + rct_ride *ride = &g_ride_list[ride_id]; + if(ride->overall_view != (uint16)-1){ + int x = (ride->overall_view & 0xFF) * 32 + 16; + int y = (ride->overall_view >> 8) * 32 + 16; + int z = map_element_height(x, y); + RCT2_GLOBAL(0x009DEA5E, uint16) = x; + RCT2_GLOBAL(0x009DEA60, uint16) = y; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + } + if(!(*bl & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8)){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; + }else{ + if(*bl & 1){ + if(!(*bl & 8)){ + window_close_by_number(WC_RIDE_CONSTRUCTION, ride_id); + } + window_close_by_number(WC_RIDE, ride_id); + window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, ride_id); + window_close_by_class(WC_NEW_CAMPAIGN); + if(RCT2_GLOBAL(0x01358103, uint8) && ride_id == RCT2_GLOBAL(0x01358117, uint8)){ + RCT2_GLOBAL(0x01358103, uint8) = 0; + } + if(RCT2_GLOBAL(0x01358107, uint8) && ride_id == RCT2_GLOBAL(0x0135811B, uint8)){ + RCT2_GLOBAL(0x01358107, uint8) = 0; + } + ride_clear_for_construction(ride_id); + ride_remove_peeps(ride_id); + RCT2_CALLPROC_X(0x00696707, 0, 0, 0, ride_id, 0, 0, 0); + RCT2_CALLPROC_X(0x006CB7FB, 0, 0, 0, ride_id, 0, 0, 0); // get ride refund price + *ebx = RCT2_GLOBAL(0x00F4413A, int); + RCT2_CALLPROC(0x006CB945); + news_item_disable_news(NEWS_ITEM_RIDE, ride_id); + + for(int i = 0; i < MAX_BANNERS; i++){ + rct_banner *banner = &gBanners[i]; + if(banner->type != BANNER_NULL && banner->flags & BANNER_FLAG_2 && banner->colour == ride_id){ + banner->flags &= 0xFB; + banner->string_idx = 778; + } + } + + uint16 spriteIndex; + rct_peep *peep; + FOR_ALL_GUESTS(spriteIndex, peep){ + uint8 ride_id_bit = ride_id & 0x3; + uint8 ride_id_offset = ride_id / 8; + peep->rides_been_on[ride_id_offset] &= ~(1 << ride_id_bit); // clear ride from potentially being in rides_been_on + if(peep->state == PEEP_STATE_WATCHING){ + if(peep->current_ride == ride_id){ + peep->current_ride = MAX_RIDES; + if(peep->time_to_stand >= 50){ // make peep stop watching the ride + peep->time_to_stand = 50; + } + } + } + // remove any free voucher for this ride from peep + if(peep->item_standard_flags & PEEP_ITEM_VOUCHER){ + if(peep->voucher_type == VOUCHER_TYPE_RIDE_FREE && peep->voucher_arguments == ride_id){ + peep->item_standard_flags &= ~(PEEP_ITEM_VOUCHER); + } + } + // remove any photos of this ride from peep + if(peep->item_standard_flags & PEEP_ITEM_PHOTO){ + if(peep->photo1_ride_ref == ride_id){ + peep->item_standard_flags &= ~PEEP_ITEM_PHOTO; + } + } + if(peep->item_extra_flags && PEEP_ITEM_PHOTO2){ + if(peep->photo2_ride_ref == ride_id){ + peep->item_extra_flags &= ~PEEP_ITEM_PHOTO2; + } + } + if(peep->item_extra_flags && PEEP_ITEM_PHOTO3){ + if(peep->photo3_ride_ref == ride_id){ + peep->item_extra_flags &= ~PEEP_ITEM_PHOTO3; + } + } + if(peep->item_extra_flags && PEEP_ITEM_PHOTO4){ + if(peep->photo4_ride_ref == ride_id){ + peep->item_extra_flags &= ~PEEP_ITEM_PHOTO4; + } + } + if(peep->guest_heading_to_ride_id == ride_id){ + peep->guest_heading_to_ride_id = MAX_RIDES; + } + if(peep->favourite_ride == ride_id){ + peep->favourite_ride = MAX_RIDES; + } + for (int i = 0; i < PEEP_MAX_THOUGHTS; i++) { + if(peep->thoughts[i].item == ride_id){ + // Clear top thought, push others up + memmove(&peep->thoughts[i], &peep->thoughts[i + 1], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1)); + peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE; + } + } + } + + user_string_free(ride->name); + ride->type = RIDE_TYPE_NULL; + window_invalidate_by_class(WC_RIDE_LIST); + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32) = calculate_park_value(); + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + return; + }else{ + *ebx = 0; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + return; + } + } +} + bool ride_type_has_flag(int rideType, int flag) { return (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (rideType * 8), uint32) & flag) != 0; diff --git a/src/ride/ride.h b/src/ride/ride.h index 9c85974e66..1a3b98959c 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -764,6 +764,7 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e void ride_set_name(int rideIndex, const char *name); void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); int get_var_10E_unk_1(rct_ride* ride); int get_var_10E_unk_2(rct_ride* ride); From 61485ed8981849ec5d58b193063ecf0ea04939b9 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sat, 11 Apr 2015 17:21:17 -0600 Subject: [PATCH 02/22] ride_get_refund_price --- src/ride/ride.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++--- src/ride/ride.h | 1 + 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/ride/ride.c b/src/ride/ride.c index 2b334d0a65..661e15b792 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -3592,6 +3592,77 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi *ebx = 0; } +/** + * + * rct2: 0x006CB7FB + */ +int ride_get_refund_price(int ride_id) +{ + uint8 oldpaused = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8); + RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = 0; + RCT2_GLOBAL(0x00F4413A, int) = 0; + for(int x = 0; x < 8192; x += 32){ + for(int y = 0; y < 8192; y += 32){ + int tile_idx = ((y * 256) + x) / 32; + rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + do{ + if((map_element->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK && map_element->properties.track.ride_index == ride_id){ + int eax, ebx, ecx, edx, esi, edi, ebp; + eax = x; + ebx = ((map_element->type & MAP_ELEMENT_DIRECTION_MASK) << 8) | 0x01; + ecx = y; + edx = map_element->properties.track.type; + edi = map_element->base_height * 8; + if(map_element->properties.track.type == 101){ + edx = 2 << 8 | map_element->properties.track.ride_index; + int oldeax = eax; + int oldebx = ebx; + int oldecx = ecx; + int oldedx = edx; + + ebx = oldebx; + ebx |= 0 << 0; + RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + ebx = oldebx; + ebx |= 1 << 8; + ecx = oldecx; + ecx += 16; + edx = oldedx; + RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + ebx = oldebx; + ebx |= 2 << 8; + eax = oldeax; + eax += 16; + ecx = oldecx; + ecx += 16; + edx = oldedx; + RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + ebx = oldebx; + ebx |= 3 << 8; + eax = oldeax; + eax += 16; + ecx = oldecx; + edx = oldedx; + RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_38, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + }else{ + edx |= 0xFF << 8; + edx &= ((map_element->properties.track.sequence & 0xF) << 8) | 0xFF; + RCT2_GLOBAL(0x00F4413A, int) += game_do_command_p(GAME_COMMAND_4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + } + y -= 32; + break; + } + map_element++; + }while(!((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE)); + } + } + RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = oldpaused; + return RCT2_GLOBAL(0x00F4413A, int); +} + /** * * rct2: 0x006B49D9 @@ -3605,10 +3676,11 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi RCT2_GLOBAL(0x009DEA60, uint16) = 0; RCT2_GLOBAL(0x009DEA62, uint16) = 0; rct_ride *ride = &g_ride_list[ride_id]; + int x = 0, y = 0, z = 0; if(ride->overall_view != (uint16)-1){ - int x = (ride->overall_view & 0xFF) * 32 + 16; - int y = (ride->overall_view >> 8) * 32 + 16; - int z = map_element_height(x, y); + x = ((ride->overall_view & 0xFF) * 32) + 16; + y = ((ride->overall_view >> 8) * 32) + 16; + z = map_element_height(x, y); RCT2_GLOBAL(0x009DEA5E, uint16) = x; RCT2_GLOBAL(0x009DEA60, uint16) = y; RCT2_GLOBAL(0x009DEA62, uint16) = z; @@ -3634,8 +3706,8 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi ride_clear_for_construction(ride_id); ride_remove_peeps(ride_id); RCT2_CALLPROC_X(0x00696707, 0, 0, 0, ride_id, 0, 0, 0); - RCT2_CALLPROC_X(0x006CB7FB, 0, 0, 0, ride_id, 0, 0, 0); // get ride refund price - *ebx = RCT2_GLOBAL(0x00F4413A, int); + *ebx = ride_get_refund_price(ride_id); + RCT2_CALLPROC(0x006CB945); news_item_disable_news(NEWS_ITEM_RIDE, ride_id); @@ -3707,6 +3779,9 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi ride->type = RIDE_TYPE_NULL; window_invalidate_by_class(WC_RIDE_LIST); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32) = calculate_park_value(); + RCT2_GLOBAL(0x009DEA5E, uint16) = x; + RCT2_GLOBAL(0x009DEA60, uint16) = y; + RCT2_GLOBAL(0x009DEA62, uint16) = z; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; return; }else{ diff --git a/src/ride/ride.h b/src/ride/ride.h index 1a3b98959c..f9d50b07aa 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -764,6 +764,7 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e void ride_set_name(int rideIndex, const char *name); void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +int ride_get_refund_price(int ride_id); void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); int get_var_10E_unk_1(rct_ride* ride); From ab9e250abedb199cb8dc5a1a04852e3b67aaaa3b Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sun, 12 Apr 2015 12:27:39 -0600 Subject: [PATCH 03/22] game_command_set_staff_order --- src/game.c | 6 +++--- src/peep/staff.c | 34 ++++++++++++++++++++++++++++++++++ src/peep/staff.h | 1 + 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/game.c b/src/game.c index 6ad9ba2780..5d67d5e56f 100644 --- a/src/game.c +++ b/src/game.c @@ -906,8 +906,8 @@ static uint32 game_do_command_table[58] = { 0, // use new_game_command_table, original: 0x006BEFA1, 29 0x006C09D1, // 30 0x006C0B83, - 0x006C0BB5, - 0x00669C6D, + 0, + 0, 0, 0x006649BD, 0x006666E7, @@ -969,7 +969,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_hire_new_staff_member, //game_command_emptysub, game_command_emptysub, // 30 game_command_emptysub, - game_command_emptysub, + game_command_set_staff_order, game_command_set_park_name, game_command_set_park_open, game_command_emptysub, diff --git a/src/peep/staff.c b/src/peep/staff.c index 7d6300d1f3..378672c353 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -211,6 +211,40 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, *edi = newPeep->sprite_index; } +/** + * + * rct2: 0x006C0BB5 + */ +void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40; + uint8 bl = *ebx; + uint8 order_id = *ebx >> 8; + uint16 sprite_id = *edx; + if(bl & 1){ + rct_peep *peep = &g_sprite_list[sprite_id].peep; + if(order_id & 0x80){ // change costume + uint8 sprite_type = order_id & ~0x80; + sprite_type += 4; + peep->sprite_type = sprite_type; + peep->flags &= ~PEEP_FLAGS_SLOW_WALK; + if(RCT2_ADDRESS(0x00982134, uint8)[sprite_type] & 1){ + peep->flags |= PEEP_FLAGS_SLOW_WALK; + } + peep->action_frame = 0; + sub_693B58(peep); + invalidate_sprite((rct_sprite*)peep); + window_invalidate_by_number(WC_PEEP, sprite_id); + window_invalidate_by_class(WC_STAFF_LIST); + }else{ + peep->staff_orders = order_id; + window_invalidate_by_number(WC_PEEP, sprite_id); + window_invalidate_by_class(WC_STAFF_LIST); + } + } + *ebx = 0; +} + /* * Updates the colour of the given staff type. */ diff --git a/src/peep/staff.h b/src/peep/staff.h index 18dff988dc..9eca6d33d9 100644 --- a/src/peep/staff.h +++ b/src/peep/staff.h @@ -51,6 +51,7 @@ enum STAFF_ORDERS{ void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void update_staff_colour(uint8 staffType, uint16 color); uint16 hire_new_staff_member(uint8 staffType); From 97bd30ece77e8959c8a8f0285bb8b3286168f001 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sun, 12 Apr 2015 14:12:06 -0600 Subject: [PATCH 04/22] game_command_set_staff_patrol --- src/game.c | 4 ++-- src/peep/staff.c | 41 +++++++++++++++++++++++++++++++++++++++-- src/peep/staff.h | 1 + src/ride/ride.c | 7 +++---- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/game.c b/src/game.c index 5d67d5e56f..bb366f4c7a 100644 --- a/src/game.c +++ b/src/game.c @@ -904,7 +904,7 @@ static uint32 game_do_command_table[58] = { 0x006E6878, 0x006C5AE9, 0, // use new_game_command_table, original: 0x006BEFA1, 29 - 0x006C09D1, // 30 + 0, // 30 0x006C0B83, 0, 0, @@ -967,7 +967,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_emptysub, game_command_hire_new_staff_member, //game_command_emptysub, - game_command_emptysub, // 30 + game_command_set_staff_patrol, // 30 game_command_emptysub, game_command_set_staff_order, game_command_set_park_name, diff --git a/src/peep/staff.c b/src/peep/staff.c index 378672c353..789bbfa8b9 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -218,10 +218,9 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40; - uint8 bl = *ebx; uint8 order_id = *ebx >> 8; uint16 sprite_id = *edx; - if(bl & 1){ + if(*ebx & GAME_COMMAND_FLAG_APPLY){ rct_peep *peep = &g_sprite_list[sprite_id].peep; if(order_id & 0x80){ // change costume uint8 sprite_type = order_id & ~0x80; @@ -245,6 +244,44 @@ void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *e *ebx = 0; } +/** + * + * rct2: 0x006C09D1 + */ +void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + int x = *eax; + int y = *ecx; + uint16 sprite_id = *edx; + rct_peep *peep = &g_sprite_list[sprite_id].peep; + int patrolOffset = peep->staff_id * (64 * 64 / 8); + int patrolIndex = ((x & 0x1F80) >> 7) | ((y & 0x1F80) >> 1); + int mask = 1 << (patrolIndex & 0x1F); + int base = patrolIndex >> 5; + + uint32 *patrolBits = (uint32*)(0x013B0E72 + patrolOffset + (base * 4)); + *patrolBits ^= mask; + + int eax2 = 0; + for(int i = 0; i < 128; i++){ + eax2 |= *(uint32*)(0x013B0E72 + patrolOffset + (i * 4)); + } + + RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2; + if(eax2){ + RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] |= 2; + } + + for(int y2 = 0; y2 < 4; y2++){ + for(int x2 = 0; x2 < 4; x2++){ + map_invalidate_tile_full((x & 0x1F80) + (x2 * 32), (y & 0x1F80) + (y2 * 32)); + } + } + } + *ebx = 0; +} + /* * Updates the colour of the given staff type. */ diff --git a/src/peep/staff.h b/src/peep/staff.h index 9eca6d33d9..87be022900 100644 --- a/src/peep/staff.h +++ b/src/peep/staff.h @@ -52,6 +52,7 @@ enum STAFF_ORDERS{ void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void update_staff_colour(uint8 staffType, uint16 color); uint16 hire_new_staff_member(uint8 staffType); diff --git a/src/ride/ride.c b/src/ride/ride.c index 661e15b792..21059f071b 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -3669,7 +3669,6 @@ int ride_get_refund_price(int ride_id) */ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { - uint8 *bl = (uint8*)ebx; uint8 ride_id = *(uint8*)edx; RCT2_GLOBAL(0x009DEA5E, uint16) = 0; @@ -3685,13 +3684,13 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi RCT2_GLOBAL(0x009DEA60, uint16) = y; RCT2_GLOBAL(0x009DEA62, uint16) = z; } - if(!(*bl & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8)){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8)){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; }else{ - if(*bl & 1){ - if(!(*bl & 8)){ + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + if(!(*ebx & 8)){ window_close_by_number(WC_RIDE_CONSTRUCTION, ride_id); } window_close_by_number(WC_RIDE, ride_id); From 623e607dfd8cd75aa3beadadf48d4a967eb01718 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sun, 12 Apr 2015 14:24:43 -0600 Subject: [PATCH 05/22] game_command_fire_staff_member --- src/game.c | 4 ++-- src/peep/peep.h | 1 + src/peep/staff.c | 17 +++++++++++++++++ src/peep/staff.h | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/game.c b/src/game.c index bb366f4c7a..c78eae6ba9 100644 --- a/src/game.c +++ b/src/game.c @@ -905,7 +905,7 @@ static uint32 game_do_command_table[58] = { 0x006C5AE9, 0, // use new_game_command_table, original: 0x006BEFA1, 29 0, // 30 - 0x006C0B83, + 0, 0, 0, 0, @@ -968,7 +968,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_hire_new_staff_member, //game_command_emptysub, game_command_set_staff_patrol, // 30 - game_command_emptysub, + game_command_fire_staff_member, game_command_set_staff_order, game_command_set_park_name, game_command_set_park_open, diff --git a/src/peep/peep.h b/src/peep/peep.h index 381e95ea95..315dd46bd6 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -570,6 +570,7 @@ int peep_check_easteregg_name(int index, rct_peep *peep); int peep_get_easteregg_name_id(rct_peep *peep); int peep_is_mechanic(rct_peep *peep); int peep_has_food(rct_peep* peep); +void peep_sprite_remove(rct_peep* peep); void peep_window_state_update(rct_peep* peep); void peep_decrement_num_riders(rct_peep* peep); diff --git a/src/peep/staff.c b/src/peep/staff.c index 789bbfa8b9..01c4e10838 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -282,6 +282,23 @@ void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int * *ebx = 0; } +/** + * + * rct2: 0x006C0B83 + */ +void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 40; + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + window_close_by_class(WC_FIRE_PROMPT); + uint16 sprite_id = *edx; + rct_peep *peep = &g_sprite_list[sprite_id].peep; + RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0); + peep_sprite_remove(peep); + } + *ebx = 0; +} + /* * Updates the colour of the given staff type. */ diff --git a/src/peep/staff.h b/src/peep/staff.h index 87be022900..9e2ea86876 100644 --- a/src/peep/staff.h +++ b/src/peep/staff.h @@ -53,6 +53,7 @@ void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, in void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void update_staff_colour(uint8 staffType, uint16 color); uint16 hire_new_staff_member(uint8 staffType); From 26ab7c7b7e2ee2e7f86e8f3832149149a19eb204 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sun, 12 Apr 2015 19:06:51 -0600 Subject: [PATCH 06/22] #1011 --- src/editor.c | 2 +- src/peep/peep.c | 2 +- src/peep/staff.c | 27 ++++++++++++++++----------- src/peep/staff.h | 2 +- src/windows/staff.c | 11 +++++------ 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/editor.c b/src/editor.c index 1c5bddf084..b51cd723f2 100644 --- a/src/editor.c +++ b/src/editor.c @@ -265,7 +265,7 @@ void sub_6BD3A4() for (int i = 200; i < 204; i++) RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[i] = STAFF_MODE_WALK; - sub_6C0C3F(); + staff_update_greyed_patrol_areas(); } /** diff --git a/src/peep/peep.c b/src/peep/peep.c index 26a63d7c32..68dc5b0901 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -573,7 +573,7 @@ void peep_sprite_remove(rct_peep* peep){ RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] = 0; peep->type = 0xFF; - sub_6C0C3F(); + staff_update_greyed_patrol_areas(); peep->type = PEEP_TYPE_STAFF; news_item_disable_news(NEWS_ITEM_PEEP, peep->sprite_index); diff --git a/src/peep/staff.c b/src/peep/staff.c index 01c4e10838..15f15c1fe7 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -263,13 +263,13 @@ void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int * uint32 *patrolBits = (uint32*)(0x013B0E72 + patrolOffset + (base * 4)); *patrolBits ^= mask; - int eax2 = 0; + int ispatrolling = 0; for(int i = 0; i < 128; i++){ - eax2 |= *(uint32*)(0x013B0E72 + patrolOffset + (i * 4)); + ispatrolling |= *(uint32*)(0x013B0E72 + patrolOffset + (i * 4)); } RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2; - if(eax2){ + if(ispatrolling){ RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] |= 2; } @@ -278,6 +278,7 @@ void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int * map_invalidate_tile_full((x & 0x1F80) + (x2 * 32), (y & 0x1F80) + (y2 * 32)); } } + staff_update_greyed_patrol_areas(); } *ebx = 0; } @@ -327,23 +328,27 @@ uint16 hire_new_staff_member(uint8 staffType) return edi; } -void sub_6C0C3F() +/** + * + * rct2: 0x006C0C3F + */ +void staff_update_greyed_patrol_areas() { - register rct_peep* peep; + rct_peep* peep; - for (register uint8 staff_type = 0; staff_type < STAFF_TYPE_COUNT; ++staff_type) + for (int staff_type = 0; staff_type < STAFF_TYPE_COUNT; ++staff_type) { - for (register uint8 i = 0; i < 128; ++i) - RCT2_ADDRESS(0x13B0E72 + (staff_type + STAFF_MAX_COUNT) * 512, uint32)[i] = 0; + for (int i = 0; i < 128; ++i) + RCT2_ADDRESS(0x13B0E72 + ((staff_type + STAFF_MAX_COUNT) * 512), uint32)[i] = 0; - for (register uint16 sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next) + for (uint16 sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next) { peep = GET_PEEP(sprite_index); if (peep->type == PEEP_TYPE_STAFF && staff_type == peep->staff_type) { - for (register uint8 i = 0; i < 128; ++i) - RCT2_ADDRESS(0x13B0E72 + (staff_type + STAFF_MAX_COUNT) * 512, uint32)[i] |= RCT2_ADDRESS(0x13B0E72 + peep->staff_id * 512, uint32)[i]; + for (int i = 0; i < 128; ++i) + RCT2_ADDRESS(0x13B0E72 + ((staff_type + STAFF_MAX_COUNT) * 512), uint32)[i] |= RCT2_ADDRESS(0x13B0E72 + (peep->staff_id * 512), uint32)[i]; } } diff --git a/src/peep/staff.h b/src/peep/staff.h index 9e2ea86876..51467efecc 100644 --- a/src/peep/staff.h +++ b/src/peep/staff.h @@ -57,7 +57,7 @@ void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int void update_staff_colour(uint8 staffType, uint16 color); uint16 hire_new_staff_member(uint8 staffType); -void sub_6C0C3F(); +void staff_update_greyed_patrol_areas(); int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y); void staff_reset_stats(); diff --git a/src/windows/staff.c b/src/windows/staff.c index 8dfb1e503a..5a14ff1deb 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -573,19 +573,18 @@ void window_staff_overview_dropdown() for (int i = 0; i < 128; i++) { - RCT2_GLOBAL(0x13B0E72 + ebx + i * 4, uint32) = 0; + RCT2_ADDRESS(0x13B0E72 + (peep->staff_id * 512), uint32)[i] = 0; } - RCT2_GLOBAL(RCT2_ADDRESS_STAFF_MODE_ARRAY + edi, uint16) &= 0xFD; // bug?? + RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] &= ~2; - window_invalidate(w); - //RCT2_CALLPROC_EBPSAFE(0x006C0C3F); - sub_6C0C3F(); + gfx_invalidate_screen(); + staff_update_greyed_patrol_areas(); } else { if (!tool_set(w, widgetIndex, 22)) { show_gridlines(); RCT2_GLOBAL(0x009DEA50, sint16) = w->number; - window_invalidate(w); + gfx_invalidate_screen(); } } } From b98585255bd80b1518bf0e321c5a5db3c7fa8934 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Mon, 13 Apr 2015 19:53:07 -0600 Subject: [PATCH 07/22] remove_peep_from_ride --- src/peep/peep.c | 17 ++++++++++++++++- src/peep/peep.h | 1 + src/peep/staff.c | 2 +- src/windows/guest.c | 2 +- src/windows/staff.c | 2 +- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/peep/peep.c b/src/peep/peep.c index 68dc5b0901..03ff279fba 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -175,6 +175,21 @@ static void sub_693BE5(rct_peep* peep, uint8 al){ sub_693B58(peep); } +/** +* +* rct2: 0x0069A512 +*/ +void remove_peep_from_ride(rct_peep* peep) +{ + if (peep->state == PEEP_STATE_QUEUING) { + remove_peep_from_queue(peep); + } + peep_decrement_num_riders(peep); + peep->state = PEEP_STATE_1; + peep_window_state_update(peep); + sub_693BE5(peep, 0); +} + static void peep_state_reset(rct_peep* peep){ peep_decrement_num_riders(peep); peep->state = PEEP_STATE_1; @@ -556,7 +571,7 @@ void peep_sprite_remove(rct_peep* peep){ //RCT2_CALLPROC_X(0x69A535, 0, 0, 0, 0, (int)peep, 0, 0); //return; - RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0); + remove_peep_from_ride(peep); invalidate_sprite((rct_sprite*)peep); window_close_by_number(WC_PEEP, peep->sprite_index); diff --git a/src/peep/peep.h b/src/peep/peep.h index 315dd46bd6..9dd9d26a89 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -584,6 +584,7 @@ void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_a void peep_set_map_tooltip(rct_peep *peep); void sub_693B58(rct_peep* peep); +void remove_peep_from_ride(rct_peep* peep); void remove_peep_from_queue(rct_peep* peep); #endif diff --git a/src/peep/staff.c b/src/peep/staff.c index 15f15c1fe7..25c9eaa181 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -294,7 +294,7 @@ void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int window_close_by_class(WC_FIRE_PROMPT); uint16 sprite_id = *edx; rct_peep *peep = &g_sprite_list[sprite_id].peep; - RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0); + remove_peep_from_ride(peep); peep_sprite_remove(peep); } *ebx = 0; diff --git a/src/windows/guest.c b/src/windows/guest.c index 37b971a367..4aff777c39 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -622,7 +622,7 @@ void window_guest_overview_mouse_up(){ w->var_48C = peep->x; - RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0); + remove_peep_from_ride(peep); invalidate_sprite((rct_sprite*)peep); sprite_move(0x8000, peep->y, peep->z, (rct_sprite*)peep); diff --git a/src/windows/staff.c b/src/windows/staff.c index 5a14ff1deb..67222c706b 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -457,7 +457,7 @@ void window_staff_overview_mouseup() w->var_48C = peep->x; - RCT2_CALLPROC_X(0x0069A512, 0, 0, 0, 0, (int)peep, 0, 0); + remove_peep_from_ride(peep); invalidate_sprite((rct_sprite*)peep); sprite_move( 0x8000, peep->y, peep->z, (rct_sprite*)peep); From af4653766750d3fefffa7d279604ba35ca9be630 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Tue, 14 Apr 2015 15:17:19 -0600 Subject: [PATCH 08/22] game_command_raise_land, game_command_lower_land --- src/game.c | 8 +-- src/world/map.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ src/world/map.h | 2 + 3 files changed, 165 insertions(+), 4 deletions(-) diff --git a/src/game.c b/src/game.c index c78eae6ba9..d8c47006ce 100644 --- a/src/game.c +++ b/src/game.c @@ -897,8 +897,8 @@ static uint32 game_do_command_table[58] = { 0, // use new_game_command_table, original: 0x00663CCD, // 20 0x006B53E9, 0x00698D6C, // text input - 0x0068C542, - 0x0068C6D1, + 0, + 0, 0x0068BC01, 0x006E66A0, 0x006E6878, @@ -960,8 +960,8 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_change_surface_style, // 20 game_command_emptysub, game_command_emptysub, - game_command_emptysub, - game_command_emptysub, + game_command_raise_land, + game_command_lower_land, game_command_emptysub, game_command_emptysub, game_command_emptysub, diff --git a/src/world/map.c b/src/world/map.c index 480c03ee52..8feb837318 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -19,6 +19,7 @@ *****************************************************************************/ #include "../addresses.h" +#include "../audio/audio.h" #include "../game.h" #include "../interface/window.h" #include "../localisation/date.h" @@ -890,6 +891,164 @@ void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, i ); } +/** + * + * rct2: 0x0068C542 + */ +void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int x = *eax; + int y = *ecx; + int z = map_element_height(*eax, *ecx); + int ax = (uint16)*edx; + int ay = (uint16)*ebp; + int bx = (uint16)(*edx >> 16); + int by = (uint16)(*ebp >> 16); + uint16 selection_type = *edi; + + int cost = 0x80000000; + + if(*ebx & GAME_COMMAND_FLAG_APPLY && RCT2_GLOBAL(0x009A8C28, uint8) == 1){ + sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); + } + + uint8 dh = 0xFF; + + // find lowest map element in selection + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; + rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + while(map_element->type & MAP_ELEMENT_TYPE_MASK){ + map_element++; + } + if(dh > map_element->base_height){ + dh = map_element->base_height; + } + } + } + + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; + rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + while(map_element->type & MAP_ELEMENT_TYPE_MASK){ + map_element++; + } + uint8 dl = map_element->base_height; + if(dl <= dh){ + uint8 dh = RCT2_ADDRESS(0x00981A1E, uint8)[(selection_type * 32) + (map_element->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK)]; // lookup table + if(dh & 0x20){ // needs to be raised, otherwise just the slope type changes + dl += 2; + dh &= ~0x20; + } + int ebx2 = *ebx; + int edx2 = (dh << 8) + dl; + int edi2 = selection_type * 32; + RCT2_CALLFUNC_X(0x0066397F, &xi, &ebx2, &yi, &edx2, (int*)&map_element, &edi2, ebp); // actually apply the change + if(ebx2 != 0x80000000){ + if(cost == 0x80000000){ + cost = ebx2; + }else{ + cost += ebx2; + } + } + } + } + } + RCT2_GLOBAL(0x141F56C, uint8) = 12; + RCT2_GLOBAL(0x009DEA5E, uint32) = x; + RCT2_GLOBAL(0x009DEA60, uint32) = y; + RCT2_GLOBAL(0x009DEA62, uint32) = z; + *ebx = cost; +} + +/** + * + * rct2: 0x0068C6D1 + */ +void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int x = *eax; + int y = *ecx; + int z = map_element_height(*eax, *ecx); + int ax = (uint16)*edx; + int ay = (uint16)*ebp; + int bx = (uint16)(*edx >> 16); + int by = (uint16)(*ebp >> 16); + uint16 selection_type = *edi; + + int cost = 0x80000000; + + if(*ebx & GAME_COMMAND_FLAG_APPLY && RCT2_GLOBAL(0x009A8C28, uint8) == 1){ + sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); + } + + uint8 dh = 0; + + // find highest map element in selection + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; + rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + while(map_element->type & MAP_ELEMENT_TYPE_MASK){ + map_element++; + } + uint8 dl = map_element->base_height; + if(map_element->properties.surface.slope & 0xF){ + dl += 2; + } + if(map_element->properties.surface.slope & 0x10){ + dl += 2; + } + if(dh < dl){ + dh = dl; + } + } + } + + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; + rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; + while(map_element->type & MAP_ELEMENT_TYPE_MASK){ + map_element++; + } + uint8 dl = map_element->base_height; + if(map_element->properties.surface.slope & 0xF){ + dl += 2; + } + if(map_element->properties.surface.slope & 0x10){ + dl += 2; + } + if(dl >= dh){ + dl = map_element->base_height; + uint8 dh = RCT2_ADDRESS(0x00981ABE, uint8)[(selection_type * 32) + (map_element->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK)]; // lookup table + if(dh & 0x20){ // needs to be lowered, otherwise just the slope type changes + dl -= 2; + dh &= ~0x20; + } + int ebx2 = *ebx; + int edx2 = (dh << 8) + dl; + int edi2 = selection_type * 32; + RCT2_CALLFUNC_X(0x0066397F, &xi, &ebx2, &yi, &edx2, (int*)&map_element, &edi2, ebp); // actually apply the change + if(ebx2 != 0x80000000){ + if(cost == 0x80000000){ + cost = ebx2; + }else{ + cost += ebx2; + } + } + } + } + } + RCT2_GLOBAL(0x141F56C, uint8) = 12; + RCT2_GLOBAL(0x009DEA5E, uint32) = x; + RCT2_GLOBAL(0x009DEA60, uint32) = y; + RCT2_GLOBAL(0x009DEA62, uint32) = z; + *ebx = cost; +} + /** * * rct2: 0x006EC6D7 diff --git a/src/world/map.h b/src/world/map.h index e8824796a9..762a33f232 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -275,6 +275,8 @@ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x])) #define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x]) From 9bd620cd99eaea9510f482f4eb55b150044317f1 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 15 Apr 2015 13:19:02 -0600 Subject: [PATCH 09/22] game_command_raise_water, game_command_lower_water, suggested changes --- src/audio/audio.c | 9 +- src/game.c | 8 +- src/world/map.c | 205 +++++++++++++++++++++++++++++++++++++--------- src/world/map.h | 2 + 4 files changed, 173 insertions(+), 51 deletions(-) diff --git a/src/audio/audio.c b/src/audio/audio.c index de5413da31..3703d8beec 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -1427,13 +1427,8 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z) RCT2_GLOBAL(0x00F438AD, uint8) = 0; int volume = 0; if (ebx == 0x8001) { - sint16 x2 = x & 0xFFE0; // round by 32 - sint16 y2 = y & 0xFFE0; - if (x2 < 0x1FFF && y2 < 0x1FFF) { - rct_map_element* mapelement = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[((y2 * 256 + x2) & 0xFFFF) / 8]; - while (map_element_get_type(mapelement) != MAP_ELEMENT_TYPE_SURFACE) { - mapelement++; - } + rct_map_element* mapelement = map_get_surface_element_at(x / 32, y / 32); + if (mapelement) { if ((mapelement->base_height * 8) - 5 > z) { RCT2_GLOBAL(0x00F438AD, uint8) = 10; } diff --git a/src/game.c b/src/game.c index d8c47006ce..702c01341e 100644 --- a/src/game.c +++ b/src/game.c @@ -900,8 +900,8 @@ static uint32 game_do_command_table[58] = { 0, 0, 0x0068BC01, - 0x006E66A0, - 0x006E6878, + 0, + 0, 0x006C5AE9, 0, // use new_game_command_table, original: 0x006BEFA1, 29 0, // 30 @@ -963,8 +963,8 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_raise_land, game_command_lower_land, game_command_emptysub, - game_command_emptysub, - game_command_emptysub, + game_command_raise_water, + game_command_lower_water, game_command_emptysub, game_command_hire_new_staff_member, //game_command_emptysub, game_command_set_staff_patrol, // 30 diff --git a/src/world/map.c b/src/world/map.c index 8feb837318..c0d1e95c7a 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -912,38 +912,30 @@ void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); } - uint8 dh = 0xFF; + uint8 min_height = 0xFF; // find lowest map element in selection for(int yi = ay; yi <= by; yi += 32){ for(int xi = ax; xi <= bx; xi += 32){ - int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; - rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; - while(map_element->type & MAP_ELEMENT_TYPE_MASK){ - map_element++; - } - if(dh > map_element->base_height){ - dh = map_element->base_height; + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + if(min_height > map_element->base_height){ + min_height = map_element->base_height; } } } for(int yi = ay; yi <= by; yi += 32){ for(int xi = ax; xi <= bx; xi += 32){ - int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; - rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; - while(map_element->type & MAP_ELEMENT_TYPE_MASK){ - map_element++; - } - uint8 dl = map_element->base_height; - if(dl <= dh){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + uint8 height = map_element->base_height; + if(height <= min_height){ uint8 dh = RCT2_ADDRESS(0x00981A1E, uint8)[(selection_type * 32) + (map_element->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK)]; // lookup table if(dh & 0x20){ // needs to be raised, otherwise just the slope type changes - dl += 2; + height += 2; dh &= ~0x20; } int ebx2 = *ebx; - int edx2 = (dh << 8) + dl; + int edx2 = (dh << 8) + height; int edi2 = selection_type * 32; RCT2_CALLFUNC_X(0x0066397F, &xi, &ebx2, &yi, &edx2, (int*)&map_element, &edi2, ebp); // actually apply the change if(ebx2 != 0x80000000){ @@ -984,52 +976,44 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); } - uint8 dh = 0; + uint8 max_height = 0; // find highest map element in selection for(int yi = ay; yi <= by; yi += 32){ for(int xi = ax; xi <= bx; xi += 32){ - int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; - rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; - while(map_element->type & MAP_ELEMENT_TYPE_MASK){ - map_element++; - } - uint8 dl = map_element->base_height; + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + uint8 base_height = map_element->base_height; if(map_element->properties.surface.slope & 0xF){ - dl += 2; + base_height += 2; } if(map_element->properties.surface.slope & 0x10){ - dl += 2; + base_height += 2; } - if(dh < dl){ - dh = dl; + if(max_height < base_height){ + max_height = base_height; } } } for(int yi = ay; yi <= by; yi += 32){ for(int xi = ax; xi <= bx; xi += 32){ - int tile_idx = (((yi & 0x1FE0) * 256) + (xi & 0x1FE0)) / 32; - rct_map_element* map_element = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx]; - while(map_element->type & MAP_ELEMENT_TYPE_MASK){ - map_element++; - } - uint8 dl = map_element->base_height; + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + uint8 height = map_element->base_height; if(map_element->properties.surface.slope & 0xF){ - dl += 2; + height += 2; } if(map_element->properties.surface.slope & 0x10){ - dl += 2; + height += 2; } - if(dl >= dh){ - dl = map_element->base_height; + if(height >= max_height){ + height = map_element->base_height; uint8 dh = RCT2_ADDRESS(0x00981ABE, uint8)[(selection_type * 32) + (map_element->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK)]; // lookup table if(dh & 0x20){ // needs to be lowered, otherwise just the slope type changes - dl -= 2; + height -= 2; dh &= ~0x20; } int ebx2 = *ebx; - int edx2 = (dh << 8) + dl; + int edx2 = (dh << 8) + height; int edi2 = selection_type * 32; RCT2_CALLFUNC_X(0x0066397F, &xi, &ebx2, &yi, &edx2, (int*)&map_element, &edi2, ebp); // actually apply the change if(ebx2 != 0x80000000){ @@ -1049,6 +1033,147 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i *ebx = cost; } +/** + * + * rct2: 0x006E66A0 + */ +void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int ax = (uint16)*eax; + int ay = (uint16)*ecx; + int bx = (uint16)*edi; + int by = (uint16)*ebp; + + int cost = 0; + + uint8 max_height = 0xFF; + + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + uint8 height = map_element->base_height; + if(map_element->properties.surface.terrain & 0x1F){ + height = (map_element->properties.surface.terrain & 0x1F) * 2; + } + if(max_height > height){ + max_height = height; + } + } + } + + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + if(map_element->base_height <= max_height){ + uint8 height = (map_element->properties.surface.terrain & 0x1F); + if(height){ + height *= 2; + if(height > max_height){ + continue; + } + height += 2; + }else{ + height = map_element->base_height + 2; + } + int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (max_height << 8) + height, esi2, edi2, ebp2; + ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); + if(ebx2 == 0x80000000){ + *ebx = 0x80000000; + return; + }else{ + cost += ebx2; + } + } + } + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + int x = ((ax + bx) / 2) + 16; + int y = ((ay + by) / 2) + 16; + int z = map_element_height(x, y); + sint16 water_height_z = z >> 16; + sint16 base_height_z = z; + z = water_height_z; + if(!z){ + z = base_height_z; + } + RCT2_GLOBAL(0x009DEA5E, uint32) = x; + RCT2_GLOBAL(0x009DEA60, uint32) = y; + RCT2_GLOBAL(0x009DEA62, uint32) = z; + sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); + } + *ebx = cost; +} + +/** + * + * rct2: 0x006E6878 + */ +void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int ax = (uint16)*eax; + int ay = (uint16)*ecx; + int bx = (uint16)*edi; + int by = (uint16)*ebp; + + int cost = 0; + + uint8 min_height = 0; + + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + uint8 height = map_element->properties.surface.terrain & 0x1F; + if(height){ + height *= 2; + if(height > min_height){ + min_height = height; + } + } + } + } + + for(int yi = ay; yi <= by; yi += 32){ + for(int xi = ax; xi <= bx; xi += 32){ + rct_map_element* map_element = map_get_surface_element_at(xi / 32, yi / 32); + + uint8 height = (map_element->properties.surface.terrain & 0x1F); + if(height){ + height *= 2; + if(height < min_height){ + continue; + } + height -= 2; + int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (min_height << 8) + height, esi2, edi2, ebp2; + ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); + if(ebx2 == 0x80000000){ + *ebx = 0x80000000; + return; + }else{ + cost += ebx2; + } + } + } + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + int x = ((ax + bx) / 2) + 16; + int y = ((ay + by) / 2) + 16; + int z = map_element_height(x, y); + sint16 water_height_z = z >> 16; + sint16 base_height_z = z; + z = water_height_z; + if(!z){ + z = base_height_z; + } + RCT2_GLOBAL(0x009DEA5E, uint32) = x; + RCT2_GLOBAL(0x009DEA60, uint32) = y; + RCT2_GLOBAL(0x009DEA62, uint32) = z; + sound_play_panned(SOUND_LAYING_OUT_WATER, 0x8001, x, y, z); + } + *ebx = cost; +} + /** * * rct2: 0x006EC6D7 diff --git a/src/world/map.h b/src/world/map.h index 762a33f232..da5ad34641 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -277,6 +277,8 @@ void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x])) #define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x]) From e2d386edbc1546c63cea83c03e9c2b4dde7a33e4 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 15 Apr 2015 17:17:43 -0600 Subject: [PATCH 10/22] game_command_remove_fence --- src/game.c | 4 +-- src/world/map.c | 76 +++++++++++++++++++++++++++++++++++++------------ src/world/map.h | 2 ++ 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/game.c b/src/game.c index 702c01341e..a7d0d69c87 100644 --- a/src/game.c +++ b/src/game.c @@ -916,7 +916,7 @@ static uint32 game_do_command_table[58] = { 0, 0, // 40 0x006E519A, - 0x006E5597, + 0, 0x006B893C, 0x006B8E1B, 0, @@ -979,7 +979,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_set_park_entrance_fee, game_command_update_staff_colour, // 40 game_command_emptysub, - game_command_emptysub, + game_command_remove_fence, game_command_emptysub, game_command_emptysub, game_command_set_current_loan, diff --git a/src/world/map.c b/src/world/map.c index c0d1e95c7a..0e8199e944 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -628,21 +628,6 @@ money32 map_try_clear_scenery(int x, int y, rct_map_element *mapElement, int fla return RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost; } -/** - * - * rct2: 0x006E5597 - */ -money32 sub_6E5597(int x, int y, int dl, int dh, int bl) -{ - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x * 32; - ecx = y * 32; - ebx = bl & 0xFF; - edx = ((dh & 0xFF) << 8) | (dl & 0xFF); - RCT2_CALLFUNC_X(0x006E5597, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return ebx; -} - money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -696,8 +681,15 @@ restart_from_beginning: goto restart_from_beginning; break; - case MAP_ELEMENT_TYPE_FENCE: - cost = sub_6E5597(x, y, mapElement->type & 3, mapElement->base_height, flags); + case MAP_ELEMENT_TYPE_FENCE:{ + int eax = x * 32; + int ebx = flags; + int ecx = y * 32; + int edx = (mapElement->base_height << 8) | (mapElement->type & MAP_ELEMENT_DIRECTION_MASK); + int esi, edi, ebp; + game_command_remove_fence(&eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + cost = ebx; + if (cost == MONEY32_UNDEFINED) return MONEY32_UNDEFINED; @@ -705,7 +697,7 @@ restart_from_beginning: if (flags & 1) goto restart_from_beginning; - break; + }break; } } while (!map_element_is_last_for_tile(mapElement++)); @@ -1174,6 +1166,54 @@ void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, *ebx = cost; } +/** + * + * rct2: 0x006E5597 + */ +void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int x = *eax; + int y = *ecx; + uint8 base_height = (*edx >> 8); + uint8 direction = *edx; + + RCT2_GLOBAL(0x141F56C, uint8) = 12; + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = 0x80000000; + return; + } + if((*ebx & 0x40) || !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_owned(x, y, base_height * 8)){ + *ebx = 0x80000000; + return; + } + rct_map_element* map_element = map_get_surface_element_at(x / 32, y / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_FENCE || + map_element->base_height != base_height || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != direction || + ((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5))){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + rct_object_entry_extended* object_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_object_entry_extended*)[map_element->properties.fence.slope]; + if((uint8)object_entry->checksum != 0xFF){ + rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; + if(banner->type != BANNER_NULL){ + window_close_by_number(WC_BANNER, map_element->properties.fence.item[0]); + banner->type = BANNER_NULL; + user_string_free(banner->string_idx); + } + } + map_invalidate_tile(x, y, map_element->base_height * 8, (map_element->base_height * 8) + 72); + map_element_remove(map_element); + } + *ebx = 0; +} + /** * * rct2: 0x006EC6D7 diff --git a/src/world/map.h b/src/world/map.h index da5ad34641..88b639ff8a 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -129,6 +129,7 @@ enum { }; enum { + MAP_ELEMENT_FLAG_5 = (1 << 4), MAP_ELEMENT_FLAG_BROKEN = (1 << 5), MAP_ELEMENT_FLAG_LAST_TILE = (1 << 7) }; @@ -279,6 +280,7 @@ void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x])) #define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x]) From 68d7f840988960b3f75e935fdfffae67e02620b2 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 15 Apr 2015 17:30:18 -0600 Subject: [PATCH 11/22] rename 0x80000000 to MONEY32_UNDEFINED --- src/game.c | 10 +++++----- src/peep/staff.c | 8 ++++---- src/ride/ride.c | 10 +++++----- src/ride/track.c | 4 ++-- src/scenario.c | 4 ++-- src/windows/clear_scenery.c | 4 ++-- src/windows/finances.c | 6 +++--- src/windows/ride_construction.c | 6 +++--- src/windows/scenery.c | 8 ++++---- src/windows/top_toolbar.c | 18 +++++++++--------- src/world/map.c | 24 ++++++++++++------------ 11 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/game.c b/src/game.c index a7d0d69c87..2c3073d104 100644 --- a/src/game.c +++ b/src/game.c @@ -358,7 +358,7 @@ static int game_check_affordability(int cost) } RCT2_GLOBAL(0x13CE952, uint32) = cost; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 827; - return 0x80000000; + return MONEY32_UNDEFINED; } static uint32 game_do_command_table[58]; @@ -411,13 +411,13 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * } cost = *ebx; - if (cost != 0x80000000) { + if (cost != MONEY32_UNDEFINED) { // Check funds insufficientFunds = 0; if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & 4) && !(flags & 0x20) && cost != 0) insufficientFunds = game_check_affordability(cost); - if (insufficientFunds != 0x80000000) { + if (insufficientFunds != MONEY32_UNDEFINED) { *ebx = original_ebx; *edx = original_edx; *esi = original_esi; @@ -438,7 +438,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * } *edx = *ebx; - if (*edx != 0x80000000 && *edx < cost) + if (*edx != MONEY32_UNDEFINED && *edx < cost) cost = *edx; // Decrement nest count @@ -470,7 +470,7 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * if (RCT2_GLOBAL(0x009A8C28, uint8) == 0 && (flags & 1) && RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8) && !(flags & 8)) window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16)); - return 0x80000000; + return MONEY32_UNDEFINED; } void pause_toggle() diff --git a/src/peep/staff.c b/src/peep/staff.c index 25c9eaa181..16fe6f79b2 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -70,7 +70,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, RCT2_GLOBAL(0x009DEA62, uint16) = _dx; if (RCT2_GLOBAL(0x13573C8, uint16) < 0x190) { - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_PEOPLE_IN_GAME; return; } @@ -82,7 +82,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, } if (i == STAFF_MAX_COUNT) { - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_STAFF_IN_GAME; return; } @@ -96,7 +96,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, if (newPeep == NULL) { - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TOO_MANY_PEOPLE_IN_GAME; return; } @@ -322,7 +322,7 @@ uint16 hire_new_staff_member(uint8 staffType) int result = game_do_command_p(GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - if (result == 0x80000000) + if (result == MONEY32_UNDEFINED) return 0xFFFF; return edi; diff --git a/src/ride/ride.c b/src/ride/ride.c index 21059f071b..a5b6147d55 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -558,7 +558,7 @@ int ride_create_ride(ride_list_item listItem) esi = GAME_COMMAND_6; game_do_command_p(esi, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return ebx == 0x80000000 ? -1 : edi; + return ebx == MONEY32_UNDEFINED ? -1 : edi; } /** @@ -2783,13 +2783,13 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int * if (setting == 0){ if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN){ RCT2_GLOBAL(0x141E9AC, uint16) = 1796; - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; return; } if (ride->status != RIDE_STATUS_CLOSED){ RCT2_GLOBAL(0x141E9AC, uint16) = 1006; - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; return; } } @@ -2798,7 +2798,7 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int * if (setting == 0 || setting == 4 || setting == 8 || setting == 9) { RCT2_GLOBAL(0x141E9AC, uint16) = 1797; - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; return; } } @@ -2807,7 +2807,7 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int * ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT && new_value > 1){ RCT2_GLOBAL(0x141E9AC, uint16) = 3141; - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; return; } diff --git a/src/ride/track.c b/src/ride/track.c index 27c128ef40..d9d4f2f96e 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -784,7 +784,7 @@ int sub_6D2189(int* cost, uint8* ride_id){ edx = track_design->type | (entry_index << 8); esi = GAME_COMMAND_6; - if (0x80000000 == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1; + if (MONEY32_UNDEFINED == game_do_command_p(GAME_COMMAND_6, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp)) return 1; // bh *ride_id = edi & 0xFF; @@ -840,7 +840,7 @@ int sub_6D2189(int* cost, uint8* ride_id){ edi = sub_6D01B3((*ride_id << 8) | bl, map_size, map_size, z); RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = backup_park_flags; - if (edi != 0x80000000){ + if (edi != MONEY32_UNDEFINED){ if (!find_object_in_entry_group(&track_design->vehicle_object, &entry_type, &entry_index)){ RCT2_GLOBAL(0xF44151, uint8) |= 4; diff --git a/src/scenario.c b/src/scenario.c index 44c9ab020e..836002e88e 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -314,7 +314,7 @@ int scenario_load_and_play_from_path(const char *path) RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, money32) = 0; RCT2_GLOBAL(0x01358334, money32) = 0; RCT2_GLOBAL(0x01358338, uint16) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = 0x80000000; + RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, uint32) = 0; RCT2_GLOBAL(0x013587D8, uint16) = 63; @@ -517,7 +517,7 @@ void scenario_objectives_check() park_value = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32); - if ( scenario_completed_company_value != 0x80000000) + if ( scenario_completed_company_value != MONEY32_UNDEFINED) return; switch (objective_type) { diff --git a/src/windows/clear_scenery.c b/src/windows/clear_scenery.c index 9c5b514f56..3a93c30365 100644 --- a/src/windows/clear_scenery.c +++ b/src/windows/clear_scenery.c @@ -103,7 +103,7 @@ void window_clear_scenery_open() window_init_scroll_widgets(window); window_push_others_below(window); - RCT2_GLOBAL(0x00F1AD62, uint32) = 0x80000000; + RCT2_GLOBAL(0x00F1AD62, uint32) = MONEY32_UNDEFINED; window->colours[0] = 24; window->colours[1] = 24; window->colours[2] = 24; @@ -209,7 +209,7 @@ static void window_clear_scenery_paint() // Draw cost amount x = (window_clear_scenery_widgets[WIDX_PREVIEW].left + window_clear_scenery_widgets[WIDX_PREVIEW].right) / 2 + w->x; y = window_clear_scenery_widgets[WIDX_PREVIEW].bottom + w->y + 5; - if (RCT2_GLOBAL(0x00F1AD62, uint32) != 0x80000000 && RCT2_GLOBAL(0x00F1AD62, uint32) != 0) + if (RCT2_GLOBAL(0x00F1AD62, uint32) != MONEY32_UNDEFINED && RCT2_GLOBAL(0x00F1AD62, uint32) != 0) gfx_draw_string_centred(dpi, 986, x, y, 0, (void*)0x00F1AD62); } diff --git a/src/windows/finances.c b/src/windows/finances.c index ec42a904f5..5ba64652ef 100644 --- a/src/windows/finances.c +++ b/src/windows/finances.c @@ -865,7 +865,7 @@ static void window_finances_financial_graph_paint() money32 *balanceHistory = RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32); for (i = 0; i < 64; i++) { money32 balance = balanceHistory[i]; - if (balance == 0x80000000) + if (balance == MONEY32_UNDEFINED) continue; // Modifier balance then keep halfing until less than 127 pixels @@ -983,7 +983,7 @@ static void window_finances_park_value_graph_paint() money32 *parkValueHistory = RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32); for (i = 0; i < 64; i++) { money32 balance = parkValueHistory[i]; - if (balance == 0x80000000) + if (balance == MONEY32_UNDEFINED) continue; // Modifier balance then keep halfing until less than 255 pixels @@ -1101,7 +1101,7 @@ static void window_finances_profit_graph_paint() money32 *weeklyProfitHistory = RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32); for (i = 0; i < 64; i++) { money32 balance = weeklyProfitHistory[i]; - if (balance == 0x80000000) + if (balance == MONEY32_UNDEFINED) continue; // Modifier balance then keep halfing until less than 127 pixels diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c index 33c1ee1b02..4486c5a9a5 100644 --- a/src/windows/ride_construction.c +++ b/src/windows/ride_construction.c @@ -169,7 +169,7 @@ rct_window *window_construction_open() window_push_others_right(w); show_gridlines(); - RCT2_GLOBAL(0xF44070, uint32) = 0x80000000; + RCT2_GLOBAL(0xF44070, uint32) = MONEY32_UNDEFINED; RCT2_GLOBAL(0xF440CD, uint8) = 8; RCT2_GLOBAL(0xF440CE, uint8) = 18; RCT2_GLOBAL(0xF440CF, uint8) = 4; @@ -307,7 +307,7 @@ void window_construction_mouseup_demolish(rct_window* w){ RCT2_CALLPROC_X(0x6C9BA5, 0, 0, 0, 0, (int)w, 0, 0); return; - RCT2_GLOBAL(0xF44070, uint32) = 0x80000000; + RCT2_GLOBAL(0xF44070, uint32) = MONEY32_UNDEFINED; sub_6C9627(); RCT2_GLOBAL(0xF440B8, uint8) = 3; @@ -440,7 +440,7 @@ void window_construction_paint() short string_y = RCT2_GLOBAL(0x9D7C08, int16_t) + w->y - 23; if (RCT2_GLOBAL(0xF440A6, uint8_t) != 4) gfx_draw_string_centred(dpi, 1407, string_x, string_y, 0, w); string_y += 11; - if (RCT2_GLOBAL(0xF44070, uint32_t) != 0x80000000 && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800)) + if (RCT2_GLOBAL(0xF44070, uint32_t) != MONEY32_UNDEFINED && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32_t) & 0x800)) gfx_draw_string_centred(dpi, 1408, string_x, string_y, 0, (void*)0xF44070); } diff --git a/src/windows/scenery.c b/src/windows/scenery.c index 228e94b200..06b9e9e984 100644 --- a/src/windows/scenery.c +++ b/src/windows/scenery.c @@ -464,7 +464,7 @@ void window_scenery_open() window->scenery.hover_counter = 0; window_push_others_below(window); RCT2_GLOBAL(0x00F64F0D, uint8) = 0; - RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000; + RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F64EC0, uint16) = 0; window_scenery_is_repaint_scenery_tool_on = 0; // repaint colored scenery tool state window_scenery_is_build_cluster_tool_on = 0; // build cluster tool state @@ -643,7 +643,7 @@ static void window_scenery_mousedown(int widgetIndex, rct_window* w, rct_widget* if (widgetIndex >= WIDX_SCENERY_TAB_1 && widgetIndex <= WIDX_SCENERY_TAB_20) { window_scenery_active_tab_index = widgetIndex - WIDX_SCENERY_TAB_1; window_invalidate(w); - RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000; + RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED; window_scenery_update_scroll(w); } } @@ -817,7 +817,7 @@ void window_scenery_scrollmousedown() window_scenery_is_repaint_scenery_tool_on &= 0xFE; sound_play_panned(4, (w->width >> 1) + w->x, 0, 0, 0); w->scenery.hover_counter = -16; - RCT2_GLOBAL(0x00F64EB4, uint32) = 0x80000000; + RCT2_GLOBAL(0x00F64EB4, uint32) = MONEY32_UNDEFINED; window_invalidate(w); } @@ -1057,7 +1057,7 @@ void window_scenery_paint() price = sceneryEntry->small_scenery.price * 10; } - if (w->scenery.selected_scenery_id == -1 && RCT2_GLOBAL(0x00F64EB4, uint32) != 0x80000000) { + if (w->scenery.selected_scenery_id == -1 && RCT2_GLOBAL(0x00F64EB4, uint32) != MONEY32_UNDEFINED) { price = RCT2_GLOBAL(0x00F64EB4, uint32); } diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index bf726d96f0..90af8a665f 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1420,7 +1420,7 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w cost = game_do_command_p(GAME_COMMAND_50, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); } - if (cost == MONEY32_UNDEFINED)return; + if (ebx == MONEY32_UNDEFINED)return; sound_play_panned(SOUND_PLACE_ITEM, 0x8001, RCT2_GLOBAL(0x009DEA5E, uint16), RCT2_GLOBAL(0x009DEA60, uint16), RCT2_GLOBAL(0x009DEA62, uint16)); @@ -1609,8 +1609,8 @@ void window_top_toolbar_land_tool_drag(short x, short y) selection_raise_land(GAME_COMMAND_FLAG_APPLY); - RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = 0x80000000; - RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = 0x80000000; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = MONEY32_UNDEFINED; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = MONEY32_UNDEFINED; return; } @@ -1619,8 +1619,8 @@ void window_top_toolbar_land_tool_drag(short x, short y) selection_lower_land(GAME_COMMAND_FLAG_APPLY); - RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = 0x80000000; - RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = 0x80000000; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = MONEY32_UNDEFINED; + RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = MONEY32_UNDEFINED; return; } @@ -1666,8 +1666,8 @@ void window_top_toolbar_water_tool_drag(short x, short y) RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16), RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) ); - RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = 0x80000000; - RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = 0x80000000; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = MONEY32_UNDEFINED; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = MONEY32_UNDEFINED; return; } @@ -1688,8 +1688,8 @@ void window_top_toolbar_water_tool_drag(short x, short y) RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16), RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) ); - RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = 0x80000000; - RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = 0x80000000; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_RAISE_COST, uint32) = MONEY32_UNDEFINED; + RCT2_GLOBAL(RCT2_ADDRESS_WATER_LOWER_COST, uint32) = MONEY32_UNDEFINED; return; } diff --git a/src/world/map.c b/src/world/map.c index 0e8199e944..5d20144156 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -898,7 +898,7 @@ void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i int by = (uint16)(*ebp >> 16); uint16 selection_type = *edi; - int cost = 0x80000000; + int cost = MONEY32_UNDEFINED; if(*ebx & GAME_COMMAND_FLAG_APPLY && RCT2_GLOBAL(0x009A8C28, uint8) == 1){ sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); @@ -930,8 +930,8 @@ void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i int edx2 = (dh << 8) + height; int edi2 = selection_type * 32; RCT2_CALLFUNC_X(0x0066397F, &xi, &ebx2, &yi, &edx2, (int*)&map_element, &edi2, ebp); // actually apply the change - if(ebx2 != 0x80000000){ - if(cost == 0x80000000){ + if(ebx2 != MONEY32_UNDEFINED){ + if(cost == MONEY32_UNDEFINED){ cost = ebx2; }else{ cost += ebx2; @@ -962,7 +962,7 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i int by = (uint16)(*ebp >> 16); uint16 selection_type = *edi; - int cost = 0x80000000; + int cost = MONEY32_UNDEFINED; if(*ebx & GAME_COMMAND_FLAG_APPLY && RCT2_GLOBAL(0x009A8C28, uint8) == 1){ sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); @@ -1008,8 +1008,8 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i int edx2 = (dh << 8) + height; int edi2 = selection_type * 32; RCT2_CALLFUNC_X(0x0066397F, &xi, &ebx2, &yi, &edx2, (int*)&map_element, &edi2, ebp); // actually apply the change - if(ebx2 != 0x80000000){ - if(cost == 0x80000000){ + if(ebx2 != MONEY32_UNDEFINED){ + if(cost == MONEY32_UNDEFINED){ cost = ebx2; }else{ cost += ebx2; @@ -1070,8 +1070,8 @@ void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, } int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (max_height << 8) + height, esi2, edi2, ebp2; ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); - if(ebx2 == 0x80000000){ - *ebx = 0x80000000; + if(ebx2 == MONEY32_UNDEFINED){ + *ebx = MONEY32_UNDEFINED; return; }else{ cost += ebx2; @@ -1139,8 +1139,8 @@ void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, height -= 2; int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (min_height << 8) + height, esi2, edi2, ebp2; ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); - if(ebx2 == 0x80000000){ - *ebx = 0x80000000; + if(ebx2 == MONEY32_UNDEFINED){ + *ebx = MONEY32_UNDEFINED; return; }else{ cost += ebx2; @@ -1180,12 +1180,12 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, RCT2_GLOBAL(0x141F56C, uint8) = 12; if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; return; } if((*ebx & 0x40) || !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ if(!map_is_location_owned(x, y, base_height * 8)){ - *ebx = 0x80000000; + *ebx = MONEY32_UNDEFINED; return; } rct_map_element* map_element = map_get_surface_element_at(x / 32, y / 32); From 16cb732533d8dd2782a2ad06836828c53867958a Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 15 Apr 2015 20:02:47 -0600 Subject: [PATCH 12/22] game_command_remove_scenery --- src/game.c | 4 +- src/world/map.c | 120 ++++++++++++++++++++++++++++-------------------- src/world/map.h | 1 + 3 files changed, 72 insertions(+), 53 deletions(-) diff --git a/src/game.c b/src/game.c index 2c3073d104..75b23f1cf8 100644 --- a/src/game.c +++ b/src/game.c @@ -888,7 +888,7 @@ static uint32 game_do_command_table[58] = { 0, 0x006660A8, 0x0066640B, - 0x006E0E01, + 0, 0x006E08F4, 0x006E650F, 0, @@ -951,7 +951,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_set_ride_setting, game_command_emptysub, game_command_emptysub, - game_command_emptysub, + game_command_remove_scenery, game_command_emptysub, game_command_emptysub, game_command_place_footpath, diff --git a/src/world/map.c b/src/world/map.c index 5d20144156..088d625ff4 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -581,51 +581,64 @@ void map_invalidate_tile(int x, int y, int zLow, int zHigh) * * rct2: 0x006E0E01 */ -money32 map_try_clear_scenery(int x, int y, rct_map_element *mapElement, int flags) +void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + int x = *eax; + int y = *ecx; + uint8 base_height = *edx; + uint8 scenery_type = *edx >> 8; + uint8 map_element_type = *ebx >> 8; money32 cost; - rct_scenery_entry *entry; - - entry = g_smallSceneryEntries[mapElement->properties.scenery.type]; + + rct_scenery_entry *entry = g_smallSceneryEntries[scenery_type]; cost = entry->small_scenery.removal_price * 10; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(0x009DEA5E, uint32) = x * 32 + 16; - RCT2_GLOBAL(0x009DEA60, uint32) = y * 32 + 16; - RCT2_GLOBAL(0x009DEA62, uint32) = mapElement->base_height * 8; + RCT2_GLOBAL(0x009DEA5E, uint32) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint32) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint32) = base_height * 8; - x *= 32; - y *= 32; - - if (!(flags & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + if (!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - return MONEY32_UNDEFINED; + *ebx = MONEY32_UNDEFINED; + return; } - if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !(flags & 0x40)) { + if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !(*ebx & 0x40)) { // Check if allowed to remove item if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) { if (entry->small_scenery.height > 64) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY; - return MONEY32_UNDEFINED; + *ebx = MONEY32_UNDEFINED; + return; } } // Check if the land is owned - if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)) - if (!map_is_location_owned(x, y, RCT2_GLOBAL(0x009DEA62, uint32))) - return MONEY32_UNDEFINED; + if (!map_is_location_owned(x, y, RCT2_GLOBAL(0x009DEA62, uint32))){ + *ebx = MONEY32_UNDEFINED; + return; + } } - if ((flags & 0x40) && !(mapElement->flags & 0x10)) - return 0; + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element->type != map_element_type || + map_element->base_height != base_height || + map_element->properties.scenery.type != scenery_type || + (*ebx & 0x40) && !(map_element->flags & 0x10)){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } // Remove element - if (flags & 1) { + if (*ebx & GAME_COMMAND_FLAG_APPLY) { map_invalidate_tile_full(x, y); - map_element_remove(mapElement); + map_element_remove(map_element); } - return RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost; + *ebx = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost); } money32 sub_6A67C0(int x, int y, int z, int flags) @@ -671,8 +684,15 @@ restart_from_beginning: goto restart_from_beginning; #endif break; - case MAP_ELEMENT_TYPE_SCENERY: - cost = map_try_clear_scenery(x, y, mapElement, flags); + case MAP_ELEMENT_TYPE_SCENERY:{ + int eax = x * 32; + int ebx = (mapElement->type << 8) | flags; + int ecx = y * 32; + int edx = (mapElement->properties.scenery.type << 8) | (mapElement->base_height); + int esi, edi, ebp; + game_command_remove_scenery(&eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + cost = ebx; + if (cost == MONEY32_UNDEFINED) return MONEY32_UNDEFINED; @@ -680,7 +700,7 @@ restart_from_beginning: if (flags & 1) goto restart_from_beginning; - break; + }break; case MAP_ELEMENT_TYPE_FENCE:{ int eax = x * 32; int ebx = flags; @@ -1178,39 +1198,37 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, uint8 direction = *edx; RCT2_GLOBAL(0x141F56C, uint8) = 12; - if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; } - if((*ebx & 0x40) || !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ - if(!map_is_location_owned(x, y, base_height * 8)){ - *ebx = MONEY32_UNDEFINED; + if(!(*ebx & 0x40) && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !map_is_location_owned(x, y, base_height * 8)){ + *ebx = MONEY32_UNDEFINED; + return; + } + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_FENCE || + map_element->base_height != base_height || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != direction || + ((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5))){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; return; } - rct_map_element* map_element = map_get_surface_element_at(x / 32, y / 32); - while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_FENCE || - map_element->base_height != base_height || - (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != direction || - ((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5))){ - map_element++; - if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ - *ebx = 0; - return; - } - } - rct_object_entry_extended* object_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_object_entry_extended*)[map_element->properties.fence.slope]; - if((uint8)object_entry->checksum != 0xFF){ - rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; - if(banner->type != BANNER_NULL){ - window_close_by_number(WC_BANNER, map_element->properties.fence.item[0]); - banner->type = BANNER_NULL; - user_string_free(banner->string_idx); - } - } - map_invalidate_tile(x, y, map_element->base_height * 8, (map_element->base_height * 8) + 72); - map_element_remove(map_element); } + rct_object_entry_extended* object_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_object_entry_extended*)[map_element->properties.fence.slope]; + if((uint8)object_entry->checksum != 0xFF){ + rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; + if(banner->type != BANNER_NULL){ + window_close_by_number(WC_BANNER, map_element->properties.fence.item[0]); + banner->type = BANNER_NULL; + user_string_free(banner->string_idx); + } + } + map_invalidate_tile(x, y, map_element->base_height * 8, (map_element->base_height * 8) + 72); + map_element_remove(map_element); *ebx = 0; } diff --git a/src/world/map.h b/src/world/map.h index 88b639ff8a..dc91f3046e 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -274,6 +274,7 @@ rct_map_element *map_element_insert(int x, int y, int z, int flags); int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl); int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); +void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); From ea75926a6cf830b1106546a5bddef16cee46e4bb Mon Sep 17 00:00:00 2001 From: zsilencer Date: Thu, 16 Apr 2015 10:47:05 -0600 Subject: [PATCH 13/22] game_command_set_ride_appearance --- src/game.c | 6 ++--- src/game.h | 2 +- src/ride/ride.c | 57 ++++++++++++++++++++++++++++++++++++++++++ src/ride/ride.h | 1 + src/windows/loadsave.c | 2 +- src/windows/ride.c | 18 ++++++------- 6 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/game.c b/src/game.c index 75b23f1cf8..984294fb10 100644 --- a/src/game.c +++ b/src/game.c @@ -797,7 +797,7 @@ char save_game() path_set_extension(path, ".SV6"); if (scenario_save(path, gConfigGeneral.save_plugin_data ? 1 : 0)) { - game_do_command(0, 1047, 0, -1, GAME_COMMAND_0, 0, 0); + game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); gfx_invalidate_screen(); return 1; } else { @@ -874,7 +874,7 @@ void game_load_or_quit_no_save_prompt() #pragma region Game command function table static uint32 game_do_command_table[58] = { - 0x006B2FC5, + 0, 0x0066397F, 0, 0x006C511D, @@ -937,7 +937,7 @@ static uint32 game_do_command_table[58] = { void game_command_emptysub(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) {} static GAME_COMMAND_POINTER* new_game_command_table[58] = { - game_command_emptysub, + game_command_set_ride_appearance, game_command_emptysub, game_pause_toggle, game_command_emptysub, diff --git a/src/game.h b/src/game.h index 410b596d04..7e7e509106 100644 --- a/src/game.h +++ b/src/game.h @@ -24,7 +24,7 @@ #include "common.h" enum GAME_COMMAND { - GAME_COMMAND_0, + GAME_COMMAND_SET_RIDE_APPEARANCE, GAME_COMMAND_1, GAME_COMMAND_TOGGLE_PAUSE, // 2 GAME_COMMAND_3, //Has something to do with ride construction diff --git a/src/ride/ride.c b/src/ride/ride.c index a5b6147d55..9297e89837 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -3791,6 +3791,63 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi } } +/** + * + * rct2: 0x006B2FC5 + */ +void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + uint8 ride_id = *edx; + uint8 type = *ebx >> 8; + uint8 value = *edx >> 8; + int index = *edi; + rct_ride *ride = &g_ride_list[ride_id]; + switch(type){ + case 0: + ride->track_colour_main[index] = value; + gfx_invalidate_screen(); + break; + case 1: + ride->track_colour_additional[index] = value; + gfx_invalidate_screen(); + break; + case 2: + *((uint8*)(&ride->vehicle_colours[index])) = value; + RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0); + break; + case 3: + *((uint8*)(&ride->vehicle_colours[index]) + 1) = value; + RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0); + break; + case 4: + ride->track_colour_supports[index] = value; + gfx_invalidate_screen(); + break; + case 5: + ride->colour_scheme_type &= ~(RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN | RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR); + ride->colour_scheme_type |= value; + for(int i = 1; i < countof(ride->vehicle_colours); i++){ + ride->vehicle_colours[i] = ride->vehicle_colours[0]; + ride->vehicle_colours_extended[i] = ride->vehicle_colours_extended[0]; + } + RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0); + break; + case 6: + ride->entrance_style = value; + RCT2_GLOBAL(0x01358840, uint8) = value; + gfx_invalidate_screen(); + break; + case 7: + ride->vehicle_colours_extended[index] = value; + RCT2_CALLPROC_X(0x006DE102, 0, 0, 0, ride_id, 0, 0, 0); + break; + } + window_invalidate_by_number(WC_RIDE, ride_id); + } + *ebx = 0; +} + bool ride_type_has_flag(int rideType, int flag) { return (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (rideType * 8), uint32) & flag) != 0; diff --git a/src/ride/ride.h b/src/ride/ride.h index f9d50b07aa..ce89235380 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -766,6 +766,7 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); int ride_get_refund_price(int ride_id); void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); int get_var_10E_unk_1(rct_ride* ride); int get_var_10E_unk_2(rct_ride* ride); diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index 0ffdb04abd..d5bfe35e8d 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -605,7 +605,7 @@ static void window_loadsave_select(rct_window *w, const char *path) if (scenario_save((char*)path, gConfigGeneral.save_plugin_data ? 1 : 0)) { window_close(w); - game_do_command(0, 1047, 0, -1, GAME_COMMAND_0, 0, 0); + game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); gfx_invalidate_screen(); } else { diff --git a/src/windows/ride.c b/src/windows/ride.c index 03e02001a7..df6f385f26 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -3808,22 +3808,22 @@ static void window_ride_colour_dropdown() window_invalidate(w); break; case WIDX_TRACK_MAIN_COLOUR: - game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0); break; case WIDX_TRACK_ADDITIONAL_COLOUR: - game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0); break; case WIDX_TRACK_SUPPORT_COLOUR: - game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0); break; case WIDX_MAZE_STYLE_DROPDOWN: - game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, *((uint16*)&w->var_494), 0); + game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->var_494), 0); break; case WIDX_ENTRANCE_STYLE_DROPDOWN: - game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_0, 0, 0); + game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); break; case WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN: - game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, 0, 0); + game_do_command(0, (5 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); w->var_48C = 0; break; case WIDX_VEHICLE_COLOUR_INDEX_DROPDOWN: @@ -3831,13 +3831,13 @@ static void window_ride_colour_dropdown() window_invalidate(w); break; case WIDX_VEHICLE_MAIN_COLOUR: - game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0); + game_do_command(0, (2 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0); break; case WIDX_VEHICLE_ADDITIONAL_COLOUR_1: - game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0); + game_do_command(0, (3 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0); break; case WIDX_VEHICLE_ADDITIONAL_COLOUR_2: - game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_0, w->var_48C, 0); + game_do_command(0, (7 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->var_48C, 0); break; } } From ed709b835384aff950b692320fb58d3bc86a4f3a Mon Sep 17 00:00:00 2001 From: zsilencer Date: Fri, 17 Apr 2015 00:47:23 -0600 Subject: [PATCH 14/22] game_command_remove_large_scenery --- src/game.c | 4 +- src/game.h | 2 +- src/interface/viewport_interaction.c | 2 +- src/object.c | 4 +- src/windows/sign.c | 2 +- src/world/map.c | 131 ++++++++++++++++++++++++++- src/world/map.h | 1 + src/world/scenery.h | 9 +- 8 files changed, 145 insertions(+), 10 deletions(-) diff --git a/src/game.c b/src/game.c index 984294fb10..0fefa3b726 100644 --- a/src/game.c +++ b/src/game.c @@ -918,7 +918,7 @@ static uint32 game_do_command_table[58] = { 0x006E519A, 0, 0x006B893C, - 0x006B8E1B, + 0, 0, 0, 0x006D13FE, @@ -981,7 +981,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_remove_fence, game_command_emptysub, - game_command_emptysub, + game_command_remove_large_scenery, game_command_set_current_loan, game_command_set_research_funding, game_command_emptysub, diff --git a/src/game.h b/src/game.h index 7e7e509106..0feb19c63d 100644 --- a/src/game.h +++ b/src/game.h @@ -68,7 +68,7 @@ enum GAME_COMMAND { GAME_COMMAND_41, GAME_COMMAND_REMOVE_FENCE, GAME_COMMAND_43, - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, GAME_COMMAND_SET_CURRENT_LOAN, // 45 GAME_COMMAND_SET_RESEARCH_FUNDING, // 46 GAME_COMMAND_47, diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index a7ece92671..0cd579746d 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -512,7 +512,7 @@ static void viewport_interaction_remove_large_scenery(rct_map_element *mapElemen 1 | ((mapElement->type & 0x3) << 8), y, mapElement->base_height | ((mapElement->properties.scenerymultiple.type >> 10) << 8), - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0 ); diff --git a/src/object.c b/src/object.c index 4be671b373..6b8bc5a6f5 100644 --- a/src/object.c +++ b/src/object.c @@ -907,7 +907,7 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* chunk += 1038; } - scenery_type->large_scenery.var_0C = (uint32)chunk; + scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk; while (*((uint16*)chunk) != 0xFFFF){ chunk += 9; @@ -937,7 +937,7 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; scenery_type->name = 0; scenery_type->image = 0; - scenery_type->large_scenery.var_0C = 0; + scenery_type->large_scenery.tiles = 0; scenery_type->large_scenery.scenery_tab_id = 0; scenery_type->large_scenery.var_12 = 0; scenery_type->large_scenery.var_16 = 0; diff --git a/src/windows/sign.c b/src/windows/sign.c index 39aee6746d..c77defa2c8 100644 --- a/src/windows/sign.c +++ b/src/windows/sign.c @@ -256,7 +256,7 @@ static void window_sign_mouseup() 1 | ((map_element->type&0x3) << 8), y, map_element->base_height | ((map_element->properties.scenerymultiple.type >> 10) << 8), - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0); break; diff --git a/src/world/map.c b/src/world/map.c index 088d625ff4..a790c84410 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -641,6 +641,133 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es *ebx = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : cost); } +/** + * + * rct2: 0x006B8E1B + */ +void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + uint8 base_height = *edx; + uint8 scenerymultiple_index = *edx >> 8; + uint8 map_element_direction = *ebx >> 8; + int x = *eax; + int y = *ecx; + int z = map_element_height(x, y); + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + + if (!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; + } + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE || + map_element->base_height != base_height || + map_element->properties.scenerymultiple.type >> 10 != scenerymultiple_index || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + *ebx = 0; + return; + } + int ecx2 = map_element->properties.scenerymultiple.type >> 10; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.scenerymultiple.type & 0x3FF]; + if(scenery_entry->large_scenery.var_11 != 0xFF){ + uint8 banner_num = map_element->type & MAP_ELEMENT_QUADRANT_MASK; + banner_num |= (map_element->properties.scenerymultiple.colour[0] & 0xE0) >> 2; + banner_num |= (map_element->properties.scenerymultiple.colour[1] & 0xE0) >> 5; + if(gBanners[banner_num].type != BANNER_NULL){ + window_close_by_number(WC_BANNER, banner_num); + gBanners[banner_num].type = BANNER_NULL; + user_string_free(gBanners[banner_num].string_idx); + } + } + int x2 = scenery_entry->large_scenery.tiles[ecx2].x_offset; + int y2 = scenery_entry->large_scenery.tiles[ecx2].y_offset; + int z2 = (base_height * 8) - scenery_entry->large_scenery.tiles[ecx2].z_offset; + switch(map_element->type & MAP_ELEMENT_DIRECTION_MASK){ + case MAP_ELEMENT_DIRECTION_WEST: + break; + case MAP_ELEMENT_DIRECTION_NORTH:{ + int temp = x2; + x2 = y2; + y2 = -temp; + }break; + case MAP_ELEMENT_DIRECTION_EAST: + x2 = -x2; + y2 = -y2; + break; + case MAP_ELEMENT_DIRECTION_SOUTH:{ + int temp = y2; + y2 = x2; + x2 = -temp; + }break; + } + x2 = -x2 + x; + y2 = -y2 + y; + int i = 0; + while(1){ + if(scenery_entry->large_scenery.tiles[i].x_offset == -1){ + *ebx = scenery_entry->large_scenery.removal_price * 10; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } + return; + } + int x3 = scenery_entry->large_scenery.tiles[i].x_offset; + int y3 = scenery_entry->large_scenery.tiles[i].y_offset; + int z3 = scenery_entry->large_scenery.tiles[i].z_offset; + switch(map_element->type & MAP_ELEMENT_DIRECTION_MASK){ + case MAP_ELEMENT_DIRECTION_WEST: + break; + case MAP_ELEMENT_DIRECTION_NORTH:{ + int temp = x3; + x3 = y3; + y3 = -temp; + }break; + case MAP_ELEMENT_DIRECTION_EAST: + x3 = -x3; + y3 = -y3; + break; + case MAP_ELEMENT_DIRECTION_SOUTH:{ + int temp = y3; + y3 = x3; + x3 = -temp; + }break; + } + x3 += x2; + y3 += y2; + z3 += z2; + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_owned(x3, y3, z3)){ + *ebx = MONEY32_UNDEFINED; + return; + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_map_element* map_element = map_get_first_element_at(x3 / 32, y3 / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction || + map_element->properties.scenerymultiple.type >> 10 != i || + map_element->base_height != base_height){ + map_element++; + } + map_invalidate_tile_full(x3, y3); + map_element_remove(map_element); + } + } + i++; + } +} + money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -1218,8 +1345,8 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, return; } } - rct_object_entry_extended* object_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_object_entry_extended*)[map_element->properties.fence.slope]; - if((uint8)object_entry->checksum != 0xFF){ + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + if(scenery_entry->wall.var_0D != 0xFF){ rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; if(banner->type != BANNER_NULL){ window_close_by_number(WC_BANNER, map_element->properties.fence.item[0]); diff --git a/src/world/map.h b/src/world/map.h index dc91f3046e..adfbca7701 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -275,6 +275,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); diff --git a/src/world/scenery.h b/src/world/scenery.h index e94337fec8..7b4765f1e7 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -58,12 +58,19 @@ typedef enum { SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000 } SMALL_SCENERY_FLAGS; +typedef struct { + sint16 x_offset; + sint16 y_offset; + sint16 z_offset; + uint8 pad_6[3]; +} rct_large_scenery_tile; + typedef struct { uint8 tool_id; // 0x06 uint8 flags; // 0x07 sint16 price; // 0x08 sint16 removal_price; // 0x0A - uint32 var_0C; + rct_large_scenery_tile* tiles; // 0x0C uint8 scenery_tab_id; // 0x10 uint8 var_11; uint32 var_12; From e7d3d8b19d27611cdbef21a186b8b2e5ff1e9f36 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Fri, 17 Apr 2015 14:56:19 -0600 Subject: [PATCH 15/22] game_command_set_scenery_colour --- src/game.c | 4 ++-- src/world/map.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/world/map.h | 1 + 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/game.c b/src/game.c index 0fefa3b726..a21cd0dd49 100644 --- a/src/game.c +++ b/src/game.c @@ -926,7 +926,7 @@ static uint32 game_do_command_table[58] = { 0x006CDEE4, 0x006B9E6D, // 50 0x006BA058, - 0x006E0F26, + 0, 0x006E56B5, 0x006B909A, 0x006BA16A, @@ -989,7 +989,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_emptysub, // 50 game_command_emptysub, - game_command_emptysub, + game_command_set_scenery_colour, game_command_emptysub, game_command_emptysub, game_command_emptysub, diff --git a/src/world/map.c b/src/world/map.c index a790c84410..c9e09d9927 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -768,6 +768,55 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i } } + +/** + * + * rct2: 0x006E0F26 + */ +void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + int x = (sint16)*eax; + int y = (sint16)*ecx; + uint8 base_height = *edx; + uint8 scenery_type = *edx >> 8; + uint8 map_element_type = *ebx >> 8; + uint8 color1 = *ebp; + uint8 color2 = *ebp >> 8; + int z = base_height * 8; + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_owned(x, y, z)){ + *ebx = MONEY32_UNDEFINED; + return; + } + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element->type != map_element_type || + map_element->base_height != base_height || + map_element->properties.scenery.type != scenery_type){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + *ebx = 0; + return; + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + map_element->properties.scenery.colour_1 &= 0xE0; + map_element->properties.scenery.colour_1 |= color1; + map_element->properties.scenery.colour_2 &= 0xE0; + map_element->properties.scenery.colour_2 |= color2; + map_invalidate_tile_full(x, y); + } + } + *ebx = 0; +} + money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; diff --git a/src/world/map.h b/src/world/map.h index adfbca7701..f541658201 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -276,6 +276,7 @@ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); From 1782a62055671c0b6ef44a9629dafede8ff0f925 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Fri, 17 Apr 2015 23:01:50 -0600 Subject: [PATCH 16/22] game_command_set_fence_colour --- src/game.c | 4 ++-- src/world/map.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++--- src/world/map.h | 1 + 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/game.c b/src/game.c index a21cd0dd49..3069b86f08 100644 --- a/src/game.c +++ b/src/game.c @@ -927,7 +927,7 @@ static uint32 game_do_command_table[58] = { 0x006B9E6D, // 50 0x006BA058, 0, - 0x006E56B5, + 0, 0x006B909A, 0x006BA16A, 0x006648E3, @@ -990,7 +990,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, // 50 game_command_emptysub, game_command_set_scenery_colour, - game_command_emptysub, + game_command_set_fence_colour, game_command_emptysub, game_command_emptysub, game_command_emptysub, diff --git a/src/world/map.c b/src/world/map.c index c9e09d9927..4979dfbc75 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -768,7 +768,6 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i } } - /** * * rct2: 0x006E0F26 @@ -776,8 +775,8 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; - int x = (sint16)*eax; - int y = (sint16)*ecx; + int x = *eax; + int y = *ecx; uint8 base_height = *edx; uint8 scenery_type = *edx >> 8; uint8 map_element_type = *ebx >> 8; @@ -817,6 +816,61 @@ void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int *ebx = 0; } +/** + * + * rct2: 0x006E56B5 + */ +void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + int x = *eax; + int y = *ecx; + uint8 map_element_direction = *edx; + uint8 base_height = *edx >> 8; + uint8 color1 = *ebx >> 8; + uint8 color2 = *ebp; + uint8 color3 = *ebp >> 8; + int z = base_height * 8; + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_in_park(x, y)){ + *ebx = MONEY32_UNDEFINED; + return; + } + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_FENCE || + map_element->base_height != base_height || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction|| + ((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5))){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + *ebx = 0; + return; + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + map_element->properties.fence.item[1] &= 0xE0; + map_element->properties.fence.item[1] |= color1; + map_element->flags &= 0x9F; + map_element->properties.fence.item[1] &= 0x1F; + map_element->properties.fence.item[1] |= (color2 & 0x7) * 32; + map_element->flags |= (color2 & 0x18) * 4; + if(scenery_entry->wall.flags & 0x80){ + map_element->properties.fence.item[0] = color3; + } + map_invalidate_tile(x, y, z, z + 0x48); + } + } + *ebx = 0; +} + money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; diff --git a/src/world/map.h b/src/world/map.h index f541658201..dfa0a9aeb8 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -277,6 +277,7 @@ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); From 4379df67c424d0e80f38ae8be2fbf465e48b786b Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sat, 18 Apr 2015 13:03:18 -0600 Subject: [PATCH 17/22] game_command_set_large_scenery_colour --- src/game.c | 4 +- src/world/map.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ src/world/map.h | 1 + 3 files changed, 118 insertions(+), 2 deletions(-) diff --git a/src/game.c b/src/game.c index 3069b86f08..18b72a9350 100644 --- a/src/game.c +++ b/src/game.c @@ -928,7 +928,7 @@ static uint32 game_do_command_table[58] = { 0x006BA058, 0, 0, - 0x006B909A, + 0, 0x006BA16A, 0x006648E3, 0 @@ -991,7 +991,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_set_scenery_colour, game_command_set_fence_colour, - game_command_emptysub, + game_command_set_large_scenery_colour, game_command_emptysub, game_command_emptysub, game_command_clear_scenery diff --git a/src/world/map.c b/src/world/map.c index 4979dfbc75..98941756ff 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -871,6 +871,121 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* *ebx = 0; } +/** + * + * rct2: 0x006B909A + */ +void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + int x = *eax; + int y = *ecx; + uint8 map_element_direction = *ebx >> 8; + uint8 base_height = *edx; + uint8 scenerymultiple_index = *edx >> 8; + uint8 color1 = *ebp; + uint8 color2 = *ebp >> 8; + int z = map_element_height(x, y); + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE || + map_element->base_height != base_height || + map_element->properties.scenerymultiple.type >> 10 != scenerymultiple_index || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + *ebx = 0; + return; + } + int ecx2 = map_element->properties.scenerymultiple.type >> 10; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.scenerymultiple.type & 0x3FF]; + int x2 = scenery_entry->large_scenery.tiles[ecx2].x_offset; + int y2 = scenery_entry->large_scenery.tiles[ecx2].y_offset; + int z2 = (base_height * 8) - scenery_entry->large_scenery.tiles[ecx2].z_offset; + switch(map_element->type & MAP_ELEMENT_DIRECTION_MASK){ + case MAP_ELEMENT_DIRECTION_WEST: + break; + case MAP_ELEMENT_DIRECTION_NORTH:{ + int temp = x2; + x2 = y2; + y2 = -temp; + }break; + case MAP_ELEMENT_DIRECTION_EAST: + x2 = -x2; + y2 = -y2; + break; + case MAP_ELEMENT_DIRECTION_SOUTH:{ + int temp = y2; + y2 = x2; + x2 = -temp; + }break; + } + x2 = -x2 + x; + y2 = -y2 + y; + int i = 0; + while(1){ + if(scenery_entry->large_scenery.tiles[i].x_offset == -1){ + *ebx = 0; + return; + } + int x3 = scenery_entry->large_scenery.tiles[i].x_offset; + int y3 = scenery_entry->large_scenery.tiles[i].y_offset; + int z3 = scenery_entry->large_scenery.tiles[i].z_offset; + switch(map_element->type & MAP_ELEMENT_DIRECTION_MASK){ + case MAP_ELEMENT_DIRECTION_WEST: + break; + case MAP_ELEMENT_DIRECTION_NORTH:{ + int temp = x3; + x3 = y3; + y3 = -temp; + }break; + case MAP_ELEMENT_DIRECTION_EAST: + x3 = -x3; + y3 = -y3; + break; + case MAP_ELEMENT_DIRECTION_SOUTH:{ + int temp = y3; + y3 = x3; + x3 = -temp; + }break; + } + x3 += x2; + y3 += y2; + z3 += z2; + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_owned(x3, y3, z3)){ + *ebx = MONEY32_UNDEFINED; + return; + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_map_element* map_element = map_get_first_element_at(x3 / 32, y3 / 32); + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE || + (map_element->type & MAP_ELEMENT_DIRECTION_MASK) != map_element_direction || + map_element->properties.scenerymultiple.type >> 10 != i || + map_element->base_height != base_height){ + map_element++; + } + map_element->properties.scenerymultiple.colour[0] &= 0xE0; + map_element->properties.scenerymultiple.colour[0] |= color1; + map_element->properties.scenerymultiple.colour[1] &= 0xE0; + map_element->properties.scenerymultiple.colour[1] |= color2; + map_invalidate_tile_full(x3, y3); + } + } + i++; + } + *ebx = 0; +} + money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; diff --git a/src/world/map.h b/src/world/map.h index dfa0a9aeb8..c00b319213 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -278,6 +278,7 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); From b8657da99f80a19543ec65f17b946d564b4735ac Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sat, 18 Apr 2015 15:48:17 -0600 Subject: [PATCH 18/22] game_command_set_banner_colour --- src/game.c | 4 ++-- src/world/map.c | 56 ++++++++++++++++++++++++++++++++++++++++++------- src/world/map.h | 1 + 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/game.c b/src/game.c index 18b72a9350..5093f8b287 100644 --- a/src/game.c +++ b/src/game.c @@ -929,7 +929,7 @@ static uint32 game_do_command_table[58] = { 0, 0, 0, - 0x006BA16A, + 0, 0x006648E3, 0 }; @@ -992,7 +992,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_set_scenery_colour, game_command_set_fence_colour, game_command_set_large_scenery_colour, - game_command_emptysub, + game_command_set_banner_colour, game_command_emptysub, game_command_clear_scenery }; diff --git a/src/world/map.c b/src/world/map.c index 98941756ff..919d2b5722 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -625,7 +625,7 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es while(map_element->type != map_element_type || map_element->base_height != base_height || map_element->properties.scenery.type != scenery_type || - (*ebx & 0x40) && !(map_element->flags & 0x10)){ + (*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5)){ map_element++; if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ *ebx = 0; @@ -675,7 +675,7 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i return; } } - if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + if((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5)){ *ebx = 0; return; } @@ -801,7 +801,7 @@ void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int return; } } - if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + if((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5)){ *ebx = 0; return; } @@ -850,7 +850,7 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* return; } } - if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + if((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5)){ *ebx = 0; return; } @@ -902,7 +902,7 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed return; } } - if((*ebx & 0x40) && !(map_element->flags & 0x10)){ + if((*ebx & 0x40) && !(map_element->flags & MAP_ELEMENT_FLAG_5)){ *ebx = 0; return; } @@ -986,6 +986,49 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed *ebx = 0; } +/** + * + * rct2: 0x006BA16A + */ +void game_command_set_banner_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + int x = *eax; + int y = *ecx; + uint8 base_height = *edx; + uint8 banner_position = *edx >> 8; + uint8 color = *ebp; + int z = (base_height * 8); + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR)){ + if(!map_is_location_owned(x, y, z - 16)){ + *ebx = MONEY32_UNDEFINED; + return; + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element->type != MAP_ELEMENT_TYPE_BANNER || + map_element->properties.banner.position != banner_position){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = MONEY32_UNDEFINED; + return; + } + } + rct_window* window = window_find_by_number(WC_BANNER, map_element->properties.banner.index); + if(window){ + window_invalidate(window); + } + gBanners[map_element->properties.banner.index].colour = color; + map_invalidate_tile(x, y, z, z + 32); + } + } + *ebx = 0; +} + money32 sub_6A67C0(int x, int y, int z, int flags) { int eax, ebx, ecx, edx, esi, edi, ebp; @@ -1502,8 +1545,7 @@ void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, continue; } height -= 2; - int eax2 = xi, ebx2 = *ebx, ecx2 = yi, edx2 = (min_height << 8) + height, esi2, edi2, ebp2; - ebx2 = game_do_command_p(GAME_COMMAND_16, &eax2, &ebx2, &ecx2, &edx2, &esi2, &edi2, &ebp2); + int ebx2 = game_do_command(xi, *ebx, yi, (min_height << 8) + height, GAME_COMMAND_16, 0, 0); if(ebx2 == MONEY32_UNDEFINED){ *ebx = MONEY32_UNDEFINED; return; diff --git a/src/world/map.h b/src/world/map.h index c00b319213..9ddb688bd4 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -279,6 +279,7 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_set_banner_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_raise_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); From c40a6f4789c2d1569bfeec0ff14af8054562868b Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 22 Apr 2015 01:46:44 -0600 Subject: [PATCH 19/22] game_command_remove_banner --- src/game.c | 4 ++-- src/game.h | 2 +- src/windows/banner.c | 2 +- src/world/footpath.c | 2 +- src/world/map.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ src/world/map.h | 1 + 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/game.c b/src/game.c index 5093f8b287..16a1e44c3a 100644 --- a/src/game.c +++ b/src/game.c @@ -925,7 +925,7 @@ static uint32 game_do_command_table[58] = { 0, 0x006CDEE4, 0x006B9E6D, // 50 - 0x006BA058, + 0, 0, 0, 0, @@ -988,7 +988,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_start_campaign, game_command_emptysub, game_command_emptysub, // 50 - game_command_emptysub, + game_command_remove_banner, game_command_set_scenery_colour, game_command_set_fence_colour, game_command_set_large_scenery_colour, diff --git a/src/game.h b/src/game.h index 0feb19c63d..f7b09ca991 100644 --- a/src/game.h +++ b/src/game.h @@ -75,7 +75,7 @@ enum GAME_COMMAND { GAME_COMMAND_START_MARKETING_CAMPAIGN, // 48 GAME_COMMAND_49, GAME_COMMAND_50, // New banner? (possibly scenery) - GAME_COMMAND_51, // Remove banner + GAME_COMMAND_REMOVE_BANNER, // Remove banner GAME_COMMAND_52, GAME_COMMAND_53, GAME_COMMAND_54, diff --git a/src/windows/banner.c b/src/windows/banner.c index 8f0ac1605f..79100e79d4 100644 --- a/src/windows/banner.c +++ b/src/windows/banner.c @@ -201,7 +201,7 @@ static void window_banner_mouseup() window_close(w); break; case WIDX_BANNER_DEMOLISH: - game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_51, 0, 0); + game_do_command(x, 1, y, map_element->base_height | (map_element->properties.banner.position << 8), GAME_COMMAND_REMOVE_BANNER, 0, 0); break; case WIDX_BANNER_TEXT: window_text_input_open(w, WIDX_BANNER_TEXT, 2982, 2983, gBanners[w->number].string_idx, 0, 32); diff --git a/src/world/footpath.c b/src/world/footpath.c index 330cd02563..c811074f36 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -345,7 +345,7 @@ void remove_banners_at_element(int x, int y, rct_map_element* mapElement){ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH)return; else if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_BANNER)continue; - game_do_command(x, 1, y, mapElement->base_height | mapElement->properties.banner.position << 8, GAME_COMMAND_51, 0, 0); + game_do_command(x, 1, y, mapElement->base_height | mapElement->properties.banner.position << 8, GAME_COMMAND_REMOVE_BANNER, 0, 0); mapElement--; } } diff --git a/src/world/map.c b/src/world/map.c index 919d2b5722..e80a6f12a2 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -768,6 +768,54 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i } } +/** + * + * rct2: 0x006BA058 + */ +void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int x = *eax; + int y = *ecx; + uint8 base_height = *edx; + uint8 banner_position = *edx >> 8; + int z = base_height * 8; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 12; + RCT2_GLOBAL(0x009DEA5E, uint16) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint16) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint16) = z; + if(!(*ebx & 0x40) && RCT2_GLOBAL(0x009DEA6E, uint8) != 0){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; + } + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !map_is_location_owned(x, y, z - 16)){ + *ebx = MONEY32_UNDEFINED; + return; + } + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + while(map_element->type != MAP_ELEMENT_TYPE_BANNER || + map_element->properties.banner.position != banner_position){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + *ebx = 0; + return; + } + } + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + window_close_by_number(WC_BANNER, map_element->properties.banner.index); + rct_banner *banner = &gBanners[map_element->properties.banner.index]; + user_string_free(banner->string_idx); + banner->type = BANNER_NULL; + map_invalidate_tile(x, y, z, z + 32); + map_element_remove(map_element); + } + rct_scenery_entry *scenery_entry = object_entry_groups[OBJECT_TYPE_BANNERS].chunks[map_element->properties.banner.index]; + *ebx = (scenery_entry->banner.price * -3) / 4; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } +} + /** * * rct2: 0x006E0F26 diff --git a/src/world/map.h b/src/world/map.h index 9ddb688bd4..8d66ede404 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -276,6 +276,7 @@ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); From a8a434e26108b2e273c6e6bdb5c092e5157a69fc Mon Sep 17 00:00:00 2001 From: zsilencer Date: Wed, 22 Apr 2015 15:47:59 -0600 Subject: [PATCH 20/22] game_command_place_banner --- src/game.c | 4 +- src/game.h | 2 +- src/localisation/string_ids.h | 3 + src/object.c | 3 +- src/windows/top_toolbar.c | 4 +- src/world/map.c | 103 +++++++++++++++++++++++++++++++++- src/world/map.h | 2 + src/world/map_animation.c | 2 +- 8 files changed, 113 insertions(+), 10 deletions(-) diff --git a/src/game.c b/src/game.c index 16a1e44c3a..fef2cb6850 100644 --- a/src/game.c +++ b/src/game.c @@ -924,7 +924,7 @@ static uint32 game_do_command_table[58] = { 0x006D13FE, 0, 0x006CDEE4, - 0x006B9E6D, // 50 + 0, // 50 0, 0, 0, @@ -987,7 +987,7 @@ static GAME_COMMAND_POINTER* new_game_command_table[58] = { game_command_emptysub, game_command_start_campaign, game_command_emptysub, - game_command_emptysub, // 50 + game_command_place_banner, // 50 game_command_remove_banner, game_command_set_scenery_colour, game_command_set_fence_colour, diff --git a/src/game.h b/src/game.h index f7b09ca991..a60d5cd648 100644 --- a/src/game.h +++ b/src/game.h @@ -74,7 +74,7 @@ enum GAME_COMMAND { GAME_COMMAND_47, GAME_COMMAND_START_MARKETING_CAMPAIGN, // 48 GAME_COMMAND_49, - GAME_COMMAND_50, // New banner? (possibly scenery) + GAME_COMMAND_PLACE_BANNER, // New banner? (possibly scenery) GAME_COMMAND_REMOVE_BANNER, // Remove banner GAME_COMMAND_52, GAME_COMMAND_53, diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index f1fef1b95e..e9da964f74 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -319,6 +319,7 @@ enum { STR_BUILD_FOOTPATH_TIP = 1173, + STR_BANNER_SIGN_IN_THE_WAY = 1174, STR_CANT_BUILD_THIS_ON_SLOPED_FOOTPATH = 1175, STR_CANT_BUILD_FOOTPATH_HERE = 1176, STR_CANT_REMOVE_FOOTPATH_FROM_HERE = 1177, @@ -739,6 +740,8 @@ enum { STR_CANT_DEMOLISH_RIDE = 2248, + STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS = 2252, + STR_RESEARCH_TRANSPORT_RIDES = 2253, STR_RESEARCH_GENTLE_RIDES = 2254, STR_RESEARCH_ROLLER_COASTERS = 2255, diff --git a/src/object.c b/src/object.c index 6b8bc5a6f5..7f2be9d177 100644 --- a/src/object.c +++ b/src/object.c @@ -909,8 +909,9 @@ int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk; + // skip over large scenery tiles while (*((uint16*)chunk) != 0xFFFF){ - chunk += 9; + chunk += sizeof(rct_large_scenery_tile); } chunk += 2; diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 90af8a665f..887915cb48 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1416,8 +1416,8 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w int cost; { - int esi = 0, eax = grid_x, ecx = grid_y, edx = parameter_2, ebx = (parameter_1 & 0xFF00) | 1; - cost = game_do_command_p(GAME_COMMAND_50, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); + int esi = 0, eax = grid_x, ecx = grid_y, edx = grid_z; + game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); } if (ebx == MONEY32_UNDEFINED)return; diff --git a/src/world/map.c b/src/world/map.c index e80a6f12a2..db832b1768 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -29,6 +29,7 @@ #include "banner.h" #include "climate.h" #include "map.h" +#include "map_animation.h" #include "park.h" #include "scenery.h" @@ -797,19 +798,20 @@ void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi map_element->properties.banner.position != banner_position){ map_element++; if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ - *ebx = 0; + *ebx = MONEY32_UNDEFINED; return; } } + rct_banner *banner = &gBanners[map_element->properties.banner.index]; + uint8 banner_type = banner->type; if(*ebx & GAME_COMMAND_FLAG_APPLY){ window_close_by_number(WC_BANNER, map_element->properties.banner.index); - rct_banner *banner = &gBanners[map_element->properties.banner.index]; user_string_free(banner->string_idx); banner->type = BANNER_NULL; map_invalidate_tile(x, y, z, z + 32); map_element_remove(map_element); } - rct_scenery_entry *scenery_entry = object_entry_groups[OBJECT_TYPE_BANNERS].chunks[map_element->properties.banner.index]; + rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[banner_type]; *ebx = (scenery_entry->banner.price * -3) / 4; if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ *ebx = 0; @@ -1667,6 +1669,90 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, *ebx = 0; } +/** + * + * rct2: 0x006B9E6D + */ +void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int x = (uint16)*eax; + int y = (uint16)*ecx; + uint8 base_height = *edx; + uint8 edge = *edx >> 8; + uint8 colour = *edi; + uint8 type = *ebx >> 8; + RCT2_GLOBAL(0x009DEA5E, uint32) = x + 16; + RCT2_GLOBAL(0x009DEA60, uint32) = y + 16; + RCT2_GLOBAL(0x009DEA62, uint32) = base_height * 16; + RCT2_GLOBAL(0x141F56C, uint8) = 12; + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0){ + if(sub_68B044() && x < 8192 && y < 8192){ + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + int dl = base_height * 2; + int ch = (base_height - 1) * 2; + while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH || + (map_element->base_height != dl && map_element->base_height != ch) || + !(map_element->properties.path.edges & (1 << edge))){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; + *ebx = MONEY32_UNDEFINED; + return; + } + } + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !map_is_location_owned(x, y, base_height * 16)){ + *ebx = MONEY32_UNDEFINED; + return; + } + map_element = map_get_first_element_at(x / 32, y / 32); + dl = (base_height + 1) * 2; + while(map_element->type != MAP_ELEMENT_TYPE_BANNER || + map_element->base_height != dl || + (map_element->properties.banner.position & 0x3) != edge){ + map_element++; + if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ + uint8 a = sub_6BA278(*ebx); + if(a == 0xFF){ + *ebx = MONEY32_UNDEFINED; + return; + } + *edi = a; + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); + gBanners[a].type = type; + gBanners[a].colour = colour; + gBanners[a].x = x / 32; + gBanners[a].y = y / 32; + new_map_element->type = MAP_ELEMENT_TYPE_BANNER; + new_map_element->clearance_height = new_map_element->base_height + 2; + new_map_element->properties.banner.position = edge; + new_map_element->properties.banner.flags = 0xFF; + new_map_element->properties.banner.unused = 0; + new_map_element->properties.banner.index = a; + if(*ebx & 0x40){ + new_map_element->flags |= 0x10; + } + map_invalidate_tile_full(x, y); + map_animation_create(0x0A, x, y, new_map_element->base_height); + } + rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[type]; + *ebx = scenery_entry->banner.price; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } + return; + } + } + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_BANNER_SIGN_IN_THE_WAY; + *ebx = MONEY32_UNDEFINED; + return; + } + }else{ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + } + *ebx = MONEY32_UNDEFINED; +} + /** * * rct2: 0x006EC6D7 @@ -1860,6 +1946,17 @@ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl) return map_can_construct_with_clear_at(x, y, zLow, zHigh, (void*)0xFFFFFFFF, bl); } +/** + * + * rct2: 0x006BA278 + */ +int sub_6BA278(int ebx) +{ + int eax, ecx, edx, esi, edi, ebp; + RCT2_CALLFUNC_X(0x006BA278, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return eax; +} + /** * * rct2: 0x006E5935 diff --git a/src/world/map.h b/src/world/map.h index 8d66ede404..963ecd07f3 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -273,6 +273,7 @@ int sub_68B044(); rct_map_element *map_element_insert(int x, int y, int z, int flags); int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl); int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); +int sub_6BA278(int ebx); void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); @@ -288,6 +289,7 @@ void game_command_lower_land(int* eax, int* ebx, int* ecx, int* edx, int* esi, i void game_command_raise_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_lower_water(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #define GET_MAP_ELEMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element)[x])) #define TILE_MAP_ELEMENT_POINTER(x) (RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[x]) diff --git a/src/world/map_animation.c b/src/world/map_animation.c index b481cb0029..3a31fe5d82 100644 --- a/src/world/map_animation.c +++ b/src/world/map_animation.c @@ -48,7 +48,7 @@ void map_animation_create(int type, int x, int y, int z) { rct_map_animation *aobj = &gAnimatedObjects[0]; int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16); - for (; numAnimatedObjects > 0; aobj++) { + for (int i = 0; i < numAnimatedObjects; i++, aobj++) { if (aobj->x != x) continue; if (aobj->y != y) From 3b416a646e5917302782f589034e09ec6d264dbd Mon Sep 17 00:00:00 2001 From: zsilencer Date: Thu, 23 Apr 2015 10:36:31 -0600 Subject: [PATCH 21/22] create_new_banner done by duncanspumpkin --- src/localisation/string_ids.h | 2 ++ src/world/banner.c | 33 +++++++++++++++++++++++++++++++++ src/world/banner.h | 1 + src/world/map.c | 16 ++++++++-------- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index e9da964f74..302e2c8ac2 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -1069,6 +1069,8 @@ enum { STR_MUSIC_ACKNOWLEDGEMENTS_ELLIPSIS = 2862, STR_MUSIC_ACKNOWLEDGEMENTS = 2863, + STR_TOO_MANY_BANNERS_IN_GAME = 2980, + STR_CHANGE_BANNER_TEXT_TIP = 2986, STR_SET_AS_NO_ENTRY_BANNER_TIP = 2987, STR_DEMOLISH_BANNER_TIP = 2988, diff --git a/src/world/banner.c b/src/world/banner.c index 172ab08f7d..306b1cad26 100644 --- a/src/world/banner.c +++ b/src/world/banner.c @@ -19,6 +19,8 @@ *****************************************************************************/ #include "../addresses.h" +#include "../game.h" +#include "../localisation/localisation.h" #include "banner.h" rct_banner *gBanners = (rct_banner*)0x0135A124; @@ -32,3 +34,34 @@ void banner_init() { gBanners[i].type = BANNER_NULL; } } + +/* rct2: 0x006BA278 + * Creates a new banner and returns the index of the banner + * If the flag GAME_COMMAND_FLAG_APPLY is NOT set then returns + * the first unused index but does NOT mark the banner as created. + * returns 0xFF on failure. + */ +int create_new_banner(uint8 flags){ + int banner_index = 0; + for (; banner_index < MAX_BANNERS; banner_index++){ + if (gBanners[banner_index].type == BANNER_NULL){ + break; + } + } + + if (banner_index == MAX_BANNERS){ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_BANNERS_IN_GAME; + return BANNER_NULL; + } + + if (flags & GAME_COMMAND_FLAG_APPLY){ + rct_banner* banner = &gBanners[banner_index]; + + banner->flags = 0; + banner->type = 0; + banner->string_idx = 778; + banner->colour = 2; + banner->text_colour = 2; + } + return banner_index; +} \ No newline at end of file diff --git a/src/world/banner.h b/src/world/banner.h index 5e7843818a..c3ee3300f9 100644 --- a/src/world/banner.h +++ b/src/world/banner.h @@ -44,5 +44,6 @@ enum{ extern rct_banner *gBanners; void banner_init(); +int create_new_banner(uint8 flags); #endif diff --git a/src/world/map.c b/src/world/map.c index db832b1768..a98612d2e6 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -1711,24 +1711,24 @@ void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, (map_element->properties.banner.position & 0x3) != edge){ map_element++; if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ - uint8 a = sub_6BA278(*ebx); - if(a == 0xFF){ + int banner_index = create_new_banner(*ebx); + if(banner_index == BANNER_NULL){ *ebx = MONEY32_UNDEFINED; return; } - *edi = a; + *edi = banner_index; if(*ebx & GAME_COMMAND_FLAG_APPLY){ rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); - gBanners[a].type = type; - gBanners[a].colour = colour; - gBanners[a].x = x / 32; - gBanners[a].y = y / 32; + gBanners[banner_index].type = type; + gBanners[banner_index].colour = colour; + gBanners[banner_index].x = x / 32; + gBanners[banner_index].y = y / 32; new_map_element->type = MAP_ELEMENT_TYPE_BANNER; new_map_element->clearance_height = new_map_element->base_height + 2; new_map_element->properties.banner.position = edge; new_map_element->properties.banner.flags = 0xFF; new_map_element->properties.banner.unused = 0; - new_map_element->properties.banner.index = a; + new_map_element->properties.banner.index = banner_index; if(*ebx & 0x40){ new_map_element->flags |= 0x10; } From 71e21c2a6cdb77466be3c2b92ba73bd2f25c3ff8 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Sat, 25 Apr 2015 08:55:12 -0600 Subject: [PATCH 22/22] refactor mixer, add support for streamed music --- src/audio/audio.c | 2 +- src/audio/mixer.cpp | 368 +++++++++++++++++++++++++--------- src/audio/mixer.h | 109 ++++++---- src/localisation/string_ids.h | 3 + src/peep/peep.c | 2 +- src/ride/ride.c | 4 +- src/windows/top_toolbar.c | 6 +- src/world/footpath.h | 1 + src/world/map.c | 5 +- src/world/scenery.c | 4 +- src/world/scenery.h | 6 + 11 files changed, 367 insertions(+), 143 deletions(-) diff --git a/src/audio/audio.c b/src/audio/audio.c index 3703d8beec..f562678469 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -1555,7 +1555,7 @@ void start_title_music() && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) { if (!RCT2_GLOBAL(0x009AF600, uint8)) { #ifdef USE_MIXER - gTitleMusicChannel = Mixer_Play_Music(musicPathId); + gTitleMusicChannel = Mixer_Play_Music(musicPathId, true); #else RCT2_GLOBAL(0x014241BC, uint32) = 1; int result = sound_channel_load_file2(3, (char*)get_file_path(musicPathId), 0); diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index 0888df65b4..247e1aa395 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -31,21 +31,64 @@ extern "C" { Mixer gMixer; -Sample::Sample() +Source::~Source() +{ + +} + +unsigned long Source::GetSome(unsigned long offset, const uint8** data, unsigned long length) +{ + if (offset >= Length()) { + return 0; + } + unsigned long size = length; + if (offset + length > Length()) { + size = Length() - offset; + } + return Read(offset, data, size); +} + +unsigned long Source::Length() +{ + return length; +} + +const AudioFormat& Source::Format() +{ + return format; +} + +Source_Null::Source_Null() +{ + length = 0; +} + +unsigned long Source_Null::Read(unsigned long offset, const uint8** data, unsigned long length) +{ + return 0; +} + +Source_Sample::Source_Sample() { data = 0; length = 0; issdlwav = false; } -Sample::~Sample() +Source_Sample::~Source_Sample() { Unload(); } -bool Sample::Load(const char* filename) +unsigned long Source_Sample::Read(unsigned long offset, const uint8** data, unsigned long length) { - log_verbose("Sample::Load(%s)", filename); + *data = &Source_Sample::data[offset]; + return length; +} + +bool Source_Sample::LoadWAV(const char* filename) +{ + log_verbose("Source_Sample::LoadWAV(%s)", filename); utf8 utf8filename[512]; win1252_to_utf8(utf8filename, filename, sizeof(utf8filename)); @@ -75,9 +118,9 @@ bool Sample::Load(const char* filename) return true; } -bool Sample::LoadCSS1(const char* filename, unsigned int offset) +bool Source_Sample::LoadCSS1(const char* filename, unsigned int offset) { - log_verbose("Sample::LoadCSS1(%s, %d)", filename, offset); + log_verbose("Source_Sample::LoadCSS1(%s, %d)", filename, offset); utf8 utf8filename[512]; win1252_to_utf8(utf8filename, filename, sizeof(utf8filename)); @@ -107,13 +150,18 @@ bool Sample::LoadCSS1(const char* filename, unsigned int offset) format.freq = waveformat.nSamplesPerSec; format.format = AUDIO_S16LSB; format.channels = waveformat.nChannels; - data = new uint8[length]; + data = new (std::nothrow) uint8[length]; + if (!data) { + log_verbose("Unable to allocate data"); + SDL_RWclose(rw); + return false; + } SDL_RWread(rw, data, length, 1); SDL_RWclose(rw); return true; } -void Sample::Unload() +void Source_Sample::Unload() { if (data) { if (issdlwav) { @@ -127,16 +175,11 @@ void Sample::Unload() length = 0; } -bool Sample::Loaded() +bool Source_Sample::Convert(AudioFormat format) { - return data != 0; -} - -bool Sample::Convert(AudioFormat format) -{ - if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){ + if(Source_Sample::format.format != format.format || Source_Sample::format.channels != format.channels || Source_Sample::format.freq != format.freq){ SDL_AudioCVT cvt; - if (SDL_BuildAudioCVT(&cvt, Sample::format.format, Sample::format.channels, Sample::format.freq, format.format, format.channels, format.freq) < 0) { + if (SDL_BuildAudioCVT(&cvt, Source_Sample::format.format, Source_Sample::format.channels, Source_Sample::format.freq, format.format, format.channels, format.freq) < 0) { return false; } cvt.len = length; @@ -149,69 +192,147 @@ bool Sample::Convert(AudioFormat format) Unload(); data = cvt.buf; length = cvt.len_cvt; - Sample::format = format; + Source_Sample::format = format; return true; } return false; } -const uint8* Sample::Data() +Source_SampleStream::Source_SampleStream() { - return data; + length = 0; + rw = NULL; + buffer = 0; + buffersize = 0; } -unsigned long Sample::Length() +Source_SampleStream::~Source_SampleStream() { - return length; + Unload(); } -Stream::Stream() +unsigned long Source_SampleStream::Read(unsigned long offset, const uint8** data, unsigned long length) { - sourcetype = SOURCE_NONE; + if (length > buffersize) { + if (buffer) { + delete[] buffer; + } + buffer = new (std::nothrow) uint8[length]; + if (!buffer) { + return 0; + } + buffersize = length; + } + Sint64 currentposition = SDL_RWtell(rw); + if (currentposition == -1) { + return 0; + } + if (currentposition - databegin != offset) { + Sint64 newposition = SDL_RWseek(rw, databegin + offset, SEEK_SET); + if (newposition == -1) { + return 0; + } + currentposition = newposition; + } + *data = buffer; + int read = SDL_RWread(rw, buffer, 1, length); + if (read == -1) { + return 0; + } + return read; } -unsigned long Stream::GetSome(unsigned long offset, const uint8** data, unsigned long length) +bool Source_SampleStream::LoadWAV(SDL_RWops* rw) { - unsigned long size = length; - switch(sourcetype) { - case SOURCE_SAMPLE: - if (offset >= sample->Length()) { - return 0; - } - if (offset + length > sample->Length()) { - size = sample->Length() - offset; - } - *data = &sample->Data()[offset]; - return size; - break; + Unload(); + if (rw == NULL) { + return false; + } + Source_SampleStream::rw = rw; + Uint32 chunk_id = SDL_ReadLE32(rw); + const Uint32 RIFF = 0x46464952; + if (chunk_id != RIFF) { + log_verbose("Not a WAV file"); + return false; + } + Uint32 chunk_size = SDL_ReadLE32(rw); + Uint32 chunk_format = SDL_ReadLE32(rw); + const Uint32 WAVE = 0x45564157; + if (chunk_format != WAVE) { + log_verbose("Not in WAVE format"); + return false; + } + const Uint32 FMT = 0x20746D66; + Uint32 fmtchunk_size = FindChunk(rw, FMT); + if (!fmtchunk_size) { + log_verbose("Could not find FMT chunk"); + return false; + } + PCMWAVEFORMAT waveformat; + SDL_RWread(rw, &waveformat, sizeof(waveformat), 1); + if (waveformat.wf.wFormatTag != WAVE_FORMAT_PCM) { + log_verbose("Not in proper format"); + return false; + } + format.freq = waveformat.wf.nSamplesPerSec; + switch (waveformat.wBitsPerSample) { + case 8: + format.format = AUDIO_U8; + break; + case 16: + format.format = AUDIO_S16LSB; + break; + default: + log_verbose("Invalid bits per sample"); + return false; + break; + } + format.channels = waveformat.wf.nChannels; + const Uint32 DATA = 0x61746164; + Uint32 datachunk_size = FindChunk(rw, DATA); + if (!datachunk_size) { + log_verbose("Could not find DATA chunk"); + return false; + } + length = datachunk_size; + databegin = SDL_RWtell(rw); + return true; +} + +Uint32 Source_SampleStream::FindChunk(SDL_RWops* rw, Uint32 wanted_id) +{ + Uint32 subchunk_id = SDL_ReadLE32(rw); + Uint32 subchunk_size = SDL_ReadLE32(rw); + if (subchunk_id == wanted_id) { + return subchunk_size; + } + const Uint32 FACT = 0x74636166; + const Uint32 LIST = 0x5453494c; + const Uint32 BEXT = 0x74786562; + const Uint32 JUNK = 0x4B4E554A; + while (subchunk_id == FACT || subchunk_id == LIST || subchunk_id == BEXT || subchunk_id == JUNK) { + SDL_RWseek(rw, subchunk_size, RW_SEEK_CUR); + subchunk_id = SDL_ReadLE32(rw); + subchunk_size = SDL_ReadLE32(rw); + if (subchunk_id == wanted_id) { + return subchunk_size; + } } return 0; } -unsigned long Stream::Length() +void Source_SampleStream::Unload() { - switch(sourcetype) { - case SOURCE_SAMPLE: - return sample->Length(); - break; + if (rw) { + SDL_RWclose(rw); + rw = NULL; } - return 0; -} - -void Stream::SetSource_Sample(Sample& sample) -{ - sourcetype = SOURCE_SAMPLE; - Stream::sample = &sample; -} - -const AudioFormat* Stream::Format() -{ - switch(sourcetype) { - case SOURCE_SAMPLE: - return &sample->format; - break; + length = 0; + if (buffer) { + delete[] buffer; + buffer = 0; } - return 0; + buffersize = 0; } Channel::Channel() @@ -223,7 +344,8 @@ Channel::Channel() SetPan(0.5f); done = true; stopping = false; - stream = 0; + source = 0; + deletesourceondone = false; } Channel::~Channel() @@ -232,11 +354,14 @@ Channel::~Channel() speex_resampler_destroy(resampler); resampler = 0; } + if (deletesourceondone) { + delete source; + } } -void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE) +void Channel::Play(Source& source, int loop = MIXER_LOOP_NONE) { - Channel::stream = &stream; + Channel::source = &source; Channel::loop = loop; offset = 0; done = false; @@ -286,14 +411,25 @@ unsigned long Channel::GetOffset() bool Channel::SetOffset(unsigned long offset) { - if (stream && offset < stream->Length()) { - int samplesize = stream->Format()->channels * stream->Format()->BytesPerSample(); + if (source && offset < source->Length()) { + int samplesize = source->Format().channels * source->Format().BytesPerSample(); Channel::offset = (offset / samplesize) * samplesize; return true; } return false; } +Mixer::Mixer() +{ + effectbuffer = 0; + for (int i = 0; i < countof(css1sources); i++) { + css1sources[i] = 0; + } + for (int i = 0; i < countof(musicsources); i++) { + musicsources[i] = 0; + } +} + void Mixer::Init(const char* device) { Close(); @@ -310,10 +446,15 @@ void Mixer::Init(const char* device) format.channels = have.channels; format.freq = have.freq; const char* filename = get_file_path(PATH_ID_CSS1); - for (int i = 0; i < SOUND_MAXID; i++) { - css1samples[i].LoadCSS1(filename, i); - css1samples[i].Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional - css1streams[i].SetSource_Sample(css1samples[i]); + for (int i = 0; i < countof(css1sources); i++) { + Source_Sample* source_sample = new Source_Sample; + if (source_sample->LoadCSS1(filename, i)) { + source_sample->Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional + css1sources[i] = source_sample; + } else { + css1sources[i] = &source_null; + delete source_sample; + } } effectbuffer = new uint8[(have.samples * format.BytesPerSample() * format.channels)]; SDL_PauseAudioDevice(deviceid, 0); @@ -328,7 +469,22 @@ void Mixer::Close() } Unlock(); SDL_CloseAudioDevice(deviceid); - delete[] effectbuffer; + for (int i = 0; i < countof(css1sources); i++) { + if (css1sources[i] && css1sources[i] != &source_null) { + delete css1sources[i]; + css1sources[i] = 0; + } + } + for (int i = 0; i < countof(musicsources); i++) { + if (musicsources[i] && musicsources[i] != &source_null) { + delete musicsources[i]; + musicsources[i] = 0; + } + } + if (effectbuffer) { + delete[] effectbuffer; + effectbuffer = 0; + } } void Mixer::Lock() @@ -341,13 +497,14 @@ void Mixer::Unlock() SDL_UnlockAudioDevice(deviceid); } -Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone) +Channel* Mixer::Play(Source& source, int loop, bool deleteondone, bool deletesourceondone) { Lock(); - Channel* newchannel = new (std::nothrow) Channel(); + Channel* newchannel = new (std::nothrow) Channel; if (newchannel) { - newchannel->Play(stream, loop); + newchannel->Play(source, loop); newchannel->deleteondone = deleteondone; + newchannel->deletesourceondone = deletesourceondone; newchannel->stopping = false; channels.push_back(newchannel); } @@ -364,13 +521,20 @@ void Mixer::Stop(Channel& channel) bool Mixer::LoadMusic(int pathid) { - if (pathid >= PATH_ID_END) { + if (pathid >= countof(musicsources)) { return false; } - if (!musicsamples[pathid].Loaded()) { + if (!musicsources[pathid]) { const char* filename = get_file_path(pathid); - musicstreams[pathid].SetSource_Sample(musicsamples[pathid]); - return musicsamples[pathid].Load(filename); + Source_Sample* source_sample = new Source_Sample; + if (source_sample->LoadWAV(filename)) { + musicsources[pathid] = source_sample; + return true; + } else { + delete source_sample; + musicsources[pathid] = &source_null; + return false; + } } else { return true; } @@ -394,8 +558,8 @@ void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length) void Mixer::MixChannel(Channel& channel, uint8* data, int length) { - if (channel.stream && !channel.done) { - AudioFormat streamformat = *channel.stream->Format(); + if (channel.source && channel.source->Length() > 0 && !channel.done) { + AudioFormat streamformat = channel.source->Format(); int loaded = 0; SDL_AudioCVT cvt; cvt.len_ratio = 1; @@ -409,9 +573,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) } int samplestoread = (int)((samples - samplesloaded) * rate); int lengthloaded = 0; - if (channel.offset < channel.stream->Length()) { + if (channel.offset < channel.source->Length()) { bool mustconvert = false; - if (MustConvert(*channel.stream)) { + if (MustConvert(*channel.source)) { if (SDL_BuildAudioCVT(&cvt, streamformat.format, streamformat.channels, streamformat.freq, Mixer::format.format, Mixer::format.channels, Mixer::format.freq) == -1) { break; } @@ -420,7 +584,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) const uint8* datastream = 0; int toread = (int)(samplestoread / cvt.len_ratio) * samplesize; - int readfromstream = (channel.stream->GetSome(channel.offset, &datastream, toread)); + int readfromstream = (channel.source->GetSome(channel.offset, &datastream, toread)); if (readfromstream == 0) { break; } @@ -519,7 +683,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) loaded += lengthloaded; - if (channel.loop != 0 && channel.offset >= channel.stream->Length()) { + if (channel.loop != 0 && channel.offset >= channel.source->Length()) { if (channel.loop != -1) { channel.loop--; } @@ -528,7 +692,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) } while(loaded < length && channel.loop != 0 && !channel.stopping); channel.oldvolume = channel.volume; - if (channel.loop == 0 && channel.offset >= channel.stream->Length()) { + if (channel.loop == 0 && channel.offset >= channel.source->Length()) { channel.done = true; } } @@ -574,13 +738,10 @@ void Mixer::EffectFadeU8(uint8* data, int length, int startvolume, int endvolume } } -bool Mixer::MustConvert(Stream& stream) +bool Mixer::MustConvert(Source& source) { - const AudioFormat* streamformat = stream.Format(); - if (!streamformat) { - return false; - } - if (streamformat->format != format.format || streamformat->channels != format.channels || streamformat->freq != format.freq) { + const AudioFormat sourceformat = source.Format(); + if (sourceformat.format != format.format || sourceformat.channels != format.channels || sourceformat.freq != format.freq) { return true; } return false; @@ -609,11 +770,11 @@ void Mixer_Init(const char* device) void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone) { - if (id >= SOUND_MAXID) { + if (id >= countof(gMixer.css1sources)) { return 0; } gMixer.Lock(); - Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0); + Channel* channel = gMixer.Play(*gMixer.css1sources[id], loop, deleteondone != 0, false); if (channel) { channel->SetVolume(volume); channel->SetPan(pan); @@ -664,10 +825,33 @@ int Mixer_Channel_SetOffset(void* channel, unsigned long offset) return ((Channel*)channel)->SetOffset(offset); } -void* Mixer_Play_Music(int pathid) +void* Mixer_Play_Music(int pathid, int streaming) { - if (gMixer.LoadMusic(pathid)) { - return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false); + if (streaming) { + const char* filename = get_file_path(pathid); + + utf8 utf8filename[512]; + win1252_to_utf8(utf8filename, filename, sizeof(utf8filename)); + + SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb"); + if (rw == NULL) { + return 0; + } + Source_SampleStream* source_samplestream = new Source_SampleStream; + if (source_samplestream->LoadWAV(rw)) { + Channel* channel = gMixer.Play(*source_samplestream, MIXER_LOOP_INFINITE, false, true); + if (!channel) { + delete source_samplestream; + } + return channel; + } else { + delete source_samplestream; + return 0; + } + } else { + if (gMixer.LoadMusic(pathid)) { + return gMixer.Play(*gMixer.musicsources[pathid], MIXER_LOOP_INFINITE, false, false); + } } return 0; } \ No newline at end of file diff --git a/src/audio/mixer.h b/src/audio/mixer.h index 6920986e92..e62dd3cad0 100644 --- a/src/audio/mixer.h +++ b/src/audio/mixer.h @@ -43,45 +43,73 @@ struct AudioFormat { int channels; }; -class Sample +class Source { public: - Sample(); - ~Sample(); - bool Load(const char* filename); - bool LoadCSS1(const char* filename, unsigned int offset); - void Unload(); - bool Loaded(); - bool Convert(AudioFormat format); - const uint8* Data(); - unsigned long Length(); - - friend class Stream; - -private: - AudioFormat format; - uint8* data; - unsigned long length; - bool issdlwav; -}; - -class Stream -{ -public: - Stream(); + virtual ~Source(); unsigned long GetSome(unsigned long offset, const uint8** data, unsigned long length); unsigned long Length(); - void SetSource_Sample(Sample& sample); - const AudioFormat* Format(); + const AudioFormat& Format(); friend class Mixer; +protected: + virtual unsigned long Read(unsigned long offset, const uint8** data, unsigned long length) = 0; + + AudioFormat format; + unsigned long length; +}; + +class Source_Null : public Source +{ +public: + Source_Null(); + +protected: + unsigned long Read(unsigned long offset, const uint8** data, unsigned long length); +}; + +class Source_Sample : public Source +{ +public: + Source_Sample(); + ~Source_Sample(); + bool LoadWAV(const char* filename); + bool LoadCSS1(const char* filename, unsigned int offset); + + friend class Mixer; + +protected: + bool Convert(AudioFormat format); + private: - enum { - SOURCE_NONE = 0, - SOURCE_SAMPLE - } sourcetype; - Sample* sample; + void Unload(); + + uint8* data; + bool issdlwav; + +protected: + unsigned long Read(unsigned long offset, const uint8** data, unsigned long length); +}; + +class Source_SampleStream : public Source +{ +public: + Source_SampleStream(); + ~Source_SampleStream(); + bool LoadWAV(SDL_RWops* rw); + +private: + Uint32 FindChunk(SDL_RWops* rw, Uint32 wanted_id); + void Unload(); + + SDL_RWops* rw; + Uint64 databegin; + uint8* buffer; + unsigned long buffersize; + +protected: + unsigned long Read(unsigned long offset, const uint8** data, unsigned long length); }; class Channel @@ -89,7 +117,7 @@ class Channel public: Channel(); ~Channel(); - void Play(Stream& stream, int loop); + void Play(Source& source, int loop); void SetRate(double rate); void SetVolume(int volume); void SetPan(float pan); @@ -108,25 +136,27 @@ private: float pan; bool done; bool deleteondone; + bool deletesourceondone; bool stopping; int oldvolume; SpeexResamplerState* resampler; - Stream* stream; + Source* source; }; class Mixer { public: + Mixer(); void Init(const char* device); void Close(); void Lock(); void Unlock(); - Channel* Play(Stream& stream, int loop, bool deleteondone); + Channel* Play(Source& source, int loop, bool deleteondone, bool deletesourceondone); void Stop(Channel& channel); bool LoadMusic(int pathid); - Stream css1streams[SOUND_MAXID]; - Stream musicstreams[PATH_ID_END]; + Source* css1sources[SOUND_MAXID]; + Source* musicsources[PATH_ID_END]; private: static void SDLCALL Callback(void* arg, uint8* data, int length); @@ -135,14 +165,13 @@ private: void EffectPanU8(Channel& channel, uint8* data, int length); void EffectFadeS16(sint16* data, int length, int startvolume, int endvolume); void EffectFadeU8(uint8* data, int length, int startvolume, int endvolume); - bool MustConvert(Stream& stream); + bool MustConvert(Source& source); bool Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout); SDL_AudioDeviceID deviceid; AudioFormat format; uint8* effectbuffer; - Sample css1samples[SOUND_MAXID]; - Sample musicsamples[PATH_ID_END]; std::list channels; + Source_Null source_null; }; extern "C" @@ -158,7 +187,7 @@ void Mixer_Channel_Rate(void* channel, double rate); int Mixer_Channel_IsPlaying(void* channel); unsigned long Mixer_Channel_GetOffset(void* channel); int Mixer_Channel_SetOffset(void* channel, unsigned long offset); -void* Mixer_Play_Music(int pathid); +void* Mixer_Play_Music(int pathid, int streaming); static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); }; static float DStoMixerPan(int pan) { return (((float)pan + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; }; diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 302e2c8ac2..eca3eac66f 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -192,6 +192,8 @@ enum { STR_LOCATE_SUBJECT_TIP = 1027, STR_OFF_EDGE_OF_MAP = 1028, + STR_CAN_ONLY_BUILD_THIS_ON_LAND = 1034, + STR_LOAD_GAME_DIALOG_TITLE = 1036, STR_LOAD_LANDSCAPE_DIALOG_TITLE = 1037, STR_CONVERT_SAVED_GAME_TO_SCENARIO_1038 = 1038, @@ -378,6 +380,7 @@ enum { STR_SHOPS_STALLS_TIP = 1228, STR_ROTATE_OBJECTS_90 = 1327, + STR_LEVEL_LAND_REQUIRED = 1328, STR_LAUNCH_SPEED = 1329, STR_LAUNCH_SPEED_TIP = 1330, diff --git a/src/peep/peep.c b/src/peep/peep.c index 03ff279fba..779273b61a 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -4577,7 +4577,7 @@ void peep_update_crowd_noise() // Load and play crowd noise #ifdef USE_MIXER if (!gCrowdSoundChannel) { - gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2); + gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2, false); } if (gCrowdSoundChannel) { Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume)); diff --git a/src/ride/ride.c b/src/ride/ride.c index 9297e89837..a703dbf104 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -2662,7 +2662,7 @@ void ride_music_update_final() rct_ride_music_info* ride_music_info = &RCT2_GLOBAL(0x009AF1C8, rct_ride_music_info*)[ride_music_params->tuneid]; #ifdef USE_MIXER rct_ride_music* ride_music = &gRideMusicList[ebx]; - ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid); + ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid, true); if (ride_music->sound_channel) { ride_music->volume = ride_music_params->volume; ride_music->pan = ride_music_params->pan; @@ -2678,7 +2678,7 @@ void ride_music_update_final() } Mixer_Channel_SetOffset(ride_music->sound_channel, offset); } else { - RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0; + //RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0; } #else const char* filename = get_file_path(ride_music_info->pathid); diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 887915cb48..b6c111e634 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1416,11 +1416,11 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w int cost; { - int esi = 0, eax = grid_x, ecx = grid_y, edx = grid_z; - game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); + int esi = 0, eax = grid_x, ecx = grid_y, edx = parameter_2, ebx = (parameter_1 & 0xFF00) | 1; + cost = game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); } - if (ebx == MONEY32_UNDEFINED)return; + if (cost == MONEY32_UNDEFINED)return; sound_play_panned(SOUND_PLACE_ITEM, 0x8001, RCT2_GLOBAL(0x009DEA5E, uint16), RCT2_GLOBAL(0x009DEA60, uint16), RCT2_GLOBAL(0x009DEA62, uint16)); diff --git a/src/world/footpath.h b/src/world/footpath.h index 86574919b5..3745ae05d2 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -48,5 +48,6 @@ void footpath_provisional_remove(); void footpath_provisional_update(); void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); +void sub_673883(int x, int y, int z); #endif diff --git a/src/world/map.c b/src/world/map.c index a98612d2e6..13f898ce79 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -28,6 +28,7 @@ #include "../scenario.h" #include "banner.h" #include "climate.h" +#include "footpath.h" #include "map.h" #include "map_animation.h" #include "park.h" @@ -905,7 +906,7 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* return; } if(*ebx & GAME_COMMAND_FLAG_APPLY){ - rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.type]; map_element->properties.fence.item[1] &= 0xE0; map_element->properties.fence.item[1] |= color1; map_element->flags &= 0x9F; @@ -1655,7 +1656,7 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, return; } } - rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.type]; if(scenery_entry->wall.var_0D != 0xFF){ rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; if(banner->type != BANNER_NULL){ diff --git a/src/world/scenery.c b/src/world/scenery.c index eeb1cb68c3..3a05927927 100644 --- a/src/world/scenery.c +++ b/src/world/scenery.c @@ -178,7 +178,7 @@ void scenery_remove_ghost_tool_placement(){ 105 | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8), y, z, - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0); } @@ -191,7 +191,7 @@ void scenery_remove_ghost_tool_placement(){ 105, y, z | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8), - GAME_COMMAND_51, + GAME_COMMAND_REMOVE_BANNER, 0, 0); } diff --git a/src/world/scenery.h b/src/world/scenery.h index 7b4765f1e7..3d2e6a98e9 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -56,6 +56,12 @@ typedef enum { SMALL_SCENERY_FLAG18 = (1 << 17), // 0x20000 SMALL_SCENERY_FLAG19 = (1 << 18), // 0x40000 SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000 + SMALL_SCENERY_FLAG20 = (1 << 20), // 0x100000 + SMALL_SCENERY_FLAG21 = (1 << 21), // 0x200000 + SMALL_SCENERY_FLAG22 = (1 << 22), // 0x400000 + SMALL_SCENERY_FLAG23 = (1 << 23), // 0x800000 + SMALL_SCENERY_FLAG24 = (1 << 24), // 0x1000000 + SMALL_SCENERY_FLAG25 = (1 << 25), // 0x2000000 } SMALL_SCENERY_FLAGS; typedef struct {