diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 1f0a9b9fb0..5d856b42d7 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -45,6 +45,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 1e47f241f4..e1b4435a08 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -356,7 +356,6 @@ Source\Management - Source\Windows @@ -369,10 +368,6 @@ - - Libraries\libspeex - - Source\Windows @@ -381,9 +376,6 @@ - - Libraries\lodepng - Libraries\libspeex @@ -400,6 +392,29 @@ Libraries\libspeex + + Source\Drawing + + + + + Libraries\lodepng + + + + Libraries\libspeex + + + + + + Libraries\libspeex + + + + Libraries\lodepng + + diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index a240d5429f..a9dabe0648 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -112,4 +112,7 @@ void draw_string_centred_raw(rct_drawpixelinfo *dpi, int x, int y, int numLines, void gfx_draw_string_right(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y); void draw_string_right_underline(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y); +// rain +void update_rain_animation(); + #endif diff --git a/src/drawing/rain.c b/src/drawing/rain.c new file mode 100644 index 0000000000..b1660e5fb6 --- /dev/null +++ b/src/drawing/rain.c @@ -0,0 +1,239 @@ +/***************************************************************************** + * Copyright (c) 2014 + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * This file is part of OpenRCT2. + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *****************************************************************************/ + +#include "../addresses.h" +#include "../interface/window.h" +#include "drawing.h" + +typedef void(*draw_rain_func)(int left, int top, int width, int height); + +static void draw_light_rain(int left, int top, int width, int height); +static void draw_heavy_rain(int left, int top, int width, int height); + +/** + * + * rct2: 0x009AC058 + */ +const draw_rain_func draw_rain_function[] = { + NULL, + &draw_light_rain, + &draw_heavy_rain +}; + +/** + * + * rct2: 0x00684383 + */ +static void call_draw_rain_func(rct_window* w, short left, short right, short top, short bottom, uint32 draw_rain_func) +{ + rct_viewport* vp = w->viewport; + if (vp == NULL) { + return; + } + + left = max(left, vp->x); + right = min(right, vp->width); + + top = max(top, vp->y); + bottom = min(bottom, vp->height); + + if (left >= right || top >= bottom) { + return; + } + + int width = right - left; + int height = bottom - top; + + draw_rain_function[draw_rain_func](left, top, width, height); +} + +/** + * + * rct2: 0x006842AF + * From 0x00684383 on: split into call_draw_rain_func + */ +static void draw_rain_window(rct_window* original_w, short left, short right, short top, short bottom, uint32 draw_rain_func) +{ + rct_window* newWindow = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); + + rct_window* w = original_w + 1; // Start from second window + for (; ; w++) { + if (w >= newWindow) { + // Loop ended, draw rain for original_w + call_draw_rain_func(original_w, left, right, top, bottom, draw_rain_func); + return; + } + + if (right <= w->x || bottom <= w->y) { + continue; + } + + if (RCT_WINDOW_RIGHT(w) <= left || RCT_WINDOW_BOTTOM(w) <= top) { + continue; + } + + if (left >= w->x) { + break; + } + + draw_rain_window(original_w, left, w->x, top, bottom, draw_rain_func); + + left = w->x; + draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); + return; + } + + sint16 w_right = RCT_WINDOW_RIGHT(w); + if (right > w_right) { + draw_rain_window(original_w, left, w_right, top, bottom, draw_rain_func); + + left = w_right; + draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); + return; + } + + if (top < w->y) { + draw_rain_window(original_w, left, right, top, w->y, draw_rain_func); + + top = w->y; + draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); + return; + } + + sint16 w_bottom = RCT_WINDOW_BOTTOM(w); + if (bottom > w_bottom) { + draw_rain_window(original_w, left, right, top, w_bottom, draw_rain_func); + + top = w_bottom; + draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); + return; + } +} + +/** + * + * rct2: 0x00684266 + */ +static void draw_rain_animation(uint32 draw_rain_func) +{ + rct_drawpixelinfo *screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); + short left = screenDPI->x; + short right = left + screenDPI->width; + short top = screenDPI->y; + short bottom = top + screenDPI->height; + + rct_window* newWindow = (RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*)); + + for (rct_window* w = g_window_list; w < newWindow; w++) { + draw_rain_window(w, left, right, top, bottom, draw_rain_func); + } +} + +/** + * + * rct2: 0x00684218 + */ +void update_rain_animation() +{ + if (RCT2_GLOBAL(0x009ABDF2, uint8) == 0) + return; + + // Draw picked-up peep + if (RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) != 0xFFFFFFFF) { + gfx_draw_sprite( + (rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI, + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32), + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16), + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16), 0 + ); + } + + // Get rain draw function and draw rain + uint32 draw_rain_func = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8); + if (draw_rain_func > 0 && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1)) + draw_rain_animation(draw_rain_func); +} + +/** + * + * rct2: 0x00684114 + */ +static void draw_light_rain(int left, int top, int width, int height) +{ + int x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 8; + int y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 3) + 7; + y_start = -y_start; + + x_start += left; + y_start += top; + + gfx_draw_rain(left, top, width, height, x_start, y_start); + + x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 0x18; + y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 4) + 0x0D; + y_start = -y_start; + + x_start += left; + y_start += top; + gfx_draw_rain(left, top, width, height, x_start, y_start); +} + +/** + * + * rct2: 0x0068416D + */ +static void draw_heavy_rain(int left, int top, int width, int height) +{ + int x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int); + int y_start = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 5; + y_start = -y_start; + + x_start += left; + y_start += top; + + gfx_draw_rain(left, top, width, height, x_start, y_start); + + x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 0x10; + y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 6) + 5; + y_start = -y_start; + + x_start += left; + y_start += top; + + gfx_draw_rain(left, top, width, height, x_start, y_start); + + x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 8; + y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 3) + 7; + y_start = -y_start; + + x_start += left; + y_start += top; + + gfx_draw_rain(left, top, width, height, x_start, y_start); + + x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 0x18; + y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 4) + 0x0D; + y_start = -y_start; + + x_start += left; + y_start += top; + + gfx_draw_rain(left, top, width, height, x_start, y_start); +} \ No newline at end of file diff --git a/src/game.c b/src/game.c index 77d6cbd236..a17383258b 100644 --- a/src/game.c +++ b/src/game.c @@ -49,83 +49,6 @@ int gGameSpeed = 1; -typedef void(*draw_rain_func)(int left, int top, int width, int height); - -/** -* -* rct2: 0x00684114 -*/ -void draw_light_rain(int left, int top, int width, int height){ - int x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 8; - int y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 3) + 7; - y_start = -y_start; - - x_start += left; - y_start += top; - - gfx_draw_rain(left, top, width, height, x_start, y_start); - - x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 0x18; - y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 4) + 0x0D; - y_start = -y_start; - - x_start += left; - y_start += top; - gfx_draw_rain(left, top, width, height, x_start, y_start); -} - -/** -* -* rct2: 0x0068416D -*/ -void draw_heavy_rain(int left, int top, int width, int height){ - int x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int); - int y_start = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 5; - y_start = -y_start; - - x_start += left; - y_start += top; - - gfx_draw_rain(left, top, width, height, x_start, y_start); - - x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 0x10; - y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 6) + 5; - y_start = -y_start; - - x_start += left; - y_start += top; - - gfx_draw_rain(left, top, width, height, x_start, y_start); - - x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 8; - y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 3) + 7; - y_start = -y_start; - - x_start += left; - y_start += top; - - gfx_draw_rain(left, top, width, height, x_start, y_start); - - x_start = -RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) + 0x18; - y_start = (RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, int) * 4) + 0x0D; - y_start = -y_start; - - x_start += left; - y_start += top; - - gfx_draw_rain(left, top, width, height, x_start, y_start); -} - -/** -* -* rct2: 0x009AC058 -*/ -const draw_rain_func draw_rain_function[] = { - NULL, - &draw_light_rain, // Light rain - &draw_heavy_rain // Heavy rain -}; - /** * * rct2: 0x0066B5C0 (part of 0x0066B3E8) @@ -261,139 +184,7 @@ void update_palette_effects() } } -/** -* -* rct2: 0x00684383 -*/ -void call_draw_rain_func(rct_window* w, short left, short right, short top, short bottom, uint32 draw_rain_func) -{ - rct_viewport* vp = w->viewport; - if (vp == NULL) { - return; - } - left = max(left, vp->x); - right = min(right, vp->width); - - top = max(top, vp->y); - bottom = min(bottom, vp->height); - - if (left >= right || top >= bottom) { - return; - } - - int width = right - left; - int height = bottom - top; - - draw_rain_function[draw_rain_func](left, top, width, height); -} - -/** -* -* rct2: 0x006842AF -* From 0x00684383 on: split into call_draw_rain_func -*/ -void draw_rain_window(rct_window* original_w, short left, short right, short top, short bottom, uint32 draw_rain_func) -{ - rct_window* newWindow = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); - - rct_window* w = original_w + 1; // Start from second window - for (; ; w++) { - if (w >= newWindow) { - // Loop ended, draw rain for original_w - call_draw_rain_func(original_w, left, right, top, bottom, draw_rain_func); - return; - } - - if (right <= w->x || bottom <= w->y) { - continue; - } - - if (RCT_WINDOW_RIGHT(w) <= left || RCT_WINDOW_BOTTOM(w) <= top) { - continue; - } - - if (left >= w->x) { - break; - } - - draw_rain_window(original_w, left, w->x, top, bottom, draw_rain_func); - - left = w->x; - draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); - return; - } - - sint16 w_right = RCT_WINDOW_RIGHT(w); - if (right > w_right) { - draw_rain_window(original_w, left, w_right, top, bottom, draw_rain_func); - - left = w_right; - draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); - return; - } - - if (top < w->y) { - draw_rain_window(original_w, left, right, top, w->y, draw_rain_func); - - top = w->y; - draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); - return; - } - - sint16 w_bottom = RCT_WINDOW_BOTTOM(w); - if (bottom > w_bottom) { - draw_rain_window(original_w, left, right, top, w_bottom, draw_rain_func); - - top = w_bottom; - draw_rain_window(original_w, left, right, top, bottom, draw_rain_func); - return; - } -} - -/** -* -* rct2: 0x00684266 -*/ -void draw_rain_animation(uint32 draw_rain_func) -{ - rct_drawpixelinfo *screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); - short left = screenDPI->x; - short right = left + screenDPI->width; - short top = screenDPI->y; - short bottom = top + screenDPI->height; - - rct_window* newWindow = (RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*)); - - for (rct_window* w = g_window_list; w < newWindow; w++) { - draw_rain_window(w, left, right, top, bottom, draw_rain_func); - } -} - -/** - * - * rct2: 0x00684218 - */ -void update_rain_animation() -{ - if (RCT2_GLOBAL(0x009ABDF2, uint8) == 0) - return; - - // Draw picked-up peep - if (RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) != 0xFFFFFFFF) { - gfx_draw_sprite( - (rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI, - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32), - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16), - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16), 0 - ); - } - - // Get rain draw function and draw rain - uint32 draw_rain_func = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8); - if (draw_rain_func > 0 && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1)) - draw_rain_animation(draw_rain_func); -} void game_update() { diff --git a/src/game.h b/src/game.h index 8d660f86e9..e45c4e5c8a 100644 --- a/src/game.h +++ b/src/game.h @@ -90,7 +90,6 @@ void game_create_windows(); void game_update(); void game_logic_update(); void sub_0x0069E9A7(); -void update_rain_animation(); void update_palette_effects(); int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp);