Implement draw_rain_window and call_draw_rain_func

Implement procedure (0x006842AF) as two methods: draw_rain_window and
call_draw_rain_func.
Avoid using global variable 0x00EE7850 by passing it as a parameter:
draw_rain_func. This global variable was only used by these procedures.
Rain has some visual artifacts in RCT2, specially when using game
windows. This implementation matches the original game, and thus has the
same artifacts.
This commit is contained in:
Marco Costa 2014-07-20 02:46:29 -04:00
parent 1a57326df6
commit 54933646f1
2 changed files with 93 additions and 7 deletions

View File

@ -69,14 +69,97 @@ void update_water_animation()
RCT2_CALLPROC_EBPSAFE(0x006838BD);
}
/**
*
* 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 = 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;
RCT2_CALLPROC_X(draw_rain_func, left, top, width, height, 0, 0, 0);
}
/**
*
* 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
return call_draw_rain_func(original_w, left, right, top, bottom, draw_rain_func);
}
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;
return draw_rain_window(original_w, left, right, top, bottom, draw_rain_func);
}
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;
return draw_rain_window(original_w, left, right, top, bottom, draw_rain_func);
}
if (top < w->y) {
draw_rain_window(original_w, left, right, top, w->y, draw_rain_func);
top = w->y;
return draw_rain_window(original_w, left, right, top, bottom, draw_rain_func);
}
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;
return draw_rain_window(original_w, left, right, top, bottom, draw_rain_func);
}
}
/**
*
* rct2: 0x00684266
*/
void draw_rain_animation(uint32 eax)
void draw_rain_animation(uint32 draw_rain_func)
{
RCT2_GLOBAL(0x00EE7850, uint32) = eax;
rct_drawpixelinfo *screenDPI = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo);
short left = screenDPI->x;
short right = left + screenDPI->width;
@ -86,7 +169,7 @@ void draw_rain_animation(uint32 eax)
rct_window* newWindow = (RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*));
for (rct_window* w = g_window_list; w < newWindow; w++) {
RCT2_CALLPROC_X(0x006842AF, left, top, 0, right, (int)w, 0, bottom);
draw_rain_window(w, left, right, top, bottom, draw_rain_func);
}
}
@ -110,9 +193,9 @@ void update_rain_animation()
}
// Get rain draw function and draw rain
uint32 eax = RCT2_ADDRESS(0x009AC058, uint32)[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8)];
if (eax != 0xFFFFFFFF && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1))
draw_rain_animation(eax);
uint32 draw_rain_func = RCT2_ADDRESS(0x009AC058, uint32)[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8)];
if (draw_rain_func != 0xFFFFFFFF && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1))
draw_rain_animation(draw_rain_func);
}
void game_update()

View File

@ -146,6 +146,9 @@ typedef struct rct_window {
uint8 colours[6]; // 0x4BA
} rct_window;
#define RCT_WINDOW_RIGHT(w) (w->x + w->width)
#define RCT_WINDOW_BOTTOM(w) (w->y + w->height)
typedef enum {
WE_CLOSE = 0,
WE_MOUSE_UP = 1,