From fe799f03a528dee75abc8b83208c6c1dc15d9832 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Mon, 30 Mar 2015 17:28:36 +0200 Subject: [PATCH 1/9] Added footpath_bridge_get_info_from_pos --- src/interface/viewport.c | 26 ++++++++-------- src/interface/viewport.h | 2 +- src/interface/viewport_interaction.c | 4 +-- src/windows/footpath.c | 8 ++--- src/windows/guest.c | 2 +- src/windows/ride.c | 2 +- src/windows/staff.c | 2 +- src/windows/viewport.c | 2 +- src/world/footpath.c | 44 ++++++++++++++++++++++++++-- src/world/footpath.h | 2 +- 10 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index b9ec084b69..151cfcca78 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -1676,28 +1676,29 @@ void viewport_set_visibility(uint8 mode) * y: cx * z: bl * mapElement: edx + * viewport: edi */ -void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement) +void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement, rct_viewport **viewport) { RCT2_GLOBAL(0x9AC154, uint16_t) = flags & 0xFFFF; RCT2_GLOBAL(0x9AC148, uint8_t) = 0; rct_window* window = window_find_from_point(screenX, screenY); if (window != NULL && window->viewport != NULL) { - rct_viewport* viewport = window->viewport; + rct_viewport* myviewport = window->viewport; RCT2_GLOBAL(0x9AC138 + 4, int16_t) = screenX; RCT2_GLOBAL(0x9AC138 + 6, int16_t) = screenY; - screenX -= (int)viewport->x; - screenY -= (int)viewport->y; - if (screenX >= 0 && screenX < (int)viewport->width && screenY >= 0 && screenY < (int)viewport->height) + screenX -= (int)myviewport->x; + screenY -= (int)myviewport->y; + if (screenX >= 0 && screenX < (int)myviewport->width && screenY >= 0 && screenY < (int)myviewport->height) { - screenX <<= viewport->zoom; - screenY <<= viewport->zoom; - screenX += (int)viewport->view_x; - screenY += (int)viewport->view_y; - RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16_t) = viewport->zoom; - screenX &= (0xFFFF << viewport->zoom) & 0xFFFF; - screenY &= (0xFFFF << viewport->zoom) & 0xFFFF; + screenX <<= myviewport->zoom; + screenY <<= myviewport->zoom; + screenX += (int)myviewport->view_x; + screenY += (int)myviewport->view_y; + RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_ZOOM, uint16_t) = myviewport->zoom; + screenX &= (0xFFFF << myviewport->zoom) & 0xFFFF; + screenY &= (0xFFFF << myviewport->zoom) & 0xFFFF; RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_X, int16_t) = screenX; RCT2_GLOBAL(RCT2_ADDRESS_VIEWPORT_PAINT_Y, int16_t) = screenY; rct_drawpixelinfo* dpi = RCT2_ADDRESS(RCT2_ADDRESS_VIEWPORT_DPI, rct_drawpixelinfo); @@ -1713,6 +1714,7 @@ void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, i RCT2_CALLPROC_X(0x688217, 0, 0, 0, 0, 0, 0, 0); RCT2_CALLPROC_X(0x68862C, 0, 0, 0, 0, 0, 0, 0); } + if (viewport != NULL) *viewport = myviewport; } if (z != NULL) *z = RCT2_GLOBAL(0x9AC148, uint8_t); if (x != NULL) *x = (int)RCT2_GLOBAL(0x9AC14C, int16_t); diff --git a/src/interface/viewport.h b/src/interface/viewport.h index 27eae985d7..2712cee4ce 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -94,7 +94,7 @@ void show_construction_rights(); void hide_construction_rights(); void viewport_set_visibility(uint8 mode); -void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement); +void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement, rct_viewport **viewport); int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info *info); int viewport_interaction_left_over(int x, int y); diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index d20a8204c4..9a33a1821d 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -58,7 +58,7 @@ int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info * if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) && s6Info->var_000 != 6) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; - get_map_coordinates_from_pos(x, y, 0xFF79, &info->x, &info->y, &info->type, &info->mapElement); + get_map_coordinates_from_pos(x, y, 0xFF79, &info->x, &info->y, &info->type, &info->mapElement, NULL); mapElement = info->mapElement; sprite = (rct_sprite*)mapElement; @@ -178,7 +178,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) && s6Info->var_000 != 6) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; - get_map_coordinates_from_pos(x, y, 9, &info->x, &info->y, &info->type, &info->mapElement); + get_map_coordinates_from_pos(x, y, 9, &info->x, &info->y, &info->type, &info->mapElement, NULL); mapElement = info->mapElement; sprite = (rct_sprite*)mapElement; diff --git a/src/windows/footpath.c b/src/windows/footpath.c index d2de3966f0..da1c7b4437 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -673,7 +673,7 @@ static void window_footpath_set_provisional_path_at_point(int x, int y) map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 2); - get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement); + get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement, NULL); if (z == 0) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); @@ -716,7 +716,7 @@ static void window_footpath_set_selection_start_bridge_at_point(int screenX, int map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0) & ~(1 << 2); - sub_68A0C9(screenX, screenY, &x, &y, &direction, &mapElement); + footpath_bridge_get_info_from_pos(screenX, screenY, &x, &y, &direction, &mapElement); if (x == 0x8000) return; @@ -760,7 +760,7 @@ static void window_footpath_place_path_at_point(int x, int y) footpath_provisional_update(); - get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement); + get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement, NULL); if (z == 0) return; @@ -794,7 +794,7 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY) int x, y, z, direction; rct_map_element *mapElement; - sub_68A0C9(screenX, screenY, &x, &y, &direction, &mapElement); + footpath_bridge_get_info_from_pos(screenX, screenY, &x, &y, &direction, &mapElement); if (x == 0x8000) return; diff --git a/src/windows/guest.c b/src/windows/guest.c index d816d80bc9..75c06c0659 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -1160,7 +1160,7 @@ void window_guest_overview_tool_update(){ RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; int ebx; - get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &ebx, NULL); + get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &ebx, NULL, NULL); if (ebx == 0) return; diff --git a/src/windows/ride.c b/src/windows/ride.c index 5b16b8ea77..a1e57a2d88 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -3542,7 +3542,7 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y) int z; - get_map_coordinates_from_pos(x, y, -5, &x, &y, &z, &mapElement); + get_map_coordinates_from_pos(x, y, -5, &x, &y, &z, &mapElement, NULL); // Get map coordinates from point /*int eax, ebx, ecx, edx, esi, edi, ebp; eax = x; diff --git a/src/windows/staff.c b/src/windows/staff.c index 4c9f71d0b8..f9c1095ed5 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -1086,7 +1086,7 @@ void window_staff_overview_tool_update(){ RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; int z; - get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &z, NULL); + get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &z, NULL, NULL); if (z == 0) return; diff --git a/src/windows/viewport.c b/src/windows/viewport.c index 924926ad1b..9fb7fcf6cc 100644 --- a/src/windows/viewport.c +++ b/src/windows/viewport.c @@ -176,7 +176,7 @@ static void window_viewport_mouseup() case WIDX_LOCATE: mainWindow = window_get_main(); if (mainWindow != NULL) { - get_map_coordinates_from_pos(w->x + (w->width / 2), w->y + (w->height / 2), 0, &x, &y, NULL, NULL); + get_map_coordinates_from_pos(w->x + (w->width / 2), w->y + (w->height / 2), 0, &x, &y, NULL, NULL, NULL); window_scroll_to_location(mainWindow, x, y, map_element_height(x, y)); } break; diff --git a/src/world/footpath.c b/src/world/footpath.c index 4a6ce75530..4ebe8b3aa9 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "../game.h" #include "../localisation/localisation.h" +#include "../util/util.h" #include "footpath.h" #include "map.h" @@ -476,13 +477,52 @@ void footpath_provisional_update() /** * * rct2: 0x0068A0C9 + * screenX: eax + * screenY: ebx + * x: ax + * y: bx + * direction: cl + * mapElement: edx */ -void sub_68A0C9(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) { + // First check if we point at an entrance or exit. In that case, we would want the path coming from the entrance/exit. + int z; + rct_viewport *viewport; + get_map_coordinates_from_pos(screenX, screenY, 0xFFFB, x, y, &z, mapElement, &viewport); + if (z == 3 + && viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL) + && map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { + int ebp = (*mapElement)->properties.entrance.type << 4; + int bl = (*mapElement)->properties.entrance.index & 0xF; + if (RCT2_GLOBAL(0x0097B974 + ebp + bl, uint16) & 0xF) { + int bx = bitscanforward(RCT2_GLOBAL(0x0097B974 + ebp + bl, uint16)); + bx += (*mapElement)->type; + bx &= 3; + if (direction != NULL) *direction = bx; + return; + } + } + + get_map_coordinates_from_pos(screenX, screenY, 0xFFDA, x, y, &z, mapElement, &viewport); + if (z == 3 && map_element_get_type(*mapElement) == MAP_ELEMENT_TYPE_ENTRANCE) { + int ebp = (*mapElement)->properties.entrance.type << 4; + int bl = (*mapElement)->properties.entrance.index & 0xF; // Seems to be always 0? + // The table at 0x0097B974 is only 48 bytes big + if (RCT2_GLOBAL(0x0097B974 + ebp + bl, uint16) & 0xF) { + int bx = bitscanforward(RCT2_GLOBAL(0x0097B974 + ebp + bl, uint16)); + bx += (*mapElement)->type; // First two bits seem to contain the direction of entrance/exit + bx &= 3; + if (direction != NULL) *direction = bx; + return; + } + } + + // We point at something else int eax, ebx, ecx, edx, esi, edi, ebp; eax = screenX; ebx = screenY; - RCT2_CALLFUNC_X(0x0068A0C9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + RCT2_CALLFUNC_X(0x00689726, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); if (x != NULL) *x = *((uint16*)&eax); if (y != NULL) *y = *((uint16*)&ebx); if (direction != NULL) *direction = *((uint8*)&ecx); diff --git a/src/world/footpath.h b/src/world/footpath.h index 957c0c7f93..e1df740b72 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -46,6 +46,6 @@ void footpath_remove(int x, int y, int z, int flags); money32 footpath_provisional_set(int type, int x, int y, int z, int slope); void footpath_provisional_remove(); void footpath_provisional_update(); -void sub_68A0C9(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); #endif From 6cb205c9cce043949843c6fa16d1ad540a544759 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Wed, 1 Apr 2015 01:46:20 +0200 Subject: [PATCH 2/9] Added footpath_get_coordinates_from_pos --- src/windows/cheats.c | 21 +++--- src/windows/guest.c | 28 ++++---- src/windows/staff.c | 13 ++-- src/world/footpath.c | 154 ++++++++++++++++++++++++++++++++++++++++--- src/world/footpath.h | 1 + 5 files changed, 178 insertions(+), 39 deletions(-) diff --git a/src/windows/cheats.c b/src/windows/cheats.c index bc66a4d7ed..1c8a1a2abe 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -29,6 +29,7 @@ #include "../scenario.h" #include "../sprites.h" #include "../world/climate.h" +#include "../world/footpath.h" #include "../world/park.h" #include "../world/sprite.h" @@ -771,17 +772,16 @@ static void window_cheats_misc_tool_update() map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); - int temp_y = y + 16; - int eax = x, ecx = 0, edx = widgetIndex, edi = 0, esi = (int)w, ebp = 0; - RCT2_CALLFUNC_X(0x689726, &eax, &temp_y, &ecx, &edx, &esi, &edi, &ebp); - if (eax != 0x8000){ + int map_x, map_y; + footpath_get_coordinates_from_pos(x, y + 16, &map_x, &map_y, NULL, NULL); + if (map_x != 0x8000){ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = eax; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = eax; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = temp_y; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = temp_y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = map_x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = map_x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = map_y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = map_y; map_invalidate_selection_rect(); } @@ -798,9 +798,8 @@ static void window_cheats_misc_tool_down() if (widgetIndex != WIDX_ZERO_CLEARANCE) return; - int dest_x = x, dest_y = y, ecx = 0, edx = widgetIndex, edi = 0, esi = (int)w, ebp = 0; - dest_y += 16; - RCT2_CALLFUNC_X(0x689726, &dest_x, &dest_y, &ecx, &edx, &esi, &edi, &ebp); + int dest_x, dest_y; + footpath_get_coordinates_from_pos(x, y + 16, &dest_x, &dest_y, NULL, NULL); if (dest_x == 0x8000)return; diff --git a/src/windows/guest.c b/src/windows/guest.c index 75c06c0659..91436c8e74 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -32,6 +32,7 @@ #include "../interface/viewport.h" #include "../interface/widget.h" #include "../interface/window.h" +#include "../world/footpath.h" #include "dropdown.h" #include "error.h" @@ -1143,17 +1144,16 @@ void window_guest_overview_tool_update(){ map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); - int temp_y = y + 16; - int eax = x, ecx = 0, edx = widgetIndex, edi = 0, esi = (int)w, ebp = 0; - RCT2_CALLFUNC_X(0x689726, &eax, &temp_y, &ecx, &edx, &esi, &edi, &ebp); - if (eax != 0x8000){ + int map_x, map_y; + footpath_get_coordinates_from_pos(x, y + 16, &map_x, &map_y, NULL, NULL); + if (map_x != 0x8000){ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = eax; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = eax; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = temp_y; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = temp_y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, uint16) = map_x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = map_x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, uint16) = map_y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = map_y; map_invalidate_selection_rect(); } @@ -1176,8 +1176,8 @@ void window_guest_overview_tool_update(){ ebx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22]; ebx += w->var_492 >> 2; - ebp = peep->tshirt_colour << 19; - ecx = peep->trousers_colour << 24; + int ebp = peep->tshirt_colour << 19; + int ecx = peep->trousers_colour << 24; ebx |= ebp | ecx | 0xA0000000; RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) = ebx; @@ -1193,9 +1193,9 @@ void window_guest_overview_tool_down(){ if (widgetIndex != WIDX_PICKUP) return; - int dest_x = x, dest_y = y, ecx = 0, edx = widgetIndex, edi = 0, esi = (int)w, ebp = 0; - dest_y += 16; - RCT2_CALLFUNC_X(0x689726, &dest_x, &dest_y, &ecx, &edx, &esi, &edi, &ebp); + int dest_x, dest_y; + rct_map_element *mapElement; + footpath_get_coordinates_from_pos(x, y + 16, &dest_x, &dest_y, NULL, &mapElement); if (dest_x == 0x8000)return; @@ -1207,7 +1207,7 @@ void window_guest_overview_tool_down(){ int tile_y = dest_y & 0xFFE0; int tile_x = dest_x & 0xFFE0; - int dest_z = ((uint8*)edx)[2] * 8 + 16; + int dest_z = mapElement->base_height * 8 + 16; if (!map_is_location_owned(tile_x, tile_y, dest_z)){ window_error_open(0x785,-1); diff --git a/src/windows/staff.c b/src/windows/staff.c index f9c1095ed5..206e91d533 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -27,6 +27,7 @@ #include "../peep/peep.h" #include "../peep/staff.h" #include "../sprites.h" +#include "../world/footpath.h" #include "../world/sprite.h" #include "../world/scenery.h" #include "dropdown.h" @@ -1116,9 +1117,9 @@ void window_staff_overview_tool_down(){ if (widgetIndex == WIDX_PICKUP){ - int dest_x = x, dest_y = y, ecx = 0, edx = widgetIndex, edi = 0, esi = (int)w, ebp = 0; - dest_y += 16; - RCT2_CALLFUNC_X(0x689726, &dest_x, &dest_y, &ecx, &edx, &esi, &edi, &ebp); + int dest_x, dest_y; + rct_map_element *mapElement; + footpath_get_coordinates_from_pos(x, y + 16, &dest_x, &dest_y, NULL, &mapElement); if (dest_x == 0x8000)return; @@ -1130,7 +1131,7 @@ void window_staff_overview_tool_down(){ int tile_y = dest_y & 0xFFE0; int tile_x = dest_x & 0xFFE0; - int dest_z = ((uint8*)edx)[2] * 8 + 16; + int dest_z = mapElement->base_height * 8 + 16; if (!map_is_location_owned(tile_x, tile_y, dest_z)){ window_error_open(0x785, -1); @@ -1166,8 +1167,8 @@ void window_staff_overview_tool_down(){ RCT2_GLOBAL(0x9DE550, sint32) = -1; } else if (widgetIndex == WIDX_PATROL){ - int dest_x = x, dest_y = y, ecx = 0, edx = widgetIndex, edi = 0, esi = (int)w, ebp = 0; - RCT2_CALLFUNC_X(0x689726, &dest_x, &dest_y, &ecx, &edx, &esi, &edi, &ebp); + int dest_x, dest_y; + footpath_get_coordinates_from_pos(x, y, &dest_x, &dest_y, NULL, NULL); if (dest_x == 0x8000)return; diff --git a/src/world/footpath.c b/src/world/footpath.c index 4ebe8b3aa9..42dd50d639 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -474,6 +474,151 @@ void footpath_provisional_update() footpath_provisional_remove(); } +void sub_689726_helper(uint16 *ax, uint16 *bx, uint16 *cx, uint16 *dx, uint32 rotation) +{ + *ax = ((sint16)*ax >> 1); // Arithmetic shift! + *dx = *ax; + switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) { + case 0: + *ax = -*ax; + *ax += *bx; + *bx += *dx; + *ax += *cx; + *bx += *cx; + break; + case 1: + *ax = -*ax; + *ax -= *bx; + *bx -= *dx; + *ax -= *cx; + *bx += *cx; + break; + case 2: + *ax -= *bx; + *bx = -*bx; + *bx -= *dx; + *ax -= *cx; + *bx -= *cx; + break; + case 3: + *ax += *bx; + *bx = -*bx; + *bx += *dx; + *ax += *cx; + *bx -= *cx; + break; + } +} + +/** + * Determines the location of the footpath at which we point with the cursor. If no footpath is underneath the cursor, + * then return the location of the ground tile. Besides the location it also computes the direction of the yellow arrow + * when we are going to build a footpath bridge/tunnel. + * rct2: 0x00689726 + * In: + * screenX: eax + * screenY: ebx + * Out: + * x: ax + * y: bx + * direction: ecx + * mapElement: edx + */ +void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement) +{ + int z; + rct_map_element *myMapElement; + rct_viewport *viewport; + get_map_coordinates_from_pos(screenX, screenY, 0xFFDF, x, y, &z, &myMapElement, &viewport); + if (z != 6 || !(viewport->flags & (VIEWPORT_FLAG_UNDERGROUND_INSIDE | VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_VERTICAL))) { + get_map_coordinates_from_pos(screenX, screenY, 0xFFDE, x, y, &z, &myMapElement, &viewport); + if (z == 0) { + if (x != NULL) *x = 0x8000; + return; + } + } + + RCT2_GLOBAL(0x00F1AD3E, uint8) = z; + RCT2_GLOBAL(0x00F1AD30, rct_map_element*) = myMapElement; + + if (z == 6) { + // mapElement appears to be a footpath + z = myMapElement->base_height * 8; + if (myMapElement->properties.path.type & 0x4) + z += 8; + } + + RCT2_GLOBAL(0x00F1AD3C, uint16) = z; + RCT2_GLOBAL(0x00F1AD34, uint16) = *x; + RCT2_GLOBAL(0x00F1AD36, uint16) = *y; + RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 0x1F; + RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 0x1F; + + uint16 dx; + if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 6) { + dx = map_element_height(*x + 0x10, *y + 0x10); + } else { + dx = z; + } + + uint16 ax = screenX, bx = screenY; + ax -= viewport->x; + bx -= viewport->y; + ax <<= viewport->zoom; + bx <<= viewport->zoom; + ax += viewport->view_x; + bx += viewport->view_y; + + uint16 cx = dx; + uint16 old_ax = ax, old_bx = bx; + for (int i = 0; i < 4; i++) { + ax = old_ax; + bx = old_bx; + sub_689726_helper(&ax, &bx, &cx, &dx, 0); + cx = bx; + ax = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), ax, RCT2_GLOBAL(0x00F1AD38, uint16)); + cx = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), cx, RCT2_GLOBAL(0x00F1AD3A, uint16)); + if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 6) { + dx = map_element_height(ax + 0x10, bx + 0x10); + } else { + dx = RCT2_GLOBAL(0x00F1AD3C, uint16); + } + cx = dx; + } + ax = old_ax; + bx = old_bx; + sub_689726_helper(&ax, &bx, &cx, &dx, 0); + ax = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), ax, RCT2_GLOBAL(0x00F1AD38, uint16)); + bx = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), bx, RCT2_GLOBAL(0x00F1AD3A, uint16)); + + // Determine to which edge the cursor is closest + uint16 bp; + uint32 ecx; + dx = ax; + bp = bx; + ax &= 0xFFE0; + bx &= 0xFFE0; + dx &= 0x1F; + bp &= 0x1F; + if (dx < bp) { + dx += bp; + ecx = 0; + if (dx >= 0x20) + ecx++; + } else { + dx += bp; + ecx = 3; + if (dx >= 0x20) + ecx--; + } + + if (x != NULL) *x = ax; + if (y != NULL) *y = bx; + if (direction != NULL) *direction = ecx; + if (mapElement != NULL) *mapElement = myMapElement; + // We should get the rct_map_element from 0x00F1AD30 here, but we set it earlier to our myMapElement anyway. +} + /** * * rct2: 0x0068A0C9 @@ -519,14 +664,7 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, } // We point at something else - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = screenX; - ebx = screenY; - RCT2_CALLFUNC_X(0x00689726, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - if (x != NULL) *x = *((uint16*)&eax); - if (y != NULL) *y = *((uint16*)&ebx); - if (direction != NULL) *direction = *((uint8*)&ecx); - if (mapElement != NULL) *mapElement = (rct_map_element*)edx; + footpath_get_coordinates_from_pos(screenX, screenY, x, y, direction, mapElement); } /** diff --git a/src/world/footpath.h b/src/world/footpath.h index e1df740b72..86574919b5 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -46,6 +46,7 @@ void footpath_remove(int x, int y, int z, int flags); money32 footpath_provisional_set(int type, int x, int y, int z, int slope); 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); #endif From 585f85c725a8fe97e966abe6c45126057b6b5d99 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Thu, 2 Apr 2015 16:38:40 +0200 Subject: [PATCH 3/9] Improved footpath_get_coordinates_from_pos a bit --- src/world/footpath.c | 111 +++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 73 deletions(-) diff --git a/src/world/footpath.c b/src/world/footpath.c index 42dd50d639..edcb8d1de4 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -474,38 +474,24 @@ void footpath_provisional_update() footpath_provisional_remove(); } -void sub_689726_helper(uint16 *ax, uint16 *bx, uint16 *cx, uint16 *dx, uint32 rotation) +void sub_689726_helper(int x, int y, int z, int *out_x, int *out_y) { - *ax = ((sint16)*ax >> 1); // Arithmetic shift! - *dx = *ax; switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) { case 0: - *ax = -*ax; - *ax += *bx; - *bx += *dx; - *ax += *cx; - *bx += *cx; + *out_x = -x / 2 + y + z; + *out_y = x / 2 + y + z; break; case 1: - *ax = -*ax; - *ax -= *bx; - *bx -= *dx; - *ax -= *cx; - *bx += *cx; + *out_x = -x / 2 - y - z; + *out_y = -x / 2 + y + z; break; case 2: - *ax -= *bx; - *bx = -*bx; - *bx -= *dx; - *ax -= *cx; - *bx -= *cx; + *out_x = x / 2 - y - z; + *out_y = -x / 2 - y - z; break; case 3: - *ax += *bx; - *bx = -*bx; - *bx += *dx; - *ax += *cx; - *bx -= *cx; + *out_x = x / 2 + y + z; + *out_y = x / 2 - y - z; break; } } @@ -554,67 +540,46 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 0x1F; RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 0x1F; - uint16 dx; - if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 6) { - dx = map_element_height(*x + 0x10, *y + 0x10); - } else { - dx = z; - } + *x += 0x10; + *y += 0x10; - uint16 ax = screenX, bx = screenY; - ax -= viewport->x; - bx -= viewport->y; - ax <<= viewport->zoom; - bx <<= viewport->zoom; - ax += viewport->view_x; - bx += viewport->view_y; + int start_x, start_y; + start_x = ((screenX - viewport->x) << viewport->zoom) + viewport->view_x; + start_y = ((screenY - viewport->y) << viewport->zoom) + viewport->view_y; - uint16 cx = dx; - uint16 old_ax = ax, old_bx = bx; - for (int i = 0; i < 4; i++) { - ax = old_ax; - bx = old_bx; - sub_689726_helper(&ax, &bx, &cx, &dx, 0); - cx = bx; - ax = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), ax, RCT2_GLOBAL(0x00F1AD38, uint16)); - cx = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), cx, RCT2_GLOBAL(0x00F1AD3A, uint16)); + int out_x = *x, out_y = *y; + + for (int i = 0; i < 5; i++) { if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 6) { - dx = map_element_height(ax + 0x10, bx + 0x10); + z = map_element_height(out_x, out_y); } else { - dx = RCT2_GLOBAL(0x00F1AD3C, uint16); + z = RCT2_GLOBAL(0x00F1AD3C, uint16); } - cx = dx; + sub_689726_helper(start_x, start_y, z, &out_x, &out_y); + out_x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), out_x, RCT2_GLOBAL(0x00F1AD38, uint16)); + out_y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), out_y, RCT2_GLOBAL(0x00F1AD3A, uint16)); } - ax = old_ax; - bx = old_bx; - sub_689726_helper(&ax, &bx, &cx, &dx, 0); - ax = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), ax, RCT2_GLOBAL(0x00F1AD38, uint16)); - bx = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), bx, RCT2_GLOBAL(0x00F1AD3A, uint16)); // Determine to which edge the cursor is closest - uint16 bp; - uint32 ecx; - dx = ax; - bp = bx; - ax &= 0xFFE0; - bx &= 0xFFE0; - dx &= 0x1F; - bp &= 0x1F; - if (dx < bp) { - dx += bp; - ecx = 0; - if (dx >= 0x20) - ecx++; + uint32 myDirection; + int mod_x = out_x & 0x1F, mod_y = out_y & 0x1F; + if (mod_x < mod_y) { + if (mod_x + mod_y < 0x20) { + myDirection = 0; + } else { + myDirection = 1; + } } else { - dx += bp; - ecx = 3; - if (dx >= 0x20) - ecx--; + if (mod_x + mod_y < 0x20) { + myDirection = 3; + } else { + myDirection = 2; + } } - if (x != NULL) *x = ax; - if (y != NULL) *y = bx; - if (direction != NULL) *direction = ecx; + if (x != NULL) *x = out_x & 0xFFE0; + if (y != NULL) *y = out_y & 0xFFE0; + if (direction != NULL) *direction = myDirection; if (mapElement != NULL) *mapElement = myMapElement; // We should get the rct_map_element from 0x00F1AD30 here, but we set it earlier to our myMapElement anyway. } From 8e11c6528dafd86b59e8a3d5448760c46526a0e9 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Thu, 2 Apr 2015 17:19:21 +0200 Subject: [PATCH 4/9] Coding style --- src/world/footpath.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/world/footpath.c b/src/world/footpath.c index edcb8d1de4..ebb5c24dbd 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -530,18 +530,18 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, if (z == 6) { // mapElement appears to be a footpath z = myMapElement->base_height * 8; - if (myMapElement->properties.path.type & 0x4) + if (myMapElement->properties.path.type & (1 << 2)) z += 8; } RCT2_GLOBAL(0x00F1AD3C, uint16) = z; RCT2_GLOBAL(0x00F1AD34, uint16) = *x; RCT2_GLOBAL(0x00F1AD36, uint16) = *y; - RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 0x1F; - RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 0x1F; + RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 31; + RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 31; - *x += 0x10; - *y += 0x10; + *x += 16; + *y += 16; int start_x, start_y; start_x = ((screenX - viewport->x) << viewport->zoom) + viewport->view_x; @@ -564,21 +564,21 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, uint32 myDirection; int mod_x = out_x & 0x1F, mod_y = out_y & 0x1F; if (mod_x < mod_y) { - if (mod_x + mod_y < 0x20) { + if (mod_x + mod_y < 32) { myDirection = 0; } else { myDirection = 1; } } else { - if (mod_x + mod_y < 0x20) { + if (mod_x + mod_y < 32) { myDirection = 3; } else { myDirection = 2; } } - if (x != NULL) *x = out_x & 0xFFE0; - if (y != NULL) *y = out_y & 0xFFE0; + if (x != NULL) *x = out_x & ~0x1F; + if (y != NULL) *y = out_y & ~0x1F; if (direction != NULL) *direction = myDirection; if (mapElement != NULL) *mapElement = myMapElement; // We should get the rct_map_element from 0x00F1AD30 here, but we set it earlier to our myMapElement anyway. From b20efdada86cde3a0b64ce500d3c41496d95afcc Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Fri, 3 Apr 2015 21:11:03 +0200 Subject: [PATCH 5/9] Refactored common code into viewport_coord_to_map_coord --- src/interface/viewport.c | 118 +++++++++++++++++++-------------------- src/interface/viewport.h | 4 +- src/interface/window.c | 6 +- src/world/footpath.c | 43 +++----------- 4 files changed, 70 insertions(+), 101 deletions(-) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 151cfcca78..93d4fec99e 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -223,74 +223,37 @@ void viewport_update_pointers() *vp = NULL; } -void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation){ +/** + * edx is assumed to be (and always is) the current rotation, so it is not needed as parameter. + * rct2: 0x00689174 + */ +void sub_689174(sint16* x, sint16* y, sint16 *z) +{ //RCT2_CALLFUNC_X(0x00689174, (int*)&x, (int*)&y, (int*)&z, &curr_rotation, (int*)&window, (int*)&viewport, &ebp); sint16 start_x = *x; sint16 start_y = *y; sint16 height = 0; - switch (curr_rotation){ - case 0: - for (int i = 0; i < 6; ++i){ - *x = start_y - start_x / 2 + height; - *y = start_y + start_x / 2 + height; - - height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y); - // HACK: This is to prevent the x and y values being set to values outside - // of the map. This can happen when the height is larger than the map size. - if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){ - *x = start_y - start_x / 2; - *y = start_y + start_x / 2; - } + rct_xy16 pos; + for (int i = 0; i < 6; i++) { + pos = viewport_coord_to_map_coord(start_x, start_y, height); + height = map_element_height((0xFFFF) & pos.x, (0xFFFF) & pos.y); + + // HACK: This is to prevent the x and y values being set to values outside + // of the map. This can happen when the height is larger than the map size. + sint16 max = RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16); + if (pos.x > max && pos.y > max) { + int x_corr[] = { -1, 1, 1, -1 }; + int y_corr[] = { -1, -1, 1, 1 }; + uint32 rotation = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32); + pos.x += x_corr[rotation] * height; + pos.y += y_corr[rotation] * height; } - break; - case 1: - for (int i = 0; i < 6; ++i){ - *x = -start_y - start_x / 2 - height; - *y = start_y - start_x / 2 + height; - - height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y); - - // HACK: This is to prevent the x and y values being set to values outside - // of the map. This can happen when the height is larger than the map size. - if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){ - *x = -start_y - start_x / 2; - *y = start_y - start_x / 2; - } - } - break; - case 2: - for (int i = 0; i < 6; ++i){ - *x = -start_y + start_x / 2 - height; - *y = -start_y - start_x / 2 - height; - - height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y); - - // HACK: This is to prevent the x and y values being set to values outside - // of the map. This can happen when the height is larger than the map size. - if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){ - *x = -start_y + start_x / 2; - *y = -start_y - start_x / 2; - } - } - break; - case 3: - for (int i = 0; i < 6; ++i){ - *x = start_x / 2 + start_y + height; - *y = start_x / 2 - start_y - height; - - height = map_element_height((0xFFFF) & *x, (0xFFFF) & *y); - - // HACK: This is to prevent the x and y values being set to values outside - // of the map. This can happen when the height is larger than the map size. - if (*x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16) && *y > RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAXIMUM_X_Y, sint16)){ - *x = start_y + start_x / 2; - *y = -start_y + start_x / 2; - } - } - break; } + + *x = pos.x; + *y = pos.y; *z = height; } @@ -494,8 +457,7 @@ void viewport_update_position(rct_window *window) sint16 y = viewport->view_height / 2 + window->saved_view_y; sint16 z; - int curr_rotation = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32); - sub_689174(&x, &y, &z, curr_rotation); + sub_689174(&x, &y, &z); viewport_set_underground_flag(0, window, viewport); //RCT2_CALLPROC_X(0x006E7A15, x, y, z, 0, (int)window, (int)viewport, 0); @@ -1505,6 +1467,38 @@ void screen_pos_to_map_pos(short *x, short *y) *y = ebx & 0xFFFF; } +rct_xy16 screen_coord_to_viewport_coord(rct_viewport *viewport, uint16 x, uint16 y) +{ + rct_xy16 ret; + ret.x = ((x - viewport->x) << viewport->zoom) + viewport->view_x; + ret.y = ((y - viewport->y) << viewport->zoom) + viewport->view_y; + return ret; +} + +rct_xy16 viewport_coord_to_map_coord(int x, int y, int z) +{ + rct_xy16 ret; + switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) { + case 0: + ret.x = -x / 2 + y + z; + ret.y = x / 2 + y + z; + break; + case 1: + ret.x = -x / 2 - y - z; + ret.y = -x / 2 + y + z; + break; + case 2: + ret.x = x / 2 - y - z; + ret.y = -x / 2 - y - z; + break; + case 3: + ret.x = x / 2 + y + z; + ret.y = x / 2 - y - z; + break; + } + return ret; +} + /** * * rct2: 0x00664689 diff --git a/src/interface/viewport.h b/src/interface/viewport.h index 2712cee4ce..422e28aa52 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -82,8 +82,10 @@ void viewport_update_position(rct_window *window); void viewport_render(rct_drawpixelinfo *dpi, rct_viewport *viewport, int left, int top, int right, int bottom); void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom); -void sub_689174(sint16* x, sint16* y, sint16 *z, uint8 curr_rotation); +void sub_689174(sint16* x, sint16* y, sint16 *z); +rct_xy16 screen_coord_to_viewport_coord(rct_viewport *viewport, uint16 x, uint16 y); +rct_xy16 viewport_coord_to_map_coord(int x, int y, int z); void screen_pos_to_map_pos(short *x, short *y); void show_gridlines(); diff --git a/src/interface/window.c b/src/interface/window.c index d99977d76e..ed5d376165 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -1156,8 +1156,6 @@ void window_rotate_camera(rct_window *w) sint16 y = (viewport->height >> 1) + viewport->y; sint16 z; - uint8 rot = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8); - int ecx, edx, esi, edi = (int)viewport, ebp; //has something to do with checking if middle of the viewport is obstructed RCT2_CALLFUNC_X(0x00688972, (int*)&x, (int*)&y, &ecx, &edx, &esi, &edi, &ebp); @@ -1169,12 +1167,12 @@ void window_rotate_camera(rct_window *w) x = (viewport->view_width >> 1) + viewport->view_x; y = (viewport->view_height >> 1) + viewport->view_y; - sub_689174(&x, &y, &z, rot); + sub_689174(&x, &y, &z); } else { z = map_element_height(x, y); } - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = (rot + 1) % 4; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) = (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32) + 1) % 4; int new_x, new_y; center_2d_coordinates(x, y, z, &new_x, &new_y, viewport); diff --git a/src/world/footpath.c b/src/world/footpath.c index ebb5c24dbd..c65bb85ed2 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -474,28 +474,6 @@ void footpath_provisional_update() footpath_provisional_remove(); } -void sub_689726_helper(int x, int y, int z, int *out_x, int *out_y) -{ - switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) { - case 0: - *out_x = -x / 2 + y + z; - *out_y = x / 2 + y + z; - break; - case 1: - *out_x = -x / 2 - y - z; - *out_y = -x / 2 + y + z; - break; - case 2: - *out_x = x / 2 - y - z; - *out_y = -x / 2 - y - z; - break; - case 3: - *out_x = x / 2 + y + z; - *out_y = x / 2 - y - z; - break; - } -} - /** * Determines the location of the footpath at which we point with the cursor. If no footpath is underneath the cursor, * then return the location of the ground tile. Besides the location it also computes the direction of the yellow arrow @@ -543,26 +521,23 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, *x += 16; *y += 16; - int start_x, start_y; - start_x = ((screenX - viewport->x) << viewport->zoom) + viewport->view_x; - start_y = ((screenY - viewport->y) << viewport->zoom) + viewport->view_y; - - int out_x = *x, out_y = *y; + rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY); + rct_xy16 map_pos = { *x, *y }; for (int i = 0; i < 5; i++) { if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 6) { - z = map_element_height(out_x, out_y); + z = map_element_height(map_pos.x, map_pos.y); } else { z = RCT2_GLOBAL(0x00F1AD3C, uint16); } - sub_689726_helper(start_x, start_y, z, &out_x, &out_y); - out_x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), out_x, RCT2_GLOBAL(0x00F1AD38, uint16)); - out_y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), out_y, RCT2_GLOBAL(0x00F1AD3A, uint16)); + map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); + map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, uint16)); + map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, uint16)); } // Determine to which edge the cursor is closest uint32 myDirection; - int mod_x = out_x & 0x1F, mod_y = out_y & 0x1F; + int mod_x = map_pos.x & 0x1F, mod_y = map_pos.y & 0x1F; if (mod_x < mod_y) { if (mod_x + mod_y < 32) { myDirection = 0; @@ -577,8 +552,8 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, } } - if (x != NULL) *x = out_x & ~0x1F; - if (y != NULL) *y = out_y & ~0x1F; + if (x != NULL) *x = map_pos.x & ~0x1F; + if (y != NULL) *y = map_pos.y & ~0x1F; if (direction != NULL) *direction = myDirection; if (mapElement != NULL) *mapElement = myMapElement; // We should get the rct_map_element from 0x00F1AD30 here, but we set it earlier to our myMapElement anyway. From f52ccebbcaf100baf5fda805dd1269f294f4829a Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Sat, 4 Apr 2015 12:32:35 +0200 Subject: [PATCH 6/9] Decompiled screen_pos_to_map_pos --- src/interface/viewport.c | 36 ++++++++++++++++++++++++++++++++---- src/interface/viewport.h | 2 +- src/windows/park.c | 2 +- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 93d4fec99e..7a6d591cac 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -1457,14 +1457,42 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in * * rct2: 0x0068958D */ -void screen_pos_to_map_pos(short *x, short *y) +void screen_pos_to_map_pos(short *x, short *y, int *direction) { int eax, ebx, ecx, edx, esi, edi, ebp; eax = *x; ebx = *y; - RCT2_CALLFUNC_X(0x0068958D, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - *x = eax & 0xFFFF; - *y = ebx & 0xFFFF; + RCT2_CALLFUNC_X(0x00688972, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + *x = eax & ~0x1F; + *y = ebx & ~0x1F; + if (*x == 0x8000) + return; + + int my_direction; + int dist_from_center_x = abs(*x % 32); + int dist_from_center_y = abs(*y % 32); + if (dist_from_center_x > 8 && dist_from_center_x < 24 && + dist_from_center_y > 8 && dist_from_center_y < 24) { + my_direction = 4; + } else { + sint16 mod_x = *x & 0x1F; + sint16 mod_y = *y & 0x1F; + if (mod_x <= 16) { + if (mod_y < 16) { + my_direction = 2; + } else { + my_direction = 3; + } + } else { + if (mod_y < 16) { + my_direction = 0; + } else { + my_direction = 1; + } + } + } + + if (direction != NULL) *direction = my_direction; } rct_xy16 screen_coord_to_viewport_coord(rct_viewport *viewport, uint16 x, uint16 y) diff --git a/src/interface/viewport.h b/src/interface/viewport.h index 422e28aa52..b6e9d047f8 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -86,7 +86,7 @@ void sub_689174(sint16* x, sint16* y, sint16 *z); rct_xy16 screen_coord_to_viewport_coord(rct_viewport *viewport, uint16 x, uint16 y); rct_xy16 viewport_coord_to_map_coord(int x, int y, int z); -void screen_pos_to_map_pos(short *x, short *y); +void screen_pos_to_map_pos(short *x, short *y, int *direction); void show_gridlines(); void hide_gridlines(); diff --git a/src/windows/park.c b/src/windows/park.c index 1f3cba798f..98fed533f5 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -812,7 +812,7 @@ static void window_park_entrance_toolupdate() if (widgetIndex == WIDX_BUY_LAND_RIGHTS) { map_invalidate_selection_rect(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= 0xFFFE; - screen_pos_to_map_pos(&x, &y); + screen_pos_to_map_pos(&x, &y, NULL); if (x != SPRITE_LOCATION_NULL) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; From 5f55bd97be1582ef576f2e6f4b41d33f43ac0276 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Sat, 4 Apr 2015 14:39:46 +0200 Subject: [PATCH 7/9] Decompiled sub_688972 --- src/interface/viewport.c | 53 ++++++++++++++++++++++++++++++++++------ src/interface/viewport.h | 3 ++- src/interface/window.c | 5 ++-- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 7a6d591cac..59b7e387ea 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -1453,18 +1453,55 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in //RCT2_CALLPROC_X(0x00685CBF, left, top, 0, right, (int)viewport, (int)dpi, bottom); } +/** + * + * rct2: 0x00688972 + * In: + * screen_x: eax + * screen_y: ebx + * Out: + * x: ax + * y: bx + * map_element: edx ? + * viewport: edi + */ +void sub_688972(int screenX, int screenY, sint16 *x, sint16 *y, rct_viewport **viewport) { + int z; + rct_viewport *myViewport; + get_map_coordinates_from_pos(screenX, screenY, 0xFFFE, x, y, &z, NULL, &myViewport); + if (z == 0) { + *x = 0x8000; + return; + } + + RCT2_GLOBAL(0x00F1AD34, uint16) = *x; + RCT2_GLOBAL(0x00F1AD36, uint16) = *y; + RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 31; + RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 31; + + rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(myViewport, screenX, screenY); + rct_xy16 map_pos = { *x + 16, *y + 16 }; + + for (int i = 0; i < 5; i++) { + z = map_element_height(map_pos.x, map_pos.y); + map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); + map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, uint16)); + map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, uint16)); + } + + *x = map_pos.x; + *y = map_pos.y; + + if (viewport != NULL) *viewport = myViewport; +} + /** * * rct2: 0x0068958D */ -void screen_pos_to_map_pos(short *x, short *y, int *direction) +void screen_pos_to_map_pos(sint16 *x, sint16 *y, int *direction) { - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = *x; - ebx = *y; - RCT2_CALLFUNC_X(0x00688972, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - *x = eax & ~0x1F; - *y = ebx & ~0x1F; + sub_688972(*x, *y, x, y, NULL); if (*x == 0x8000) return; @@ -1492,6 +1529,8 @@ void screen_pos_to_map_pos(short *x, short *y, int *direction) } } + *x = *x & ~0x1F; + *y = *y & ~0x1F; if (direction != NULL) *direction = my_direction; } diff --git a/src/interface/viewport.h b/src/interface/viewport.h index b6e9d047f8..e53019738f 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -86,7 +86,8 @@ void sub_689174(sint16* x, sint16* y, sint16 *z); rct_xy16 screen_coord_to_viewport_coord(rct_viewport *viewport, uint16 x, uint16 y); rct_xy16 viewport_coord_to_map_coord(int x, int y, int z); -void screen_pos_to_map_pos(short *x, short *y, int *direction); +void sub_688972(int screenX, int screenY, sint16 *x, sint16 *y, rct_viewport **viewport); +void screen_pos_to_map_pos(sint16 *x, sint16 *y, int *direction); void show_gridlines(); void hide_gridlines(); diff --git a/src/interface/window.c b/src/interface/window.c index ed5d376165..ea66ace556 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -1156,10 +1156,9 @@ void window_rotate_camera(rct_window *w) sint16 y = (viewport->height >> 1) + viewport->y; sint16 z; - int ecx, edx, esi, edi = (int)viewport, ebp; //has something to do with checking if middle of the viewport is obstructed - RCT2_CALLFUNC_X(0x00688972, (int*)&x, (int*)&y, &ecx, &edx, &esi, &edi, &ebp); - rct_viewport *other = (rct_viewport*)edi; + rct_viewport *other; + sub_688972(x, y, &x, &y, &other); // other != viewport probably triggers on viewports in ride or guest window? // x is 0x8000 if middle of viewport is obstructed by another window? From a78b37e96eda2a029f0f10b15689436b93a352e6 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Sat, 4 Apr 2015 15:15:24 +0200 Subject: [PATCH 8/9] Decompiled sub_68A15E --- src/windows/track_place.c | 73 ++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/src/windows/track_place.c b/src/windows/track_place.c index 1023196bae..eb1b933d26 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -304,14 +304,69 @@ static void window_track_place_draw_mini_preview() * * rct2: 0x0068A15E */ -static void sub_68A15E(int x, int y, short *ax, short *bx) +static void sub_68A15E(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement) { - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ebx = y; - RCT2_CALLFUNC_X(0x0068A15E, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - *ax = *((short*)&eax); - *bx = *((short*)&ebx); + int z; + rct_map_element *myMapElement; + rct_viewport *viewport; + get_map_coordinates_from_pos(screenX, screenY, 0xFFF6, x, y, &z, &myMapElement, &viewport); + + if (z == 0) { + *x = 0x8000; + return; + } + + RCT2_GLOBAL(0x00F1AD3E, uint8) = z; + RCT2_GLOBAL(0x00F1AD30, rct_map_element*) = myMapElement; + + if (z == 4) { + // myMapElement appears to be water + z = myMapElement->properties.surface.terrain; + z = (z & MAP_ELEMENT_WATER_HEIGHT_MASK) << 4; + } + + RCT2_GLOBAL(0x00F1AD3C, uint16) = z; + RCT2_GLOBAL(0x00F1AD34, uint16) = *x; + RCT2_GLOBAL(0x00F1AD36, uint16) = *y; + RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 31; + RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 31; + + rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY); + rct_xy16 map_pos = { *x + 16, *y + 16 }; + + for (int i = 0; i < 5; i++) { + if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 4) { + z = map_element_height(map_pos.x, map_pos.y); + } else { + z = RCT2_GLOBAL(0x00F1AD3C, uint16); + } + map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); + map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, uint16)); + map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, uint16)); + } + + // Determine to which edge the cursor is closest + int myDirection; + int mod_x = map_pos.x & 0x1F; + int mod_y = map_pos.y & 0x1F; + if (mod_x < mod_y) { + if (mod_x + mod_y < 32) { + myDirection = 0; + } else { + myDirection = 1; + } + } else { + if (mod_x + mod_y < 32) { + myDirection = 3; + } else { + myDirection = 2; + } + } + + *x = map_pos.x & ~0x1F; + *y = map_pos.y & ~0x1F; + if (direction != NULL) *direction = myDirection; + if (mapElement != NULL) *mapElement = myMapElement; } /** @@ -483,7 +538,7 @@ static void window_track_place_toolupdate() RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; // Get the tool map position - sub_68A15E(x, y, &x, &y); + sub_68A15E(x, y, &x, &y, NULL, NULL); if (x == (short)0x8000) { window_track_place_clear_provisional(); return; @@ -545,7 +600,7 @@ static void window_track_place_tooldown() map_invalidate_map_selection_tiles(); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; - sub_68A15E(x, y, &x, &y); + sub_68A15E(x, y, &x, &y, NULL, NULL); if (x == (short)0x8000) return; From 05fa87ad5d4c0d425734a040e7eafb93fcf324f5 Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Sat, 4 Apr 2015 15:22:37 +0200 Subject: [PATCH 9/9] Fixed warnings --- src/interface/viewport.c | 18 +++++++++--------- src/windows/track_place.c | 20 ++++++++++---------- src/world/footpath.c | 12 ++++++------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 59b7e387ea..89ce091184 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -1466,27 +1466,27 @@ void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, in * viewport: edi */ void sub_688972(int screenX, int screenY, sint16 *x, sint16 *y, rct_viewport **viewport) { - int z; + int my_x, my_y, z; rct_viewport *myViewport; - get_map_coordinates_from_pos(screenX, screenY, 0xFFFE, x, y, &z, NULL, &myViewport); + get_map_coordinates_from_pos(screenX, screenY, 0xFFFE, &my_x, &my_y, &z, NULL, &myViewport); if (z == 0) { *x = 0x8000; return; } - RCT2_GLOBAL(0x00F1AD34, uint16) = *x; - RCT2_GLOBAL(0x00F1AD36, uint16) = *y; - RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 31; - RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 31; + RCT2_GLOBAL(0x00F1AD34, sint16) = my_x; + RCT2_GLOBAL(0x00F1AD36, sint16) = my_y; + RCT2_GLOBAL(0x00F1AD38, sint16) = my_x + 31; + RCT2_GLOBAL(0x00F1AD3A, sint16) = my_y + 31; rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(myViewport, screenX, screenY); - rct_xy16 map_pos = { *x + 16, *y + 16 }; + rct_xy16 map_pos = { my_x + 16, my_y + 16 }; for (int i = 0; i < 5; i++) { z = map_element_height(map_pos.x, map_pos.y); map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); - map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, uint16)); - map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, uint16)); + map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, sint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, sint16)); + map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, sint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, sint16)); } *x = map_pos.x; diff --git a/src/windows/track_place.c b/src/windows/track_place.c index eb1b933d26..001c4ff014 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -304,12 +304,12 @@ static void window_track_place_draw_mini_preview() * * rct2: 0x0068A15E */ -static void sub_68A15E(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement) +static void sub_68A15E(int screenX, int screenY, short *x, short *y, int *direction, rct_map_element **mapElement) { - int z; + int my_x, my_y, z; rct_map_element *myMapElement; rct_viewport *viewport; - get_map_coordinates_from_pos(screenX, screenY, 0xFFF6, x, y, &z, &myMapElement, &viewport); + get_map_coordinates_from_pos(screenX, screenY, 0xFFF6, &my_x, &my_y, &z, &myMapElement, &viewport); if (z == 0) { *x = 0x8000; @@ -326,13 +326,13 @@ static void sub_68A15E(int screenX, int screenY, int *x, int *y, int *direction, } RCT2_GLOBAL(0x00F1AD3C, uint16) = z; - RCT2_GLOBAL(0x00F1AD34, uint16) = *x; - RCT2_GLOBAL(0x00F1AD36, uint16) = *y; - RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 31; - RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 31; + RCT2_GLOBAL(0x00F1AD34, sint16) = my_x; + RCT2_GLOBAL(0x00F1AD36, sint16) = my_y; + RCT2_GLOBAL(0x00F1AD38, sint16) = my_x + 31; + RCT2_GLOBAL(0x00F1AD3A, sint16) = my_y + 31; rct_xy16 start_vp_pos = screen_coord_to_viewport_coord(viewport, screenX, screenY); - rct_xy16 map_pos = { *x + 16, *y + 16 }; + rct_xy16 map_pos = { my_x + 16, my_y + 16 }; for (int i = 0; i < 5; i++) { if (RCT2_GLOBAL(0x00F1AD3E, uint8) != 4) { @@ -341,8 +341,8 @@ static void sub_68A15E(int screenX, int screenY, int *x, int *y, int *direction, z = RCT2_GLOBAL(0x00F1AD3C, uint16); } map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); - map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, uint16)); - map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, uint16)); + map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, sint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, sint16)); + map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, sint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, sint16)); } // Determine to which edge the cursor is closest diff --git a/src/world/footpath.c b/src/world/footpath.c index c65bb85ed2..8a0f7c594e 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -513,10 +513,10 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, } RCT2_GLOBAL(0x00F1AD3C, uint16) = z; - RCT2_GLOBAL(0x00F1AD34, uint16) = *x; - RCT2_GLOBAL(0x00F1AD36, uint16) = *y; - RCT2_GLOBAL(0x00F1AD38, uint16) = *x + 31; - RCT2_GLOBAL(0x00F1AD3A, uint16) = *y + 31; + RCT2_GLOBAL(0x00F1AD34, sint16) = *x; + RCT2_GLOBAL(0x00F1AD36, sint16) = *y; + RCT2_GLOBAL(0x00F1AD38, sint16) = *x + 31; + RCT2_GLOBAL(0x00F1AD3A, sint16) = *y + 31; *x += 16; *y += 16; @@ -531,8 +531,8 @@ void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, z = RCT2_GLOBAL(0x00F1AD3C, uint16); } map_pos = viewport_coord_to_map_coord(start_vp_pos.x, start_vp_pos.y, z); - map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, uint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, uint16)); - map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, uint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, uint16)); + map_pos.x = clamp(RCT2_GLOBAL(0x00F1AD34, sint16), map_pos.x, RCT2_GLOBAL(0x00F1AD38, sint16)); + map_pos.y = clamp(RCT2_GLOBAL(0x00F1AD36, sint16), map_pos.y, RCT2_GLOBAL(0x00F1AD3A, sint16)); } // Determine to which edge the cursor is closest