From 286b43355a6f1c67db4cda0137a5e0db5e0e9656 Mon Sep 17 00:00:00 2001 From: IntelOrca Date: Tue, 8 Apr 2014 17:52:39 +0100 Subject: [PATCH] start work on window drawing --- projects/openrct2.vcxproj | 1 + src/addresses.h | 8 +++ src/game.c | 4 +- src/gfx.c | 101 +++++++++++++++++++++++++++++++++++++- src/news_item.c | 8 +-- src/news_item.h | 1 + src/rct2.c | 25 ++++++++-- src/rct2.h | 1 + src/scenario.c | 1 - src/title.c | 2 +- src/viewport.c | 70 +++++++++++++++++++++++++- src/viewport.h | 4 ++ src/window.c | 67 +++++++++++++++++++++++-- src/window.h | 3 ++ 14 files changed, 278 insertions(+), 18 deletions(-) diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 991a80aa18..95aba80932 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -125,6 +125,7 @@ true MultiThreaded 1Byte + 4013 true diff --git a/src/addresses.h b/src/addresses.h index 1257d1daab..df031c8785 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -61,6 +61,10 @@ #define RCT2_ADDRESS_RUN_INTRO_TICK_PART 0x009AC319 +#define RCT2_ADDRESS_INPUT_STATE 0x009DE51D +#define RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS 0x009DE51F +#define RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER 0x009DE520 + #define RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS 0x009DE533 #define RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER 0x009DE534 #define RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX 0x009DE536 @@ -73,6 +77,8 @@ #define RCT2_ADDRESS_PLACE_OBJECT_MODIFIER 0x009DEA70 #define RCT2_ADDRESS_ON_TUTORIAL 0x009DEA71 +#define RCT2_ADDRESS_WINDOW_DPI 0x009DEA74 + #define RCT2_ADDRESS_CMDLINE 0x009E2D98 #define RCT2_ADDRESS_G1_ELEMENTS 0x009EBD28 @@ -104,6 +110,8 @@ #define RCT2_ADDRESS_OS_TIME_MONTH 0x01423A04 #define RCT2_ADDRESS_OS_TOTALPHYS 0x01423B5C #define RCT2_ADDRESS_OS_TIME_DAY 0x01424304 +#define RCT2_ADDRESS_OS_TIME_YEAR 0x01424320 +#define RCT2_ADDRESS_OS_TIME_DAYOFWEEK 0x01423B20 static void RCT2_CALLPROC_EBPSAFE(int address) { diff --git a/src/game.c b/src/game.c index cc32a7a89d..10344b06ed 100644 --- a/src/game.c +++ b/src/game.c @@ -79,7 +79,7 @@ void game_update() RCT2_CALLPROC_EBPSAFE(0x006EE77A); - RCT2_CALLPROC_EBPSAFE(0x006E77A1); // window_refresh_all(); + window_update_all(); RCT2_GLOBAL(0x01388698, uint16)++; @@ -136,7 +136,7 @@ void game_logic_update() RCT2_CALLPROC_EBPSAFE(0x0067009A); // Update windows - window_update_all(); + window_dispatch_update_all(); if (RCT2_GLOBAL(0x009AC31B, uint8) != 0) { _bx = 3010; diff --git a/src/gfx.c b/src/gfx.c index 1f9fd72e13..5c3d330eeb 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -24,6 +24,9 @@ #include "addresses.h" #include "gfx.h" #include "rct2.h" +#include "window.h" + +uint8 _screenDirtyBlocks[5120]; /** * @@ -171,5 +174,101 @@ void gfx_invalidate_screen() */ void gfx_set_dirty_blocks(int left, int top, int right, int bottom) { - RCT2_CALLPROC_X(0x006E732D, left, top, 0, right, 0, 0, bottom); + int x, y; + uint8 *screenDirtyBlocks = RCT2_ADDRESS(0x00EDE408, uint8); + + left = max(left, 0); + top = max(top, 0); + right = min(right, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16)); + bottom = min(bottom, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16)); + + if (left >= right) + return; + if (top >= bottom) + return; + + right--; + bottom--; + + left >>= RCT2_GLOBAL(0x009ABDF0, sint8); + right >>= RCT2_GLOBAL(0x009ABDF0, sint8); + top >>= RCT2_GLOBAL(0x009ABDF1, sint8); + bottom >>= RCT2_GLOBAL(0x009ABDF1, sint8); + + for (y = top; y <= bottom; y++) + for (x = left; x <= right; x++) + screenDirtyBlocks[y * RCT2_GLOBAL(0x009ABDE8, sint32) + x] = 0xFF; +} + +/** +* +* rct2: 0x006E73BE +*/ +void gfx_draw_dirty_blocks() +{ + int i, x, y, yy, yyy; + short left, top, right, bottom; + uint8 *screenDirtyBlocks = RCT2_ADDRESS(0x00EDE408, uint8); + + x = y = i = 0; + for (x = 0; x < RCT2_GLOBAL(0x009ABDE8, sint32); x++) { + for (y = 0; y < RCT2_GLOBAL(0x009ABDEC, sint32); y++) { + if (screenDirtyBlocks[y * RCT2_GLOBAL(0x009ABDE8, sint32) + x] == 0) + continue; + + for (yy = y; yy < RCT2_GLOBAL(0x009ABDEC, sint32); yy++) + if (screenDirtyBlocks[yy * RCT2_GLOBAL(0x009ABDE8, sint32) + x] == 0) + break; + yy--; + + // Reset the dirty blocks + for (yyy = y; yyy <= yy; yyy += RCT2_GLOBAL(0x009ABDE8, sint32)) + screenDirtyBlocks[yyy * RCT2_GLOBAL(0x009ABDE8, sint32) + x] = 0; + + left = x * RCT2_GLOBAL(0x009ABDE4, sint16); + top = y * RCT2_GLOBAL(0x009ABDE6, sint16); + right = ((x + 1) * RCT2_GLOBAL(0x009ABDE4, sint16)); + bottom = ((yy + 1) * RCT2_GLOBAL(0x009ABDE4, sint16)); + if (left < RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) && top < RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16)) { + right = min(right, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16)); + bottom = min(bottom, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, sint16)); + gfx_redraw_screen_rect(left, top, right, bottom); + } + } + } +} + +/** + * + * rct2: 0x006E7499 + * left (ax) + * top (bx) + * right (dx) + * bottom (bp) + */ +void gfx_redraw_screen_rect(short left, short top, short right, short bottom) +{ + rct_window* w; + rct_drawpixelinfo *screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); + rct_drawpixelinfo *windowDPI = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_DPI, rct_drawpixelinfo); + + // Unsure what this does + RCT2_CALLPROC_X(0x00683326, left, top, right - 1, bottom - 1, 0, 0, 0); + + windowDPI->bits = screenDPI->bits + left + ((screenDPI->width + screenDPI->pitch) * top); + windowDPI->x = left; + windowDPI->y = top; + windowDPI->width = right - left; + windowDPI->height = bottom - top; + windowDPI->pitch = screenDPI->width + screenDPI->pitch + left - right; + + for (w = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window); w < RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); w++) { + if (w->flags & WF_TRANSPARENT) + continue; + if (right <= w->x || bottom <= w->y) + continue; + if (left >= w->x + w->width || top >= w->y + w->height) + continue; + window_draw(w, left, top, right, bottom); + } } \ No newline at end of file diff --git a/src/news_item.c b/src/news_item.c index ee9efdf9d3..2d40180b94 100644 --- a/src/news_item.c +++ b/src/news_item.c @@ -19,10 +19,13 @@ *****************************************************************************/ #include "addresses.h" +#include "audio.h" #include "news_item.h" #include "rct2.h" #include "window.h" +static int news_item_get_new_history_slot(); + /** * * rct2: 0x0066DF32 @@ -46,11 +49,10 @@ void news_item_init_queue() */ void news_item_update_current() { - int _ebp; short ax, bx, remove_time; rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); - RCT2_CALLPROC_EBPSAFE(0x00407671); // get_system_time() + get_system_time(); ax = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16); bx = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16); @@ -143,7 +145,7 @@ void news_item_close_current() * Finds a spare history slot or replaces an existing one if there are no spare * slots available. */ -int news_item_get_new_history_slot() +static int news_item_get_new_history_slot() { int i; rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); diff --git a/src/news_item.h b/src/news_item.h index 87b6c682b5..6eaf56f923 100644 --- a/src/news_item.h +++ b/src/news_item.h @@ -54,6 +54,7 @@ typedef struct { } rct_news_item; void news_item_init_queue(); +void news_item_update_current(); void news_item_close_current(); #endif \ No newline at end of file diff --git a/src/rct2.c b/src/rct2.c index 43e0e3d017..552ae9312e 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -29,10 +29,12 @@ #include "game.h" #include "gfx.h" #include "intro.h" +#include "news_item.h" #include "osinterface.h" #include "rct2.h" #include "scenario.h" #include "title.h" +#include "viewport.h" void rct2_init_directories(); void rct2_startup_checks(); @@ -90,7 +92,7 @@ void rct2_init() { RCT2_GLOBAL(0x00F663AC, int) = 0; RCT2_GLOBAL(0x009AC310, char*) = RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, char*); - RCT2_CALLPROC_EBPSAFE(0x00407671); // get_system_time() + get_system_time(); RCT2_GLOBAL(0x009DEA69, short) = RCT2_GLOBAL(0x01424304, short); RCT2_GLOBAL(0x009DEA6B, short) = RCT2_GLOBAL(0x01424304, short); rct2_init_directories(); @@ -106,7 +108,7 @@ void rct2_init() RCT2_CALLPROC_EBPSAFE(0x006C19AC); osinterface_init(); RCT2_CALLPROC_EBPSAFE(0x006BA8E0); // init_audio(); - RCT2_CALLPROC_EBPSAFE(0x006E6EAC); // viewport_init_all(); + viewport_init_all(); news_item_init_queue(); RCT2_CALLPROC_EBPSAFE(0x006C45E7); // get local time RCT2_CALLPROC_EBPSAFE(0x00667104); @@ -221,7 +223,22 @@ char *get_file_path(int pathId) ebx = pathId; RCT2_CALLFUNC_X(0x00674E6C, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return ebx; + return (char*)ebx; +} + +/** + * Obtains os system time (day, month, year and day of the week). + * rct2: 0x00407671 + */ +void get_system_time() +{ + SYSTEMTIME systime; + + GetSystemTime(&systime); + RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16) = systime.wDay; + RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16) = systime.wMonth; + RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_YEAR, sint16) = systime.wYear; + RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAYOFWEEK, sint16) = systime.wDayOfWeek; } /** @@ -250,5 +267,5 @@ void *rct2_realloc(void *block, size_t numBytes) */ void rct2_free(void *block) { - return RCT2_CALLPROC_1(0x004068DE, void*, block); + RCT2_CALLPROC_1(0x004068DE, void*, block); } \ No newline at end of file diff --git a/src/rct2.h b/src/rct2.h index c9a137e9e2..0ffc2af9fc 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -115,6 +115,7 @@ enum { }; char *get_file_path(int pathId); +void get_system_time(); void *rct2_malloc(size_t numBytes); void *rct2_realloc(void *block, size_t numBytes); void rct2_free(void *block); diff --git a/src/scenario.c b/src/scenario.c index a5e0add04b..8e90feb6d9 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -65,7 +65,6 @@ void scenario_load_list() HANDLE hFindFile; WIN32_FIND_DATAA findFileData; int i; - char *src, *dst; // Load scores scenario_scores_load(); diff --git a/src/title.c b/src/title.c index 282cccff60..364640e155 100644 --- a/src/title.c +++ b/src/title.c @@ -118,7 +118,7 @@ void title_update() RCT2_CALLPROC_EBPSAFE(0x006EE77A); - RCT2_CALLPROC_EBPSAFE(0x006E77A1); // window_refresh_all(); + window_update_all(); RCT2_GLOBAL(0x01388698, uint16)++; diff --git a/src/viewport.c b/src/viewport.c index 08edd0f6c5..d51feac9b4 100644 --- a/src/viewport.c +++ b/src/viewport.c @@ -19,9 +19,77 @@ *****************************************************************************/ #include "addresses.h" +#include "gfx.h" +#include "strings.h" #include "viewport.h" +#include "window.h" +#define RCT2_FIRST_VIEWPORT (RCT2_ADDRESS(RCT2_ADDRESS_VIEWPORT_LIST, rct_viewport)) +#define RCT2_LAST_VIEWPORT (RCT2_GLOBAL(RCT2_ADDRESS_NEW_VIEWPORT_PTR, rct_viewport*) - 1) +#define RCT2_NEW_VIEWPORT (RCT2_GLOBAL(RCT2_ADDRESS_NEW_VIEWPORT_PTR, rct_viewport*)) + +/** + * + * rct2: 0x006E6EAC + */ void viewport_init_all() { - RCT2_CALLPROC_EBPSAFE(0x006E6EAC); + int i, d; + rct_g1_element *g1_element; + + // Palette from sprites? + d = 0; + for (i = 4915; i < 4947; i++) { + g1_element = &(RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[i]); + *((int*)(0x0141FC44 + d)) = *((int*)(&g1_element->offset[0xF5])); + *((int*)(0x0141FC48 + d)) = *((int*)(&g1_element->offset[0xF9])); + *((int*)(0x0141FD44 + d)) = *((int*)(&g1_element->offset[0xFD])); + d += 8; + } + + // Setting up windows + RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*) = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window); + RCT2_GLOBAL(0x01423604, sint32) = 0; + + // Setting up viewports + for (i = 0; i < 9; i++) + RCT2_FIRST_VIEWPORT[i].width = 0; + RCT2_NEW_VIEWPORT = NULL; + + // ? + RCT2_GLOBAL(0x009DE518, sint32) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_RESET; + RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1; + RCT2_GLOBAL(0x009DE550, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1; + RCT2_GLOBAL(0x009DE58A, sint16) = 0; + RCT2_GLOBAL(0x009DEA50, sint16) = -1; + RCT2_CALLPROC_EBPSAFE(0x006EE3C3); + format_string((char*)0x0141FA44, STR_CANCEL, NULL); + format_string((char*)0x0141F944, STR_OK, NULL); +} + +/** + * UNTESTED + * rct2: 0x006EE510 + */ +void viewport_update_pointers() +{ + rct_viewport *viewport; + rct_viewport **vp = &RCT2_NEW_VIEWPORT; + + for (viewport = RCT2_FIRST_VIEWPORT; viewport <= RCT2_NEW_VIEWPORT; viewport++) + if (viewport->width != 0) + *vp++ = viewport; + + *vp = NULL; +} + +/** + * + * rct2: 0x006E7A3A + */ +void viewport_update_position(rct_window *window) +{ + RCT2_CALLPROC_X(0x006E7A3A, 0, 0, 0, 0, window, 0, 0); } \ No newline at end of file diff --git a/src/viewport.h b/src/viewport.h index 762e14bc4c..672cc3345f 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -21,6 +21,10 @@ #ifndef _VIEWPORT_H_ #define _VIEWPORT_H_ +#include "window.h" + void viewport_init_all(); +void viewport_update_pointers(); +void viewport_update_position(rct_window *window); #endif \ No newline at end of file diff --git a/src/window.c b/src/window.c index d9dab19d82..e773f963a2 100644 --- a/src/window.c +++ b/src/window.c @@ -24,13 +24,17 @@ #include "rct2.h" #include "widget.h" #include "window.h" +#include "viewport.h" #define RCT2_FIRST_WINDOW (RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window)) #define RCT2_LAST_WINDOW (RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*) - 1) #define RCT2_NEW_WINDOW (RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*)) -// rct2: 0x006ED7B0 -void window_update_all() +/** + * + * rct2: 0x006ED7B0 + */ +void window_dispatch_update_all() { rct_window *w; @@ -43,6 +47,47 @@ void window_update_all() RCT2_CALLPROC_EBPSAFE(0x006EE411); } +/** + * + * rct2: 0x006E77A1 + */ +void window_update_all() +{ + rct_window* w; + + RCT2_GLOBAL(0x009E3CD8, sint32)++; + // if (RCT2_GLOBAL(0x009E3CD8, sint32) == 224 && RCT2_GLOBAL(0x009ABDF2, sint8) != 0) + // RCT2_CALLPROC(0x004067E3); // ddwindow_move_to_top_corner + + if (RCT2_GLOBAL(0x009ABDF2, sint8) == 0) + return; + + gfx_draw_dirty_blocks(); + + for (w = RCT2_FIRST_WINDOW; w < RCT2_NEW_WINDOW; w++) + if (w->viewport != NULL) + viewport_update_position(w); + + // 1000 tick update + RCT2_GLOBAL(0x009DEB7C, sint16) += RCT2_GLOBAL(0x009DE588, sint16); + if (RCT2_GLOBAL(0x009DEB7C, sint16) >= 1000) { + RCT2_GLOBAL(0x009DEB7C, sint16) = 0; + for (w = RCT2_LAST_WINDOW; w >= RCT2_FIRST_WINDOW; w--) + RCT2_CALLPROC_X(w->event_handlers[WE_UNKNOWN_07], 0, 0, 0, 0, w, 0, 0); + } + + // Border flash invalidation + for (w = RCT2_LAST_WINDOW; w >= RCT2_FIRST_WINDOW; w--) { + if (w->flags & WF_WHITE_BORDER_MASK) { + w->flags -= WF_WHITE_BORDER_ONE; + if (!(w->flags & WF_WHITE_BORDER_MASK)) + window_invalidate(w); + } + } + + RCT2_CALLPROC_X(0x006E7868, 0, 0, 0, 0, 0, RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo), 0); // process_mouse_wheel_input(); +} + /** * Opens a new window. * rct2: 0x006EACA4 @@ -140,7 +185,7 @@ void window_close(rct_window* window) return; // Call close event of window - // window_call_basic_event(window, WE_CLOSE); + RCT2_CALLPROC_X(window->event_handlers[WE_CLOSE], 0, 0, 0, 0, window, 0, 0); window = window_find_by_id(window->classification, window->number); @@ -159,8 +204,7 @@ void window_close(rct_window* window) if (num_windows > 0) memmove(window, window + 1, num_windows * sizeof(rct_window)); - // ? - RCT2_CALLPROC(0x006EE510); + viewport_update_pointers(); } /** @@ -347,4 +391,17 @@ rct_window *window_bring_to_front(rct_window *w) } return w; +} + +/** + * Draws a window that is in the specified region. + * rct2: 0x006E756C + * left (ax) + * top (bx) + * right (dx) + * bottom (bp) + */ +void window_draw(rct_window *w, int left, int top, int right, int bottom) +{ + RCT2_CALLPROC_X(0x006E756C, left, top, 0, right, w, 0, bottom); } \ No newline at end of file diff --git a/src/window.h b/src/window.h index 98bc19659a..52ea516238 100644 --- a/src/window.h +++ b/src/window.h @@ -266,6 +266,7 @@ enum { WC_CHEATS = 110, } WINDOW_CLASS; +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); void window_close(rct_window *window); @@ -278,4 +279,6 @@ int window_get_scroll_data_index(rct_window *w, int widget_index); rct_window *window_bring_to_front_by_id(rct_windowclass cls, rct_windownumber number); rct_window *window_bring_to_front(rct_window *w); +void window_draw(rct_window *w, int left, int top, int right, int bottom); + #endif \ No newline at end of file