From 2b9aa8a2b719aec8d4c7bdecdeadfb2f2f0ddfc3 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 30 Sep 2014 18:56:30 +0100 Subject: [PATCH 1/5] start implementing window_track_place --- src/string_ids.h | 3 +- src/window.h | 3 + src/window_track_list.c | 2 +- src/window_track_place.c | 213 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 217 insertions(+), 4 deletions(-) diff --git a/src/string_ids.h b/src/string_ids.h index 4d22b3eb56..f4bd4f45bc 100644 --- a/src/string_ids.h +++ b/src/string_ids.h @@ -1177,7 +1177,8 @@ enum { STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP = 3111, STR_CLICK_ON_DESIGN_TO_RENAME_OR_DELETE_IT = 3112, - + STR_SELECT_A_DIFFERENT_DESIGN = 3113, + STR_GO_BACK_TO_DESIGN_SELECTION_WINDOW_TIP = 3114, STR_SAVE_TRACK_DESIGN = 3115, STR_SAVE_TRACK_DESIGN_NOT_POSSIBLE = 3116, diff --git a/src/window.h b/src/window.h index 8f74ccef9b..47b749b222 100644 --- a/src/window.h +++ b/src/window.h @@ -398,6 +398,9 @@ enum PROMPT_MODE { // rct2: 0x01420078 extern rct_window* g_window_list; +// rct2: 0x00F635EE +extern ride_list_item _window_track_list_item; + void window_dispatch_update_all(); void window_update_all(); rct_window *window_create(int x, int y, int width, int height, uint32 *event_handlers, rct_windowclass cls, uint16 flags); diff --git a/src/window_track_list.c b/src/window_track_list.c index fb08c63d53..784e99427a 100644 --- a/src/window_track_list.c +++ b/src/window_track_list.c @@ -93,7 +93,7 @@ static void* window_track_list_events[] = { (uint32*)window_track_list_scrollpaint }; -static ride_list_item _window_track_list_item; +ride_list_item _window_track_list_item; void window_track_list_format_name(char *dst, const char *src, char colour) { diff --git a/src/window_track_place.c b/src/window_track_place.c index 678384c295..cfcd377603 100644 --- a/src/window_track_place.c +++ b/src/window_track_place.c @@ -19,9 +19,74 @@ *****************************************************************************/ #include "addresses.h" +#include "sprites.h" +#include "string_ids.h" #include "viewport.h" +#include "widget.h" #include "window.h" +enum { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_ROTATE, + WIDX_MIRROR, + WIDX_SELECT_DIFFERENT_DESIGN, + WIDX_PRICE +}; + +static rct_widget window_track_place_widgets[] = { + { WWT_FRAME, 0, 0, 199, 0, 123, 0xFFFFFFFF, STR_NONE }, + { WWT_CAPTION, 0, 1, 198, 1, 14, 3155, STR_WINDOW_TITLE_TIP }, + { WWT_CLOSEBOX, 0, 187, 197, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, + { WWT_FLATBTN, 0, 173, 196, 83, 106, SPR_ROTATE_ARROW, STR_ROTATE_90_TIP }, + { WWT_FLATBTN, 0, 173, 196, 59, 82, 5170, STR_MIRROR_IMAGE_TIP }, + { WWT_DROPDOWN_BUTTON, 0, 4, 195, 109, 120, STR_SELECT_A_DIFFERENT_DESIGN, STR_GO_BACK_TO_DESIGN_SELECTION_WINDOW_TIP }, + { WWT_EMPTY, 0, 0, 0, 0, 0, 0xFFFFFFFF, STR_NONE }, + { WIDGETS_END }, +}; + +static void window_track_place_emptysub() { } +static void window_track_place_close(); +static void window_track_place_mouseup(); +static void window_track_place_update(rct_window *w); +static void window_track_place_toolupdate(); +static void window_track_place_tooldown(); +static void window_track_place_toolabort(); +static void window_track_place_unknown14(); +static void window_track_place_paint(); + +static void* window_track_place_events[] = { + window_track_place_close, + window_track_place_mouseup, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_update, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_toolupdate, + window_track_place_tooldown, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_toolabort, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_unknown14, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_emptysub, + window_track_place_paint, + window_track_place_emptysub +}; + /** * * rct2: 0x006CFCA0 @@ -34,8 +99,8 @@ void window_track_place_open() RCT2_GLOBAL(0x00F44168, void*) = rct2_malloc(13104); RCT2_CALLPROC_EBPSAFE(0x006D182E); - w = window_create(0, 29, 200, 124, (uint32*)0x0099405C, WC_TRACK_DESIGN_PLACE, 0); - w->widgets = (rct_widget*)0x009D7F18; + w = window_create(0, 29, 200, 124, (uint32*)window_track_place_events, WC_TRACK_DESIGN_PLACE, 0); + w->widgets = window_track_place_widgets; w->enabled_widgets = 4 | 8 | 0x10 | 0x20; window_init_scroll_widgets(w); w->colours[0] = 24; @@ -49,4 +114,148 @@ void window_track_place_open() RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF; RCT2_GLOBAL(0x00F440AE, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3; RCT2_CALLPROC_EBPSAFE(0x006D1845); +} + +/** + * + * rct2: 0x006D0119 + */ +static void window_track_place_close() +{ + RCT2_CALLPROC_EBPSAFE(0x006D017F); + viewport_set_visibility(0); + RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~6; + hide_gridlines(); + rct2_free(RCT2_GLOBAL(0x00F44168, void*)); +} + +/** + * + * rct2: 0x006CFEAC + */ +static void window_track_place_mouseup() +{ + rct_window *w; + short widgetIndex; + + window_widget_get_registers(w, widgetIndex); + + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_ROTATE: + RCT2_CALLPROC_EBPSAFE(0x006D017F); + RCT2_GLOBAL(0x00F440AE, uint16) = (RCT2_GLOBAL(0x00F440AE, uint16) + 1) & 3; + window_invalidate(w); + RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF; + RCT2_CALLPROC_EBPSAFE(0x006D1845); + break; + case WIDX_MIRROR: + RCT2_CALLPROC_EBPSAFE(0x006D2436); + RCT2_GLOBAL(0x00F440AE, uint16) = (-RCT2_GLOBAL(0x00F440AE, uint16)) & 3; + window_invalidate(w); + RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF; + RCT2_CALLPROC_EBPSAFE(0x006D1845); + break; + case WIDX_SELECT_DIFFERENT_DESIGN: + window_close(w); + window_track_list_open(_window_track_list_item); + break; + } +} + +/** + * + * rct2: 0x006CFCA0 + */ +static void window_track_place_update(rct_window *w) +{ + if (!(RCT2_GLOBAL(0x009DE518, uint32) & (1 << 3))) + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TRACK_DESIGN_PLACE) + window_close(w); +} + +/** + * + * rct2: 0x006CFF2D + */ +static void window_track_place_toolupdate() +{ + rct_window *w; + short widgetIndex, x, y; + + window_tool_get_registers(w, widgetIndex, x, y); + + RCT2_CALLPROC_X(0x006CFF2D, x, y, 0, widgetIndex, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006CFF34 + */ +static void window_track_place_tooldown() +{ + rct_window *w; + short widgetIndex, x, y; + + window_tool_get_registers(w, widgetIndex, x, y); + + RCT2_CALLPROC_X(0x006CFF34, x, y, 0, widgetIndex, (int)w, 0, 0); +} + +/** + * + * rct2: 0x006D015C + */ +static void window_track_place_toolabort() +{ + RCT2_CALLPROC_EBPSAFE(0x006D017F); +} + +/** + * + * rct2: 0x006CFF01 + */ +static void window_track_place_unknown14() +{ + RCT2_CALLPROC_EBPSAFE(0x006D1845); +} + +/** + * + * rct2: 0x006CFD9D + */ +static void window_track_place_paint() +{ + rct_window *w; + rct_drawpixelinfo *dpi, *clippedDpi; + rct_g1_element tmpElement, *subsituteElement, *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); + + window_paint_get_registers(w, dpi); + + window_draw_widgets(w, dpi); + + // Draw mini tile preview + clippedDpi = clip_drawpixelinfo(dpi, w->x + 4, 168, w->y + 18, 78); + if (clippedDpi != NULL) { + subsituteElement = &g1Elements[0]; + tmpElement = *subsituteElement; + subsituteElement->offset = RCT2_GLOBAL(0x00F44168, uint8*); + subsituteElement->width = 168; + subsituteElement->height = 78; + subsituteElement->x_offset = 0; + subsituteElement->y_offset = 0; + subsituteElement->flags = 0; + gfx_draw_sprite(clippedDpi, 0, 0, 0, 0); + *subsituteElement = tmpElement; + } + + if (RCT2_GLOBAL(0x00F440D9, money32) == 0x80000000) + return; + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) + return; + + gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, 0, (money32*)0x00F440D9); } \ No newline at end of file From f761306beb4756250bd45685897d5d46b2864604 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Wed, 1 Oct 2014 02:03:36 +0100 Subject: [PATCH 2/5] implement window_track_place_toolupdate --- src/viewport.c | 24 +++++ src/viewport.h | 2 + src/window_footpath.c | 23 +---- src/window_peep.c | 10 +- src/window_track_place.c | 212 ++++++++++++++++++++++++++++++++++----- 5 files changed, 221 insertions(+), 50 deletions(-) diff --git a/src/viewport.c b/src/viewport.c index f1aa777363..3f412edc4f 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -1088,3 +1088,27 @@ void viewport_set_visibility(uint8 mode) window_invalidate(window); } } + +/** + * + * rct2: 0x00685ADC + * screenX: eax + * screenY: ebx + * flags: edx + * x: ax + * y: cx + * z: bl + * mapElement: edx + */ +void get_map_coordinates_from_pos(int screenX, int screenY, int flags, int *x, int *y, int *z, rct_map_element **mapElement) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + eax = x; + ebx = y; + edx = flags; + RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + if (x != NULL) *x = *((uint8*)&eax); + if (y != NULL) *y = *((uint8*)&ecx); + if (z != NULL) *z = *((uint8*)&ebx); + if (mapElement != NULL) *mapElement = (rct_map_element*)edx; +} \ No newline at end of file diff --git a/src/viewport.h b/src/viewport.h index dfbcfb8c5c..c1dbd0c7c8 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -65,4 +65,6 @@ 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); + #endif diff --git a/src/window_footpath.c b/src/window_footpath.c index 582f9198fe..62c1e5ada5 100644 --- a/src/window_footpath.c +++ b/src/window_footpath.c @@ -615,16 +615,7 @@ static void window_footpath_set_provisional_path_at_point(int x, int y) RCT2_CALLPROC_EBPSAFE(0x0068AAE1); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~4; - // Get map coordinates from point - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ebx = y; - edx = -34; - RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - x = eax & 0xFFFF; - z = ebx & 0xFF; - y = ecx & 0xFFFF; - mapElement = (rct_map_element*)edx; + get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement); if (z == 0) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~1; @@ -697,17 +688,7 @@ static void window_footpath_place_path_at_point(int x, int y) RCT2_CALLPROC_EBPSAFE(0x006A7831); - // Get map coordinates from point - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ebx = y; - edx = -34; - RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - x = eax & 0xFFFF; - z = ebx & 0xFF; - y = ecx & 0xFFFF; - mapElement = (rct_map_element*)edx; - + get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement); if (z == 0) return; diff --git a/src/window_peep.c b/src/window_peep.c index 2238f77de6..5dbd0d03d8 100644 --- a/src/window_peep.c +++ b/src/window_peep.c @@ -1153,11 +1153,11 @@ void window_peep_overview_tool_update(){ } RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; - eax = x; - int ebx = y; - edx = 0; - RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - if ((ebx & 0xFF) == 0) return; + + int ebx; + get_map_coordinates_from_pos(x, y, 0, NULL, NULL, &ebx, NULL); + if (ebx == 0) + return; x--; y += 16; diff --git a/src/window_track_place.c b/src/window_track_place.c index cfcd377603..a0cd1371dd 100644 --- a/src/window_track_place.c +++ b/src/window_track_place.c @@ -18,13 +18,19 @@ * along with this program. If not, see . *****************************************************************************/ +#include #include "addresses.h" +#include "game.h" #include "sprites.h" #include "string_ids.h" #include "viewport.h" #include "widget.h" #include "window.h" +#define TRACK_MINI_PREVIEW_WIDTH 168 +#define TRACK_MINI_PREVIEW_HEIGHT 78 +#define TRACK_MINI_PREVIEW_SIZE (TRACK_MINI_PREVIEW_WIDTH * TRACK_MINI_PREVIEW_HEIGHT) + enum { WIDX_BACKGROUND, WIDX_TITLE, @@ -87,6 +93,108 @@ static void* window_track_place_events[] = { window_track_place_emptysub }; +static uint8 *_window_track_place_mini_preview; +static sint16 _window_track_place_last_x; +static sint16 _window_track_place_last_y; + +static uint8 _window_track_place_last_was_valid; +static sint16 _window_track_place_last_valid_x; +static sint16 _window_track_place_last_valid_y; +static sint16 _window_track_place_last_valid_z; +static money32 _window_track_place_last_cost; + +/** + * + * rct2: 0x006D182E + */ +static void window_track_place_clear_mini_preview() +{ + memset(_window_track_place_mini_preview, 220, TRACK_MINI_PREVIEW_SIZE); +} + +/** + * + * rct2: 0x006D1845 + */ +static void window_track_place_draw_mini_preview() +{ + RCT2_GLOBAL(0x00F44168, uint8*) = _window_track_place_mini_preview; + RCT2_CALLPROC_EBPSAFE(0x006D1845); +} + +/** + * + * rct2: 0x0068A15E + */ +static short sub_68A15E(int x, int y, short *ax, short *bx) +{ + 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); +} + +/** + * Seems to highlight the surface tiles to match the track layout at the given position but also returns some Z value. + * rct2: 0x006D01B3 + */ +static int sub_6D01B3(int bl, int x, int y, int z) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + eax = x; + ebx = bl; + ecx = y; + edx = z; + esi = 0; + edi = 0; + ebp = 0; + RCT2_CALLFUNC_X(0x006D01B3, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return *((short*)&ebx); +} + +/** + * + * rct2: 0x006D017F + */ +static void window_track_place_clear_provisional() +{ + if (_window_track_place_last_was_valid) { + sub_6D01B3( + (RCT2_GLOBAL(0x00F440EB, uint8) << 8) | 6, + _window_track_place_last_valid_x, + _window_track_place_last_valid_y, + _window_track_place_last_valid_z + ); + _window_track_place_last_was_valid = 0; + } +} + +static int sub_6D17C6(int x, int y) +{ + rct_map_element *mapElement; + int z; + + mapElement = map_get_surface_element_at(x >> 5, y >> 5); + z = mapElement->base_height * 8; + + // Increase Z above slope + if (mapElement->properties.surface.slope & 0x0F) { + z += 16; + + // Increase Z above double slope + if (mapElement->properties.surface.slope & 0x10) + z += 16; + } + + // Increase Z above water + if (mapElement->properties.surface.terrain & 0x1F) + z = max(z, (mapElement->properties.surface.terrain & 0x1F) << 4); + + return z + sub_6D01B3(3, x, y, z); +} + /** * * rct2: 0x006CFCA0 @@ -96,8 +204,9 @@ void window_track_place_open() rct_window *w; window_close_construction_windows(); - RCT2_GLOBAL(0x00F44168, void*) = rct2_malloc(13104); - RCT2_CALLPROC_EBPSAFE(0x006D182E); + + _window_track_place_mini_preview = malloc(TRACK_MINI_PREVIEW_SIZE); + window_track_place_clear_mini_preview(); w = window_create(0, 29, 200, 124, (uint32*)window_track_place_events, WC_TRACK_DESIGN_PLACE, 0); w->widgets = window_track_place_widgets; @@ -110,10 +219,10 @@ void window_track_place_open() RCT2_GLOBAL(0x009DE518, uint32) |= 6; window_push_others_right(w); show_gridlines(); - RCT2_GLOBAL(0x00F440D9, uint32) |= 0x80000000; - RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF; + _window_track_place_last_cost = MONEY32_UNDEFINED; + _window_track_place_last_x = 0xFFFF; RCT2_GLOBAL(0x00F440AE, uint8) = (-RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3; - RCT2_CALLPROC_EBPSAFE(0x006D1845); + window_track_place_draw_mini_preview(); } /** @@ -122,12 +231,12 @@ void window_track_place_open() */ static void window_track_place_close() { - RCT2_CALLPROC_EBPSAFE(0x006D017F); + window_track_place_clear_provisional(); viewport_set_visibility(0); RCT2_CALLPROC_EBPSAFE(0x0068AB1B); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~6; hide_gridlines(); - rct2_free(RCT2_GLOBAL(0x00F44168, void*)); + free(_window_track_place_mini_preview); } /** @@ -146,18 +255,18 @@ static void window_track_place_mouseup() window_close(w); break; case WIDX_ROTATE: - RCT2_CALLPROC_EBPSAFE(0x006D017F); + window_track_place_clear_provisional(); RCT2_GLOBAL(0x00F440AE, uint16) = (RCT2_GLOBAL(0x00F440AE, uint16) + 1) & 3; window_invalidate(w); - RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF; - RCT2_CALLPROC_EBPSAFE(0x006D1845); + _window_track_place_last_x = 0xFFFF; + window_track_place_draw_mini_preview(); break; case WIDX_MIRROR: RCT2_CALLPROC_EBPSAFE(0x006D2436); RCT2_GLOBAL(0x00F440AE, uint16) = (-RCT2_GLOBAL(0x00F440AE, uint16)) & 3; window_invalidate(w); - RCT2_GLOBAL(0x00F440DD, uint16) = 0xFFFF; - RCT2_CALLPROC_EBPSAFE(0x006D1845); + _window_track_place_last_x = 0xFFFF; + window_track_place_draw_mini_preview(); break; case WIDX_SELECT_DIFFERENT_DESIGN: window_close(w); @@ -185,10 +294,67 @@ static void window_track_place_toolupdate() { rct_window *w; short widgetIndex, x, y; + int i, z; + money32 cost; window_tool_get_registers(w, widgetIndex, x, y); - RCT2_CALLPROC_X(0x006CFF2D, x, y, 0, widgetIndex, (int)w, 0, 0); + RCT2_CALLPROC_X(0x006CFF2D, x, y, 0, widgetIndex, (int)w, 0, 0); return; + + // BUG: After placing layout, path tiles aren't connected, even though they were in the provisional appearance + + RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; + + // Get the tool map position + sub_68A15E(x, y, &x, &y); + if (x == (short)0x8000) { + window_track_place_clear_provisional(); + return; + } + + // Check if tool map position has changed since last update + if (x == _window_track_place_last_x && y == _window_track_place_last_y) { + sub_6D01B3(0, x, y, 0); + return; + } + + cost = MONEY32_UNDEFINED; + + // Get base Z position + z = sub_6D17C6(x, y); + if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) { + window_track_place_clear_provisional(); + + // Try increasing Z until a feasible placement is found + for (i = 0; i < 7; i++) { + int eax, ebx, ecx, edx, esi, edi, ebp; + + eax = x; + ebx = 105; + ecx = y; + edi = z; + cost = game_do_command_p(GAME_COMMAND_47, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + if (cost != MONEY32_UNDEFINED) { + RCT2_GLOBAL(0x00F440EB, uint16) = *((short*)&edi); + _window_track_place_last_valid_x = x; + _window_track_place_last_valid_y = y; + _window_track_place_last_valid_z = z; + _window_track_place_last_was_valid = 1; + break; + } + z += 8; + } + } + + _window_track_place_last_x = x; + _window_track_place_last_y = y; + if (cost != _window_track_place_last_cost) { + _window_track_place_last_cost = cost; + widget_invalidate(WC_TRACK_DESIGN_PLACE, 0, WIDX_PRICE); + } + + sub_6D01B3(0, x, y, z); } /** @@ -211,7 +377,7 @@ static void window_track_place_tooldown() */ static void window_track_place_toolabort() { - RCT2_CALLPROC_EBPSAFE(0x006D017F); + window_track_place_clear_provisional(); } /** @@ -220,7 +386,7 @@ static void window_track_place_toolabort() */ static void window_track_place_unknown14() { - RCT2_CALLPROC_EBPSAFE(0x006D1845); + window_track_place_draw_mini_preview(); } /** @@ -242,9 +408,9 @@ static void window_track_place_paint() if (clippedDpi != NULL) { subsituteElement = &g1Elements[0]; tmpElement = *subsituteElement; - subsituteElement->offset = RCT2_GLOBAL(0x00F44168, uint8*); - subsituteElement->width = 168; - subsituteElement->height = 78; + subsituteElement->offset = _window_track_place_mini_preview; + subsituteElement->width = TRACK_MINI_PREVIEW_WIDTH; + subsituteElement->height = TRACK_MINI_PREVIEW_HEIGHT; subsituteElement->x_offset = 0; subsituteElement->y_offset = 0; subsituteElement->flags = 0; @@ -252,10 +418,8 @@ static void window_track_place_paint() *subsituteElement = tmpElement; } - if (RCT2_GLOBAL(0x00F440D9, money32) == 0x80000000) - return; - if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) - return; - - gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, 0, (money32*)0x00F440D9); + // Price + if (_window_track_place_last_cost != MONEY32_UNDEFINED) + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) + gfx_draw_string_centred(dpi, STR_COST_LABEL, w->x + 88, w->y + 94, 0, &_window_track_place_last_cost); } \ No newline at end of file From 24a6f275513c8c218e6f699489e660ced3d8b060 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 3 Oct 2014 17:50:09 +0100 Subject: [PATCH 3/5] fix path bug and implement tooldown for place track --- src/viewport.c | 4 +-- src/window_track_place.c | 60 +++++++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/viewport.c b/src/viewport.c index 3f412edc4f..25b4fe062b 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -1103,8 +1103,8 @@ 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) { int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ebx = y; + eax = screenX; + ebx = screenY; edx = flags; RCT2_CALLFUNC_X(0x00685ADC, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); if (x != NULL) *x = *((uint8*)&eax); diff --git a/src/window_track_place.c b/src/window_track_place.c index a0cd1371dd..cf22e43cc2 100644 --- a/src/window_track_place.c +++ b/src/window_track_place.c @@ -20,6 +20,7 @@ #include #include "addresses.h" +#include "audio.h" #include "game.h" #include "sprites.h" #include "string_ids.h" @@ -126,7 +127,7 @@ static void window_track_place_draw_mini_preview() * * rct2: 0x0068A15E */ -static short sub_68A15E(int x, int y, short *ax, short *bx) +static void sub_68A15E(int x, int y, short *ax, short *bx) { int eax, ebx, ecx, edx, esi, edi, ebp; eax = x; @@ -299,10 +300,6 @@ static void window_track_place_toolupdate() window_tool_get_registers(w, widgetIndex, x, y); - RCT2_CALLPROC_X(0x006CFF2D, x, y, 0, widgetIndex, (int)w, 0, 0); return; - - // BUG: After placing layout, path tiles aren't connected, even though they were in the provisional appearance - RCT2_CALLPROC_EBPSAFE(0x0068AB1B); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; @@ -364,11 +361,60 @@ static void window_track_place_toolupdate() static void window_track_place_tooldown() { rct_window *w; - short widgetIndex, x, y; + short widgetIndex, x, y, z; + int i; + money32 cost; window_tool_get_registers(w, widgetIndex, x, y); - RCT2_CALLPROC_X(0x006CFF34, x, y, 0, widgetIndex, (int)w, 0, 0); + window_track_place_clear_provisional(); + RCT2_CALLPROC_EBPSAFE(0x0068AB1B); + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~7; + + sub_68A15E(x, y, &x, &y); + if (x == (short)0x8000) + return; + + // Try increasing Z until a feasible placement is found + z = sub_6D17C6(x, y); + for (i = 0; i < 7; i++) { + RCT2_GLOBAL(0x009A8C29, uint8) |= 1; + + int eax, ebx, ecx, edx, esi, edi, ebp; + eax = x; + ebx = 1; + ecx = y; + edi = z; + cost = game_do_command_p(GAME_COMMAND_47, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + RCT2_GLOBAL(0x009A8C29, uint8) &= ~1; + + if (cost != MONEY32_UNDEFINED) { + window_close_by_id(WC_ERROR, 0); + sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); + + int rideIndex = edi & 0xFF; + RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; + if (RCT2_GLOBAL(0x00F4414E, uint8) & 1) { + window_ride_main_open(rideIndex); + window_close(w); + } else { + RCT2_CALLPROC_X(0x006CC3FB, 0, 0, 0, rideIndex, 0, 0, 0); + w = window_find_by_id(0x80 | WC_RIDE_CONSTRUCTION, 0); + RCT2_CALLPROC_X(w->event_handlers[WE_MOUSE_UP], 0, 0, 0, 29, (int)w, 0, 0); + } + return; + } + + // Check if player did not have enough funds + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) == 827) + break; + + z += 8; + } + + // Unable to build track + sound_play_panned(SOUND_ERROR, 0x8001, x, y, z); } /** From db8b9439b8a57a1a0e93859f1c65fa9a9d804352 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Fri, 3 Oct 2014 18:15:20 +0100 Subject: [PATCH 4/5] refactor window_track_place.c --- src/window_track_place.c | 47 +++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/window_track_place.c b/src/window_track_place.c index cf22e43cc2..39b365d80a 100644 --- a/src/window_track_place.c +++ b/src/window_track_place.c @@ -172,7 +172,11 @@ static void window_track_place_clear_provisional() } } -static int sub_6D17C6(int x, int y) +/** + * + * rct2: 0x006D17C6 + */ +static int window_track_place_get_base_z(int x, int y) { rct_map_element *mapElement; int z; @@ -196,6 +200,21 @@ static int sub_6D17C6(int x, int y) return z + sub_6D01B3(3, x, y, z); } +static void window_track_place_attempt_placement(int x, int y, int z, int bl, money32 *cost, uint8 *rideIndex) +{ + int eax, ebx, ecx, edx, esi, edi, ebp; + money32 result; + + eax = x; + ebx = bl; + ecx = y; + edi = z; + result = game_do_command_p(GAME_COMMAND_47, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + + if (cost != NULL) *cost = result; + if (rideIndex != NULL) *rideIndex = edi & 0xFF; +} + /** * * rct2: 0x006CFCA0 @@ -297,6 +316,7 @@ static void window_track_place_toolupdate() short widgetIndex, x, y; int i, z; money32 cost; + uint8 rideIndex; window_tool_get_registers(w, widgetIndex, x, y); @@ -319,21 +339,15 @@ static void window_track_place_toolupdate() cost = MONEY32_UNDEFINED; // Get base Z position - z = sub_6D17C6(x, y); + z = window_track_place_get_base_z(x, y); if (RCT2_GLOBAL(0x009DEA6E, uint8) == 0) { window_track_place_clear_provisional(); // Try increasing Z until a feasible placement is found for (i = 0; i < 7; i++) { - int eax, ebx, ecx, edx, esi, edi, ebp; - - eax = x; - ebx = 105; - ecx = y; - edi = z; - cost = game_do_command_p(GAME_COMMAND_47, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + window_track_place_attempt_placement(x, y, z, 105, &cost, &rideIndex); if (cost != MONEY32_UNDEFINED) { - RCT2_GLOBAL(0x00F440EB, uint16) = *((short*)&edi); + RCT2_GLOBAL(0x00F440EB, uint16) = rideIndex; _window_track_place_last_valid_x = x; _window_track_place_last_valid_y = y; _window_track_place_last_valid_z = z; @@ -364,6 +378,7 @@ static void window_track_place_tooldown() short widgetIndex, x, y, z; int i; money32 cost; + uint8 rideIndex; window_tool_get_registers(w, widgetIndex, x, y); @@ -376,24 +391,16 @@ static void window_track_place_tooldown() return; // Try increasing Z until a feasible placement is found - z = sub_6D17C6(x, y); + z = window_track_place_get_base_z(x, y); for (i = 0; i < 7; i++) { RCT2_GLOBAL(0x009A8C29, uint8) |= 1; - - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ebx = 1; - ecx = y; - edi = z; - cost = game_do_command_p(GAME_COMMAND_47, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - + window_track_place_attempt_placement(x, y, z, 1, &cost, &rideIndex); RCT2_GLOBAL(0x009A8C29, uint8) &= ~1; if (cost != MONEY32_UNDEFINED) { window_close_by_id(WC_ERROR, 0); sound_play_panned(SOUND_PLACE_ITEM, 0x8001, x, y, z); - int rideIndex = edi & 0xFF; RCT2_GLOBAL(0x00F440A7, uint8) = rideIndex; if (RCT2_GLOBAL(0x00F4414E, uint8) & 1) { window_ride_main_open(rideIndex); From 7c79a0199f80e1ea818ede488ce181290146db81 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Sat, 4 Oct 2014 00:28:43 +0100 Subject: [PATCH 5/5] implement window_track_place_draw_mini_preview --- src/track.h | 1 + src/window_track_place.c | 204 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 2 deletions(-) diff --git a/src/track.h b/src/track.h index 4c4fa6c203..1bdf348969 100644 --- a/src/track.h +++ b/src/track.h @@ -22,6 +22,7 @@ #define _TRACK_H_ #include "rct2.h" +#include "ride.h" typedef struct { uint8 type; diff --git a/src/window_track_place.c b/src/window_track_place.c index 39b365d80a..be3b367c0e 100644 --- a/src/window_track_place.c +++ b/src/window_track_place.c @@ -24,6 +24,7 @@ #include "game.h" #include "sprites.h" #include "string_ids.h" +#include "track.h" #include "viewport.h" #include "widget.h" #include "window.h" @@ -113,14 +114,213 @@ static void window_track_place_clear_mini_preview() memset(_window_track_place_mini_preview, 220, TRACK_MINI_PREVIEW_SIZE); } +/** + * Size: 0x0A + */ +typedef struct { + uint8 var_00; + sint16 x; + sint16 y; + uint8 pad_05[3]; + uint8 var_08; + uint8 unk_09; +} rct_preview_track; + +/** + * Size: 0x04 + */ +typedef struct { + union { + uint32 all; + struct { + sint8 x; + sint8 y; + uint8 unk_2; + uint8 type; + }; + }; +} rct_preview_maze; + +#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y; + /** * * rct2: 0x006D1845 */ static void window_track_place_draw_mini_preview() { - RCT2_GLOBAL(0x00F44168, uint8*) = _window_track_place_mini_preview; - RCT2_CALLPROC_EBPSAFE(0x006D1845); + rct_track_design *design = (rct_track_design*)0x009D8178; + uint8 *pixel, colour, *trackPtr, bits; + int i, rotation, pass, x, y, pixelX, pixelY, originX, originY, minX, minY, maxX, maxY; + rct_preview_maze *mazeBlock; + rct_preview_track *trackBlock; + + window_track_place_clear_mini_preview(); + + minX = 0; + minY = 0; + maxX = 0; + maxY = 0; + + // First pass is used to determine the width and height of the image so it can centre it + for (pass = 0; pass < 2; pass++) { + originX = 0; + originY = 0; + if (pass == 1) { + originX -= ((maxX + minX) >> 6) << 5; + originY -= ((maxY + minY) >> 6) << 5; + } + + if (design->type != RIDE_TYPE_MAZE) { + #pragma region Track + + rotation = RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32); + trackPtr = design->preview[0]; + + while (*trackPtr != 255) { + int trackType = *trackPtr; + if (trackType == 101) + trackType = 255; + + // Station track is a lighter colour + colour = RCT2_ADDRESS(0x0099BA64, uint8)[trackType * 16] & 0x10 ? 222 : 218; + + // Follow a single track piece shape + trackBlock = RCT2_ADDRESS(0x00994638, rct_preview_track*)[trackType]; + while (trackBlock->var_00 != 255) { + x = originX; + y = originY; + + switch (rotation & 3) { + case 0: + x += trackBlock->x; + y += trackBlock->y; + break; + case 1: + x += trackBlock->y; + y -= trackBlock->x; + break; + case 2: + x -= trackBlock->x; + y -= trackBlock->y; + break; + case 3: + x -= trackBlock->y; + y += trackBlock->x; + break; + } + + if (pass == 0) { + minX = min(minX, x); + maxX = max(maxX, x); + minY = min(minY, y); + maxY = max(maxY, y); + } else { + pixelX = 80 + ((y / 32) - (x / 32)) * 4; + pixelY = 38 + ((y / 32) + (x / 32)) * 2; + if (pixelX <= 160 && pixelY <= 75) { + pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX]; + + bits = trackBlock->var_08 << (rotation & 3); + bits = (bits & 0x0F) | ((bits & 0xF0) >> 4); + + for (i = 0; i < 4; i++) { + if (bits & 1) pixel[338 + i] = colour; + if (bits & 2) pixel[168 + i] = colour; + if (bits & 4) pixel[ 2 + i] = colour; + if (bits & 8) pixel[172 + i] = colour; + } + } + } + trackBlock++; + } + + // Change rotation and next position based on track curvature + rotation &= 3; + trackType *= 10; + switch (rotation) { + case 0: + originX += RCT2_GLOBAL(0x009968C1 + trackType, sint16); + originY += RCT2_GLOBAL(0x009968C3 + trackType, sint16); + break; + case 1: + originX += RCT2_GLOBAL(0x009968C3 + trackType, sint16); + originY -= RCT2_GLOBAL(0x009968C1 + trackType, sint16); + break; + case 2: + originX -= RCT2_GLOBAL(0x009968C1 + trackType, sint16); + originY -= RCT2_GLOBAL(0x009968C3 + trackType, sint16); + break; + case 3: + originX -= RCT2_GLOBAL(0x009968C3 + trackType, sint16); + originY += RCT2_GLOBAL(0x009968C1 + trackType, sint16); + break; + } + rotation += RCT2_ADDRESS(0x009968BC, uint8)[trackType] - RCT2_ADDRESS(0x009968BB, uint8)[trackType]; + rotation &= 3; + if (RCT2_ADDRESS(0x009968BC, uint8)[trackType] & 4) + rotation |= 4; + if (!(rotation & 4)) { + originX += RCT2_GLOBAL(0x00993CCC + (rotation * 4), sint16); + originY += RCT2_GLOBAL(0x00993CCE + (rotation * 4), sint16); + } + trackPtr += 2; + } + + #pragma endregion + } else { + #pragma region Maze + + rotation = (RCT2_GLOBAL(0x00F440AE, uint8) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) & 3; + mazeBlock = (rct_preview_maze*)design->preview[0]; + while (mazeBlock->all != 0) { + x = mazeBlock->x * 32; + y = mazeBlock->y * 32; + switch (rotation) { + case 1: + x = -x; + swap(x, y); + break; + case 2: + x = -x; + y = -y; + break; + case 3: + x = -x; + swap(x, y); + break; + } + x += originX; + y += originY; + + // Entrance or exit is a lighter colour + colour = mazeBlock->type == 8 || mazeBlock->type == 128 ? 222 : 218; + + if (pass == 0) { + minX = min(minX, x); + maxX = max(maxX, x); + minY = min(minY, y); + maxY = max(maxY, y); + } else { + pixelX = 80 + ((y / 32) - (x / 32)) * 4; + pixelY = 38 + ((y / 32) + (x / 32)) * 2; + if (pixelX <= 160 && pixelY <= 75) { + pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX]; + + for (i = 0; i < 4; i++) { + pixel[338 + i] = colour; + pixel[168 + i] = colour; + pixel[ 2 + i] = colour; + pixel[172 + i] = colour; + } + } + } + mazeBlock++; + } + + #pragma endregion + } + } } /**