From b20efdada86cde3a0b64ce500d3c41496d95afcc Mon Sep 17 00:00:00 2001 From: Timmy Weerwag Date: Fri, 3 Apr 2015 21:11:03 +0200 Subject: [PATCH] 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.