From 6adb384a7eef4a7069c0523aaad9c111f8300d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 24 Jul 2015 23:40:04 +0200 Subject: [PATCH] Refactoring in news_item Now news_items are fetched only with exposed calls, which add a layer of simple checks. I also switched few places to access a read-only version of news_item. --- src/management/news_item.c | 135 ++++++++++++++++++++++-------- src/management/news_item.h | 4 + src/peep/peep.h | 2 +- src/windows/game_bottom_toolbar.c | 16 ++-- src/windows/news.c | 43 +++++----- 5 files changed, 132 insertions(+), 68 deletions(-) diff --git a/src/management/news_item.c b/src/management/news_item.c index 13e33b9d50..787dbbdeca 100644 --- a/src/management/news_item.c +++ b/src/management/news_item.c @@ -28,11 +28,42 @@ #include "../world/sprite.h" #include "news_item.h" -rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); - +rct_news_item *gNewsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); void window_game_bottom_toolbar_invalidate_news_item(); static int news_item_get_new_history_slot(); +#define MAX_NEWS 60 + +bool news_item_is_valid_idx(const uint8 idx) +{ + if (idx > MAX_NEWS) + { + log_error("Tried to get news item past MAX_NEWS."); + return false; + } + return true; +} + +rct_news_item *news_item_get(const uint8 idx) +{ + if (news_item_is_valid_idx(idx)) + { + return &gNewsItems[idx]; + } else { + return NULL; + } +} + +bool news_item_is_empty(const uint8 idx) +{ + return news_item_get(idx)->type == NEWS_ITEM_NULL; +} + +bool news_item_is_queue_empty() +{ + return news_item_is_empty(0); +} + /** * * rct2: 0x0066DF32 @@ -40,16 +71,41 @@ static int news_item_get_new_history_slot(); void news_item_init_queue() { int i; - rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); - newsItems[0].type = NEWS_ITEM_NULL; - newsItems[11].type = NEWS_ITEM_NULL; + news_item_get(0)->type = NEWS_ITEM_NULL; + news_item_get(11)->type = NEWS_ITEM_NULL; + // Throttles for warning types (PEEP_*_WARNING) for (i = 0; i < 16; i++) RCT2_ADDRESS(0x01358750, uint8)[i] = 0; window_game_bottom_toolbar_invalidate_news_item(); } +static void news_item_tick_current() +{ + int ticks; + ticks = news_item_get(0)->ticks++; + if (ticks == 1 && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) { + // Play sound + sound_play_panned(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0); + } +} + +static bool news_item_is_current_old() +{ + int remove_time = 320; + if (!news_item_is_empty(5) && + !news_item_is_empty(4) && + !news_item_is_empty(3) && + !news_item_is_empty(2)) + remove_time = 256; + + if (news_item_get(0)->ticks >= remove_time) + return true; + + return false; +} + /** * * rct2: 0x0066E252 @@ -57,7 +113,6 @@ void news_item_init_queue() void news_item_update_current() { short ax, bx, remove_time; - rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); get_system_time(); @@ -91,27 +146,16 @@ void news_item_update_current() 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) + if (news_item_is_queue_empty()) return; 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(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2, 0, 0, 0); - } + news_item_tick_current(); // 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) + if (news_item_is_current_old()) news_item_close_current(); } @@ -125,7 +169,7 @@ void news_item_close_current() 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) + if (news_item_is_queue_empty()) return; // Find an available history news item slot for current message @@ -135,7 +179,7 @@ void news_item_close_current() newsItems[i] = newsItems[0]; // Set the end of the end of the history list - if (i < 60) + if (i < MAX_NEWS) newsItems[i + 1].type = NEWS_ITEM_NULL; // Invalidate the news window @@ -150,6 +194,15 @@ void news_item_close_current() window_game_bottom_toolbar_invalidate_news_item(); } +static void news_item_shift_history_up() +{ + const int history_idx = 11; + rct_news_item *history_start = news_item_get(history_idx); + const size_t count = sizeof(rct_news_item) * (MAX_NEWS - 1 - history_idx); + memmove(history_start, history_start + 1, count); +} + + /** * Finds a spare history slot or replaces an existing one if there are no spare * slots available. @@ -157,17 +210,15 @@ void news_item_close_current() static 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) + for (i = 11; i <= MAX_NEWS; i++) + if (news_item_is_empty(i)) return i; // Dequeue the first history news item, shift history up - for (i = 11; i < 60; i++) - newsItems[i] = newsItems[i + 1]; - return 60; + news_item_shift_history_up(); + return MAX_NEWS; } /** @@ -264,7 +315,7 @@ void news_item_add_to_queue_raw(uint8 type, const char *text, uint32 assoc) // find first open slot while (newsItem->type != NEWS_ITEM_NULL) { - if (newsItem + 1 >= (rct_news_item*)0x13CB1CC) + if (newsItem + 1 >= (rct_news_item*)0x13CB1CC) // &news_list[10] news_item_close_current(); else newsItem++; @@ -358,24 +409,36 @@ void news_item_open_subject(int type, int subject) * rct2: 0x0066E407 */ void news_item_disable_news(uint8 type, uint32 assoc) { - rct_news_item* newsItem = newsItems; - while (newsItem->type != NEWS_ITEM_NULL) { + // TODO: write test invalidating windows + int i; + for (i = 0; i < 11; i++) + { + if (!news_item_is_empty(i)) + { + rct_news_item * const newsItem; if (type == newsItem->type && assoc == newsItem->assoc) { newsItem->flags |= 0x1; - if (newsItem == RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)) { + if (i == 0) { window_game_bottom_toolbar_invalidate_news_item(); } } - newsItem++; + } else { + break; + } } - newsItem = &newsItems[11]; //0x13CB2D8 - while (newsItem->type != NEWS_ITEM_NULL) { + for (i = 11; i <= MAX_NEWS; i++) + { + if (!news_item_is_empty(i)) + { + rct_news_item * const newsItem = news_item_get(i); if (type == newsItem->type && assoc == newsItem->assoc) { newsItem->flags |= 0x1; window_invalidate_by_class(WC_RECENT_NEWS); } - newsItem++; + } else { + break; + } } } diff --git a/src/management/news_item.h b/src/management/news_item.h index 34d4459147..c998f6ce31 100644 --- a/src/management/news_item.h +++ b/src/management/news_item.h @@ -60,5 +60,9 @@ void news_item_add_to_queue(uint8 type, rct_string_id string_id, uint32 assoc); void news_item_add_to_queue_raw(uint8 type, const char *text, uint32 assoc); void news_item_open_subject(int type, int subject); void news_item_disable_news(uint8 type, uint32 assoc); +rct_news_item *news_item_get(const uint8 idx); +bool news_item_is_empty(const uint8 idx); +bool news_item_is_queue_empty(); +bool news_item_is_valid_idx(const uint8 idx); #endif diff --git a/src/peep/peep.h b/src/peep/peep.h index 5399d760b1..8b0f89cebb 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -557,7 +557,7 @@ enum { #define GET_PEEP(sprite_index) &(g_sprite_list[sprite_index].peep) /** - * Helper macro loop for enumerating through all the non null rides. To avoid needing a end loop counterpart, statements are + * Helper macro loop for enumerating through all the peeps. To avoid needing a end loop counterpart, statements are * applied in tautology if statements. */ #define FOR_ALL_PEEPS(sprite_index, peep) \ diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index 549ec4c3af..60052aff9a 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -182,15 +182,15 @@ static void window_game_bottom_toolbar_mouseup(rct_window *w, int widgetIndex) news_item_close_current(); break; case WIDX_NEWS_SUBJECT: - newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]); + newsItem = news_item_get(0); news_item_open_subject(newsItem->type, newsItem->assoc); break; case WIDX_NEWS_LOCATE: - newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]); - if (newsItem->type == NEWS_ITEM_NULL) + if (news_item_is_queue_empty()) break; { + newsItem = news_item_get(0); int x, y, z; int subject = newsItem->assoc; @@ -268,12 +268,12 @@ static void window_game_bottom_toolbar_invalidate(rct_window *w) window_game_bottom_toolbar_widgets[WIDX_LEFT_INSET].type = WWT_EMPTY; window_game_bottom_toolbar_widgets[WIDX_RIGHT_INSET].type = WWT_EMPTY; - newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]); - if (newsItem->type == 0) { + if (news_item_is_queue_empty()) { window_game_bottom_toolbar_widgets[WIDX_MIDDLE_INSET].type = WWT_EMPTY; window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].type = WWT_EMPTY; window_game_bottom_toolbar_widgets[WIDX_NEWS_LOCATE].type = WWT_EMPTY; } else { + newsItem = news_item_get(0); window_game_bottom_toolbar_widgets[WIDX_MIDDLE_INSET].type = WWT_25; window_game_bottom_toolbar_widgets[WIDX_NEWS_SUBJECT].type = WWT_FLATBTN; window_game_bottom_toolbar_widgets[WIDX_NEWS_LOCATE].type = WWT_FLATBTN; @@ -320,7 +320,7 @@ static void window_game_bottom_toolbar_invalidate(rct_window *w) void window_game_bottom_toolbar_invalidate_news_item() { window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].type = - RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0].type == NEWS_ITEM_NULL ? WWT_EMPTY : WWT_IMGBTN; + news_item_is_queue_empty() ? WWT_EMPTY : WWT_IMGBTN; widget_invalidate_by_class(WC_BOTTOM_TOOLBAR, WIDX_MIDDLE_OUTSET); } @@ -353,7 +353,7 @@ static void window_game_bottom_toolbar_paint(rct_window *w, rct_drawpixelinfo *d window_game_bottom_toolbar_draw_left_panel(dpi, w); window_game_bottom_toolbar_draw_right_panel(dpi, w); - if (RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0].type != 0) + if (!news_item_is_queue_empty()) window_game_bottom_toolbar_draw_news_item(dpi, w); else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8)) window_game_bottom_toolbar_draw_tutorial_text(dpi, w); @@ -509,7 +509,7 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc rct_widget *middleOutsetWidget; middleOutsetWidget = &window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET]; - newsItem = &(RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item)[0]); + newsItem = news_item_get(0); // Current news item gfx_fill_rect_inset( diff --git a/src/windows/news.c b/src/windows/news.c index 71e4d5a420..3c54c736c4 100644 --- a/src/windows/news.c +++ b/src/windows/news.c @@ -140,7 +140,6 @@ static void window_news_mouseup(rct_window *w, int widgetIndex) static void window_news_update(rct_window *w) { int i, j, x, y, z; - rct_news_item *newsItems; if (w->news.var_480 == -1) return; @@ -150,22 +149,22 @@ static void window_news_update(rct_window *w) window_invalidate(w); sound_play_panned(SOUND_CLICK_2, w->x + (w->width / 2), 0, 0, 0); - newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); j = w->news.var_480; w->news.var_480 = -1; for (i = 11; i < 61; i++) { - if (newsItems[i].type == NEWS_ITEM_NULL) + if (news_item_is_empty(i)) return; if (j == 0) { - if (newsItems[i].flags & 1) + rct_news_item * const newsItem = news_item_get(i); + if (newsItem->flags & 1) return; if (w->news.var_482 == 1) { - news_item_open_subject(newsItems[i].type, newsItems[i].assoc); + news_item_open_subject(newsItem->type, newsItem->assoc); return; } else if (w->news.var_482 > 1) { - news_item_get_subject_location(newsItems[i].type, newsItems[i].assoc, &x, &y, &z); + news_item_get_subject_location(newsItem->type, newsItem->assoc, &x, &y, &z); if (x != SPRITE_LOCATION_NULL) if ((w = window_get_main()) != NULL) window_scroll_to_location(w, x, y, z); @@ -183,11 +182,10 @@ static void window_news_update(rct_window *w) static void window_news_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) { int i; - rct_news_item *newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); *height = 0; for (i = 11; i < 61; i++) { - if (newsItems[i].type == NEWS_ITEM_NULL) + if (news_item_is_empty(i)) break; *height += 42; @@ -201,16 +199,15 @@ static void window_news_scrollgetsize(rct_window *w, int scrollIndex, int *width static void window_news_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { int i, buttonIndex; - rct_news_item *newsItems; buttonIndex = 0; - newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); for (i = 11; i < 61; i++) { - if (newsItems[i].type == NEWS_ITEM_NULL) + if (news_item_is_empty(i)) break; if (y < 42) { - if (newsItems[i].flags & 1) { + rct_news_item * const newsItem = news_item_get(i); + if (newsItem->flags & 1) { buttonIndex = 0; break; } else if (y < 14) { @@ -223,12 +220,12 @@ static void window_news_scrollmousedown(rct_window *w, int scrollIndex, int x, i buttonIndex = 0; break; } else if (x < 351) { - if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItems[i].type] & 2) { + if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 2) { buttonIndex = 1; break; } } else if (x < 376) { - if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItems[i].type] & 1) { + if (RCT2_ADDRESS(0x0097BE7C, uint8)[newsItem->type] & 1) { buttonIndex = 2; break; } @@ -276,13 +273,11 @@ static void window_news_invalidate(rct_window *w) static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { int i, x, y, yy, press; - rct_news_item *newsItems, *newsItem, *newsItem2; y = 0; - newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); for (i = 11; i < 61; i++) { - newsItem = &newsItems[i]; - if (newsItem->type == NEWS_ITEM_NULL) + rct_news_item * const newsItem = news_item_get(i); + if (news_item_is_empty(i)) break; if (y >= dpi->y + dpi->height) break; @@ -313,8 +308,9 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s press = 0; if (w->news.var_480 != -1) { - newsItem2 = &newsItems[11 + w->news.var_480]; - if (newsItem == newsItem2 && w->news.var_482 == 1) + const uint8 idx = 11 + w->news.var_480; + news_item_is_valid_idx(idx); + if (i == idx && w->news.var_482 == 1) press = 0x20; } gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press); @@ -376,8 +372,9 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s press = 0; if (w->news.var_480 != -1) { - newsItem2 = &newsItems[11 + w->news.var_480]; - if (newsItem == newsItem2 && w->news.var_482 == 2) + const uint8 idx = 11 + w->news.var_480; + news_item_is_valid_idx(idx); + if (i == idx && w->news.var_482 == 2) press = 0x20; } gfx_fill_rect_inset(dpi, x, yy, x + 23, yy + 23, w->colours[2], press); @@ -386,4 +383,4 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s y += 42; } -} \ No newline at end of file +}