diff --git a/src/game.c b/src/game.c index 65b25027f6..420606d585 100644 --- a/src/game.c +++ b/src/game.c @@ -619,6 +619,7 @@ static void input_mouseover(int x, int y, rct_window *w, int widgetIndex) */ static void input_mouseover_widget_check(rct_windowclass windowClass, rct_windownumber windowNumber, int widgetIndex) { + if (widgetIndex == -1) return; //Prevents invalid widgets being clicked source of bug is elsewhere // Check if widget cursor was over has changed if (windowClass != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) || windowNumber != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) || @@ -2049,9 +2050,10 @@ char save_game() * * rct2: 0x006E3879 */ -static void rct2_exit() +void rct2_exit() { RCT2_CALLPROC_EBPSAFE(0x006E3879); + //Post quit message does not work in 0x6e3879 as its windows only. } /** diff --git a/src/game.h b/src/game.h index 47d7f51ceb..6ed975bce2 100644 --- a/src/game.h +++ b/src/game.h @@ -31,5 +31,6 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb void game_load_or_quit_no_save_prompt(); int game_load_save(); char save_game(); +void rct2_exit(); #endif diff --git a/src/string_ids.c b/src/string_ids.c index 081e602b77..06b51543ad 100644 --- a/src/string_ids.c +++ b/src/string_ids.c @@ -21,6 +21,7 @@ #include #include #include "addresses.h" +#include "game.h" #include "date.h" #include "rct2.h" #include "string_ids.h" @@ -1569,6 +1570,28 @@ void format_string(char *dest, rct_string_id format, void *args) format_string_part(&dest, format, (char**)&args); } +/** + * rct2: 0x006E37F7 + * error (eax) + * format (bx) + */ +void error_string_quit(int error, rct_string_id format){ + //RCT2_CALLPROC_X(0x006E37F7, error, format, 0, 0, 0, 0, 0); + RCT2_GLOBAL(0x14241A0, uint32) = error; + RCT2_GLOBAL(0x9E2DA0, uint32) = 1; + + char* error_string = RCT2_ADDRESS(0x1424080, char); + void* args = RCT2_ADDRESS(0x13CE952, void); + *error_string = 0; + + if (format != 0xFFFF){ + format_string(error_string, format, args); + } + RCT2_GLOBAL(0x9E2D9C, uint32) = 1; + rct2_exit(); + rct2_endupdate(); +} + void generate_string_file() { FILE* f; diff --git a/src/string_ids.h b/src/string_ids.h index a13bbe7d2d..0fc81a9c64 100644 --- a/src/string_ids.h +++ b/src/string_ids.h @@ -26,6 +26,7 @@ typedef unsigned short rct_string_id; void format_string(char *dest, rct_string_id format, void *args); void generate_string_file(); void reset_saved_strings(); +void error_string_quit(int error, rct_string_id format); enum { // Font format codes diff --git a/src/viewport.c b/src/viewport.c index 1b23c7c97f..e31188e27f 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -22,6 +22,8 @@ #include "config.h" #include "gfx.h" #include "string_ids.h" +#include "sprite.h" +#include "sprites.h" #include "viewport.h" #include "window.h" @@ -71,27 +73,126 @@ void viewport_init_all() format_string((char*)0x0141FA44, STR_CANCEL, NULL); format_string((char*)0x0141F944, STR_OK, NULL); } +/** + * rct:0x006EB0C1 + * x : ax + * y : bx + * z : cx + * out_x : ax + * out_y : bx + * Converts between 3d point of a sprite to 2d coordinates for centering on that sprite + */ +void center_2d_coordinates(int x, int y, int z, int* out_x, int* out_y, rct_viewport* viewport){ + int start_x = x; + + switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)){ + case 0: + x = y - x; + y = y / 2 + start_x / 2 - z; + break; + case 1: + x = -y - x; + y = y / 2 - start_x / 2 - z; + break; + case 2: + x = -y + x; + y = -y / 2 - start_x / 2 - z; + break; + case 3: + x = y + x; + y = -y / 2 + start_x / 2 - z; + break; + } + + *out_x = x - viewport->view_width/2; + *out_y = y - viewport->view_height/2; +} /** * * rct2: 0x006EB009 + * x: ax + * y: eax (top 16) + * width: bx + * height: ebx (top 16) + * zoom: cl (8 bits) + * ecx: ecx (top 16 bits see zoom) + * edx: edx + * w: esi */ -void viewport_create(rct_window *w, int x, int y, int width, int height, int ecx, int edx) +void viewport_create(rct_window *w, int x, int y, int width, int height, int zoom, int ecx, int edx) { - x &= 0xFFFF; - y &= 0xFFFF; - RCT2_CALLPROC_X(0x006EB009, (y << 16) | x, (height << 16) | width, ecx, edx, (int)w, 0, 0); + rct_viewport* viewport; + int eax = 0xFF000001; + int ebx = -1; + + for (viewport = g_viewport_list; viewport->width != 0; viewport++){ + if (viewport >= RCT2_ADDRESS(RCT2_ADDRESS_NEW_VIEWPORT_PTR, rct_viewport)){ + error_string_quit(0xFF000001, -1); + } + } + + viewport->x = x; + viewport->y = y; + viewport->width = width; + viewport->height = height; + + if (!(edx & (1 << 30))){ + zoom = 0; + } + edx &= ~(1 << 30); + + viewport->view_width = width << zoom; + viewport->view_height = height << zoom; + viewport->zoom = zoom; + viewport->flags = 0; + + if (RCT2_GLOBAL(0x9AAC7A, uint8) & 1){ + viewport->flags |= VIEWPORT_FLAG_GRIDLINES; + } + w->viewport = viewport; + int center_x, center_y, center_z; + + if (edx & (1 << 31)){ + edx &= 0xFFFF; + w->var_4B0 = edx; + rct_sprite* sprite = &g_sprite_list[edx]; + center_x = sprite->unknown.x; + center_y = sprite->unknown.y; + center_z = sprite->unknown.z; + } + else{ + center_x = edx & 0xFFFF; + center_y = edx >> 16; + center_z = ecx >> 16; + w->var_4B0 = SPR_NONE; + } + + int view_x, view_y; + center_2d_coordinates(center_x, center_y, center_z, &view_x, &view_y, viewport); + + w->saved_view_x = view_x; + w->saved_view_y = view_y; + viewport->view_x = view_x; + viewport->view_y = view_y; + + viewport_update_pointers(); + + //x &= 0xFFFF; + //y &= 0xFFFF; + //RCT2_CALLPROC_X(0x006EB009, (y << 16) | x, (height << 16) | width, zoom, edx, (int)w, 0, 0); } /** - * UNTESTED + * * rct2: 0x006EE510 */ void viewport_update_pointers() { rct_viewport *viewport; - rct_viewport **vp = &RCT2_NEW_VIEWPORT; + rct_viewport **vp = RCT2_ADDRESS(RCT2_ADDRESS_NEW_VIEWPORT_PTR, rct_viewport*); + if (*vp == NULL) *vp = g_viewport_list; for (viewport = g_viewport_list; viewport <= RCT2_NEW_VIEWPORT; viewport++) if (viewport->width != 0) *vp++ = viewport; @@ -108,6 +209,8 @@ void viewport_update_position(rct_window *window) RCT2_CALLPROC_X(0x006E7A3A, 0, 0, 0, 0, (int)window, 0, 0); } +void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom); + /** * * rct2: 0x00685C02 @@ -172,11 +275,25 @@ void viewport_render(rct_drawpixelinfo *dpi, rct_viewport *viewport, int left, i int height = y_start - y_end; if (height > 384){ //Paint - RCT2_CALLPROC_X(0x00685CBF, x_end, y_end, height, x_start, (int)viewport, (int)dpi, y_end + 384); + viewport_paint(viewport, dpi, x_end, y_end, x_start, y_end + 384); y_end += 384; } //Paint - RCT2_CALLPROC_X(0x00685CBF, x_end, y_end, height, x_start, (int)viewport, (int)dpi, y_start); + viewport_paint(viewport, dpi, x_end, y_end, x_start, y_start); +} + +/** + * + * rct2:0x00685CBF + * eax: left + * ebx: top + * edx: right + * esi: viewport + * edi: dpi + * ebp: bottom + */ +void viewport_paint(rct_viewport* viewport, rct_drawpixelinfo* dpi, int left, int top, int right, int bottom){ + RCT2_CALLPROC_X(0x00685CBF, left, top, 0, right, (int)viewport, (int)dpi, bottom); } /** diff --git a/src/viewport.h b/src/viewport.h index 3aa6e67b35..e3893d28a8 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -46,7 +46,7 @@ enum { extern rct_viewport* g_viewport_list; void viewport_init_all(); -void viewport_create(rct_window *w, int x, int y, int width, int height, int ecx, int edx); +void viewport_create(rct_window *w, int x, int y, int width, int height, int zoom, int ecx, int edx); void viewport_update_pointers(); void viewport_update_position(rct_window *window); void viewport_render(rct_drawpixelinfo *dpi, rct_viewport *viewport, int left, int top, int right, int bottom); diff --git a/src/window_banner.c b/src/window_banner.c index 7b27b8fbe2..57d1dacc01 100644 --- a/src/window_banner.c +++ b/src/window_banner.c @@ -139,6 +139,7 @@ void window_banner_open() w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 2, (viewportWidget->bottom - viewportWidget->top) - 2, + 0, 100, // TODO: needs banner map position 100 // TODO: needs banner map position ); diff --git a/src/window_main.c b/src/window_main.c index 2ab518cc18..6be5a7a15a 100644 --- a/src/window_main.c +++ b/src/window_main.c @@ -19,72 +19,95 @@ *****************************************************************************/ #include "addresses.h" +#include "viewport.h" #include "widget.h" #include "window.h" rct_widget window_main_widgets[] = { - { WWT_VIEWPORT, 0, 0x0000, 0xFFFF, 0x0000, 0xFFFF, 0xFFFFFFFF, 0xFFFF }, + { WWT_VIEWPORT, 0, 0x0000, 0xFFFF, 0x0000, 0xFFFF, 0xFFFFFFFE, 0xFFFF }, { WIDGETS_END }, }; +void window_main_empty(){} +void window_main_paint(); + +void* window_main_events[] = { + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_empty, + window_main_paint, + window_main_empty +}; + /** - * Creates the main window and the toolbars or title screen buttons. + * Creates the main window that holds the main viewport. * rct2: 0x0066B3E8 */ void window_main_open() { rct_window* window; - rct_widget* main_widgets = (rct_widget*)0x009A9414; - main_widgets[0].right = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16); - main_widgets[0].bottom = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16); + window_main_widgets[0].right = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16); + window_main_widgets[0].bottom = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16); window = window_create( 0, 0, window_main_widgets[0].right, window_main_widgets[0].bottom, - (uint32*)0x0097C0BC, + (uint32*)window_main_events, WC_MAIN_WINDOW, WF_STICK_TO_BACK ); - window->widgets = main_widgets; + window->widgets = window_main_widgets; - // RCT2_CALLPROC_X(0x006EB009, window->x, window->y, 0x4000000, 0x0FFF0FFF, window, 0, 0); - #ifdef _MSC_VER - __asm { - mov esi, window - mov edx, 0FFF0FFFh - mov eax, [esi+2Ch] - mov ebx, [esi+30h] - mov ecx, 4000000h - push ebp - mov ebp, 6EB009h - call ebp - } - __asm { - pop ebp - or word ptr [edi+12h], 400h - } - #else - __asm__ ( "\ - \n\ - push ebx \n\ - mov esi, %[window] \n\ - mov edx, 0x0FFF0FFF \n\ - mov eax, [esi+0x2C] \n\ - mov ebx, [esi+0x30] \n\ - mov ecx, 0x4000000 \n\ - push ebp \n\ - mov ebp, 0x6EB009 \n\ - call ebp \n\ - \n\ - pop ebp \n\ - or word ptr [edi+0x12], 0x400 \n\ - pop ebx \n\ - " : [window] "+m" (window) : : "esi","edx","eax","ecx" ); - #endif - + viewport_create(window, window->x, window->y, window->width, window->height, 0, 0x40000000, 0x0FFF0FFF); + window->viewport->flags |= 0x0400; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, sint32) = 0; RCT2_GLOBAL(0x009E32B0, uint8) = 0; RCT2_GLOBAL(0x009E32B2, uint8) = 0; RCT2_GLOBAL(0x009E32B3, uint8) = 0; RCT2_GLOBAL(0x00F3EFA2, uint8) = 0; } + + +/** + * + * rct2: 0x66CCAE + * This function immediately jumps to 0x00685BE1 this is the second function + * decompiled. + */ +void window_main_paint(){ + rct_window* w; + rct_drawpixelinfo* dpi; + +#ifdef _MSC_VER + __asm mov w, esi + __asm mov dpi, edi +#else + __asm__ ( "mov %[w], esi " : [w] "+m" (w) ); + __asm__ ( "mov %[dpi], edi " : [dpi] "+m" (dpi) ); +#endif + + viewport_render(dpi, w->viewport, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height); +} diff --git a/src/window_park.c b/src/window_park.c index 2f65603d65..86a7b6b5e7 100644 --- a/src/window_park.c +++ b/src/window_park.c @@ -1166,6 +1166,7 @@ static void window_park_init_viewport(rct_window *w) w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 2, (viewportWidget->bottom - viewportWidget->top) - 2, + zr&0xFF, zr, xy );