diff --git a/src/addresses.h b/src/addresses.h index 027d61ab19..f5b46b9d41 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -85,7 +85,9 @@ #define RCT2_ADDRESS_VIEWPORT_LIST 0x014234BC #define RCT2_ADDRESS_NEW_VIEWPORT_PTR 0x01423570 +#define RCT2_ADDRESS_OS_TIME_MONTH 0x01423A04 #define RCT2_ADDRESS_OS_TOTALPHYS 0x01423B5C +#define RCT2_ADDRESS_OS_TIME_DAY 0x01424304 static void RCT2_CALLPROC_EBPSAFE(int address) { diff --git a/src/gfx.c b/src/gfx.c index 7b46886f0d..1f9fd72e13 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -159,4 +159,17 @@ void gfx_draw_string_centred(rct_drawpixelinfo *dpi, int format, int x, int y, i void gfx_invalidate_screen() { RCT2_CALLPROC_EBPSAFE(0x006ED7E5); +} + +/** + * + * rct2: 0x006E732D + * left (ax) + * top (bx) + * right (dx) + * bottom (bp) + */ +void gfx_set_dirty_blocks(int left, int top, int right, int bottom) +{ + RCT2_CALLPROC_X(0x006E732D, left, top, 0, right, 0, 0, bottom); } \ No newline at end of file diff --git a/src/gfx.h b/src/gfx.h index 6a66a863f4..b34197e2ca 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -66,7 +66,7 @@ int gfx_get_string_width(char *buffer); int clip_text(char *buffer, int width); void gfx_fill_rect_inset(rct_drawpixelinfo *dpi, short left, short top, short right, short bottom, int colour, short _si); -void gfx_set_dirty_blocks(short left, short top, short right, short bottom); +void gfx_set_dirty_blocks(int left, int top, int right, int bottom); void gfx_draw_dirty_blocks(); void gfx_redraw_screen_rect(short left, short top, short right, short bottom); void gfx_invalidate_screen(); diff --git a/src/news_item.c b/src/news_item.c index f0037c5b21..e51b5ab0a8 100644 --- a/src/news_item.c +++ b/src/news_item.c @@ -21,6 +21,7 @@ #include "addresses.h" #include "news_item.h" #include "rct2.h" +#include "window.h" /** * @@ -37,4 +38,123 @@ void news_item_init_queue() RCT2_ADDRESS(0x01358750, uint8)[i] = 0; RCT2_CALLPROC_EBPSAFE(0x0066BB79); // window_game_bottom_toolbar_invalidate_news_item(); +} + +/** + * + * rct2: 0x0066E252 + */ +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); + + // get_system_time(); + + ax = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16); + bx = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16); + if (bx != RCT2_GLOBAL(0x009DEA6B, sint16)) { + bx--; + if (bx == 0) + bx = 12; + if (bx != RCT2_GLOBAL(0x009DEA6B, sint16) || ax == 1) { + // loc_66E2AE + RCT2_GLOBAL(0x013573DC, sint32) = 10000; + if (RCT2_GLOBAL(0x013573DC, sint32) >= 0) + RCT2_GLOBAL(0x013573DC, sint32) = -RCT2_GLOBAL(0x013573DC, sint32); + } + } else { + if (ax != RCT2_GLOBAL(0x009DEA69, sint16)) { + ax--; + if (ax != RCT2_GLOBAL(0x009DEA69, sint16)) { + // loc_66E2AE + RCT2_GLOBAL(0x013573DC, sint32) = 10000; + if (RCT2_GLOBAL(0x013573DC, sint32) >= 0) + RCT2_GLOBAL(0x013573DC, sint32) = -RCT2_GLOBAL(0x013573DC, sint32); + } + } + } + + RCT2_GLOBAL(0x009DEA69, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16); + RCT2_GLOBAL(0x009DEA6B, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16); + + // Check if there is a current news item + if (newsItems[0].type == 0) + return; + + RCT2_CALLPROC_EBPSAFE(0x0066BB79); // window_game_bottom_toolbar_invalidate_news_item(); + + // Update the current news item + newsItems[0].ticks++; + if (newsItems[0].ticks == 1 && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) { + // Play sound + sound_play_panned(39, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2); + } + + // Removal of current news item + remove_time = 320; + if (newsItems[2].type != 0 && + newsItems[3].type != 0 && + newsItems[4].type != 0 && + newsItems[5].type != 0) + remove_time = 256; + + if (newsItems[0].ticks >= remove_time) + news_item_close_current(); +} + +/** + * + * rct2: 0x0066E377 + */ +void news_item_close_current() +{ + int i; + rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); + + // Check if there is a current message + if (newsItems[0].type == NEWS_ITEM_NULL) + return; + + // Find an available history news item slot for current message + i = news_item_get_new_history_slot(); + + // Set the history news item slot to the current news item + newsItems[i] = newsItems[0]; + + // Set the end of the end of the history list + if (i < 60) + newsItems[i + 1].type = NEWS_ITEM_NULL; + + // Invalidate the news window + window_invalidate_by_id(WC_RECENT_NEWS, 0); + + // Dequeue the current news item, shift news up + for (i = 0; i < 10; i++) + newsItems[i] = newsItems[i + 1]; + newsItems[10].type = NEWS_ITEM_NULL; + + // Invalidate current news item bar + RCT2_CALLPROC_EBPSAFE(0x0066BB79); // window_game_bottom_toolbar_invalidate_news_item(); +} + +/** + * Finds a spare history slot or replaces an existing one if there are no spare + * slots available. + */ +int news_item_get_new_history_slot() +{ + int i; + rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); + + // Find an available history news item slot + for (i = 11; i < 61; i++) + if (newsItems[i].type == NEWS_ITEM_NULL) + return i; + + // Dequeue the first history news item, shift history up + for (i = 11; i < 60; i++) + newsItems[i] = newsItems[i + 1]; + return 60; } \ No newline at end of file diff --git a/src/news_item.h b/src/news_item.h index c7effe25a8..87b6c682b5 100644 --- a/src/news_item.h +++ b/src/news_item.h @@ -54,5 +54,6 @@ typedef struct { } rct_news_item; void news_item_init_queue(); +void news_item_close_current(); #endif \ No newline at end of file diff --git a/src/rct2.c b/src/rct2.c index f9d73e053a..2dcfe952a9 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -105,7 +105,7 @@ void rct2_init() osinterface_init(); RCT2_CALLPROC_EBPSAFE(0x006BA8E0); // init_audio(); RCT2_CALLPROC_EBPSAFE(0x006E6EAC); // viewport_init_all(); - RCT2_CALLPROC_EBPSAFE(0x0066DF32); // news_item_init_queue() + news_item_init_queue(); RCT2_CALLPROC_EBPSAFE(0x006C45E7); // get local time RCT2_CALLPROC_EBPSAFE(0x00667104); RCT2_CALLPROC_EBPSAFE(0x006C4209); diff --git a/src/window.c b/src/window.c index fd423e1bb5..d9dab19d82 100644 --- a/src/window.c +++ b/src/window.c @@ -20,6 +20,7 @@ #include "addresses.h" #include "audio.h" +#include "gfx.h" #include "rct2.h" #include "widget.h" #include "window.h" @@ -193,10 +194,45 @@ rct_window *window_find_by_id(rct_windowclass cls, rct_windownumber number) */ void window_invalidate(rct_window *window) { - RCT2_CALLPROC_X(0x006EB31A, 0, 0, 0, 0, window, 0, 0); + if (window != NULL) + gfx_set_dirty_blocks(window->x, window->y, window->x + window->width, window->y + window->height); +} - // if (window != NULL) - // gfx_set_dirty_blocks(window->x, window->y, window->x + window->width, window->y + window->height); +/** + * + * rct2: 0x006EC3AC + * + * @param cls (ax) + * @param number (bx) + */ +void window_invalidate_by_id(uint16 cls, rct_windownumber number) +{ + rct_window* w; + rct_widget* widget; + uint8 widgetIndex; + + if (cls & 0x80) { + widgetIndex = cls >> 8; + cls &= 0x7F; + for (w = RCT2_FIRST_WINDOW; w < RCT2_NEW_WINDOW; w++) { + if (w->classification == cls && w->number == number) { + widget = &w->widgets[widgetIndex]; + if (widget->left != -2) { + gfx_set_dirty_blocks(w->x + widget->left, w->y + widget->top, + w->x + widget->right + 1, w->y + widget->bottom + 1); + } + } + } + } else if (cls & 0x40) { + cls &= 0xBF; + for (w = RCT2_FIRST_WINDOW; w < RCT2_NEW_WINDOW; w++) + if (w->classification == cls) + window_invalidate(w); + } else { + for (w = RCT2_FIRST_WINDOW; w < RCT2_NEW_WINDOW; w++) + if (w->classification == cls && w->number == number) + window_invalidate(w); + } } /** diff --git a/src/window.h b/src/window.h index f9409f03b9..98bc19659a 100644 --- a/src/window.h +++ b/src/window.h @@ -271,6 +271,7 @@ rct_window *window_create(int x, int y, int width, int height, uint32 *event_han void window_close(rct_window *window); rct_window *window_find_by_id(rct_windowclass cls, rct_windownumber number); void window_invalidate(rct_window *window); +void window_invalidate_by_id(uint16 cls, rct_windownumber number); void window_init_scroll_widgets(rct_window *w); int window_get_scroll_data_index(rct_window *w, int widget_index);