draw rain via new IRainDrawer interface

This commit is contained in:
Ted John 2016-06-03 23:06:22 +01:00
parent d4edf58a51
commit 3e6eb48d4c
11 changed files with 402 additions and 329 deletions

View File

@ -46,7 +46,7 @@
<ClCompile Include="src\drawing\font.c" />
<ClCompile Include="src\drawing\line.c" />
<ClCompile Include="src\drawing\NewDrawing.cpp" />
<ClCompile Include="src\drawing\rain.c" />
<ClCompile Include="src\drawing\Rain.cpp" />
<ClCompile Include="src\drawing\rect.c" />
<ClCompile Include="src\drawing\scrolling_text.c" />
<ClCompile Include="src\drawing\sprite.c" />
@ -339,6 +339,7 @@
<ClInclude Include="src\drawing\IDrawingContext.h" />
<ClInclude Include="src\drawing\IDrawingEngine.h" />
<ClInclude Include="src\drawing\NewDrawing.h" />
<ClInclude Include="src\drawing\Rain.h" />
<ClInclude Include="src\editor.h" />
<ClInclude Include="src\game.h" />
<ClInclude Include="src\hook.h" />

View File

@ -20,6 +20,8 @@
#include <SDL_video.h>
struct rct_drawpixelinfo;
interface IDrawingEngine
{
virtual ~IDrawingEngine() { }
@ -36,3 +38,14 @@ namespace DrawingEngineFactory
{
IDrawingEngine * CreateSoftware();
};
interface IRainDrawer
{
virtual ~IRainDrawer() { }
virtual void Draw(sint32 x,
sint32 y,
sint32 width,
sint32 height,
sint32 xStart,
sint32 yStart) abstract;
};

23
src/drawing/Rain.h Normal file
View File

@ -0,0 +1,23 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include "../common.h"
interface IRainDrawer;
void DrawRain(IRainDrawer * rainDrawer);

View File

@ -39,15 +39,6 @@ uint8 _screenDirtyBlockShiftY;
rct_drawpixelinfo gScreenDPI;
rct_drawpixelinfo gWindowDPI;
typedef struct rain_pixel {
uint32 position;
uint8 colour;
} rain_pixel;
#define MAX_RAIN_PIXELS 0xFFFE
static rain_pixel _rainPixels[MAX_RAIN_PIXELS];
static uint32 _numRainPixels;
uint8 gGamePalette[256 * 4];
uint32 gPaletteEffectFrame;
@ -295,91 +286,6 @@ bool clip_drawpixelinfo(rct_drawpixelinfo *dst, rct_drawpixelinfo *src, int x, i
return false;
}
/**
*
* rct2: 0x00684027
* ebp used to be a parameter but it is always zero
* left : eax
* top : ebx
* width : ecx
* height : edx
* x_start: edi
* y_start: esi
*/
void gfx_draw_rain(int left, int top, int width, int height, sint32 x_start, sint32 y_start)
{
static const uint8 RainPattern[] = {
32, 32, 0, 12, 0, 14, 0, 16, -1, 0, -1, 0, -1, 0, -1, 0, -1,
0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0,
-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,
0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0
};
const uint8 *pattern = RainPattern;
uint8 pattern_x_space = *pattern++;
uint8 pattern_y_space = *pattern++;
uint8 pattern_start_x_offset = x_start % pattern_x_space;
uint8 pattern_start_y_offset = y_start % pattern_y_space;
rct_drawpixelinfo *dpi = &gScreenDPI;
uint32 pixel_offset = (dpi->pitch + dpi->width) * top + left;
uint8 pattern_y_pos = pattern_start_y_offset % pattern_y_space;
//Stores the colours of changed pixels
rain_pixel *pixel_store = &_rainPixels[_numRainPixels];
for (; height != 0; height--) {
uint8 pattern_x = pattern[pattern_y_pos * 2];
if (pattern_x != 0xFF) {
if (_numRainPixels < (MAX_RAIN_PIXELS - (uint32)width)) {
int final_pixel_offset = width + pixel_offset;
int x_pixel_offset = pixel_offset;
x_pixel_offset += ((uint8)(pattern_x - pattern_start_x_offset)) % pattern_x_space;
uint8 pattern_pixel = pattern[pattern_y_pos * 2 + 1];
for (; x_pixel_offset < final_pixel_offset; x_pixel_offset += pattern_x_space){
uint8 current_pixel = dpi->bits[x_pixel_offset];
dpi->bits[x_pixel_offset] = pattern_pixel;
_numRainPixels++;
// Store colour and position
*pixel_store++ = (rain_pixel){ x_pixel_offset, current_pixel };
}
}
}
pixel_offset += dpi->pitch + dpi->width;
pattern_y_pos++;
pattern_y_pos %= pattern_y_space;
}
}
/**
*
* rct2: 0x006843DC
*/
void redraw_rain()
{
if (_numRainPixels > 0) {
rct_window *window = window_get_main();
uint32 numPixels = window->width * window->height;
uint8 *screenPixels = gScreenDPI.bits;
for (uint32 i = 0; i < _numRainPixels; i++) {
rain_pixel rainPixel = _rainPixels[i];
// HACK
if (rainPixel.position > numPixels) {
log_verbose("Pixel error, skipping rain draw in this frame");
break;
}
screenPixels[rainPixel.position] = rainPixel.colour;
}
_numRainPixels = 0;
}
}
void gfx_invalidate_pickedup_peep()
{
uint32 sprite = gPickupPeepImage;

View File

@ -181,10 +181,6 @@ void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availab
bool ttf_initialise();
void ttf_dispose();
// rain
void update_rain_animation();
void redraw_rain();
// scrolling text
void scrolling_text_initialise_bitmaps();
int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode);

View File

@ -17,6 +17,7 @@
#include "../../core/Math.hpp"
#include "../../core/Memory.hpp"
#include "../IDrawingEngine.h"
#include "../Rain.h"
extern "C"
{
@ -36,6 +37,117 @@ struct DirtyGrid
uint8 * Blocks;
};
class RainDrawer : public IRainDrawer
{
private:
struct RainPixel
{
uint32 Position;
uint8 Colour;
};
static constexpr uint32 MaxRainPixels = 0xFFFE;
size_t _rainPixelsCapacity;
uint32 _rainPixelsCount;
RainPixel * _rainPixels;
rct_drawpixelinfo * _screenDPI;
public:
RainDrawer()
{
_rainPixelsCapacity = MaxRainPixels;
_rainPixelsCount = 0;
_rainPixels = new RainPixel[_rainPixelsCapacity];
}
~RainDrawer()
{
delete _rainPixels;
}
void SetDPI(rct_drawpixelinfo * dpi)
{
_screenDPI = dpi;
}
void Draw(sint32 x, sint32 y, sint32 width, sint32 height, sint32 xStart, sint32 yStart)
{
static const uint8 RainPattern[] =
{
32, 32, 0, 12, 0, 14, 0, 16, 255, 0, 255, 0, 255, 0, 255, 0, 255,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0,
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 0, 0
};
const uint8 * pattern = RainPattern;
uint8 patternXSpace = *pattern++;
uint8 patternYSpace = *pattern++;
uint8 patternStartXOffset = xStart % patternXSpace;
uint8 patternStartYOffset = yStart % patternYSpace;
uint32 pixelOffset = (_screenDPI->pitch + _screenDPI->width) * y + x;
uint8 patternYPos = patternStartYOffset % patternYSpace;
uint8 * screenBits = _screenDPI->bits;
//Stores the colours of changed pixels
RainPixel * newPixels = &_rainPixels[_rainPixelsCount];
for (; height != 0; height--)
{
uint8 patternX = pattern[patternYPos * 2];
if (patternX != 0xFF)
{
if (_rainPixelsCount < (_rainPixelsCapacity - (uint32)width))
{
uint32 finalPixelOffset = width + pixelOffset;
uint32 xPixelOffset = pixelOffset;
xPixelOffset += ((uint8)(patternX - patternStartXOffset)) % patternXSpace;
uint8 patternPixel = pattern[patternYPos * 2 + 1];
for (; xPixelOffset < finalPixelOffset; xPixelOffset += patternXSpace)
{
uint8 current_pixel = screenBits[xPixelOffset];
screenBits[xPixelOffset] = patternPixel;
_rainPixelsCount++;
// Store colour and position
*newPixels++ = { xPixelOffset, current_pixel };
}
}
}
pixelOffset += _screenDPI->pitch + _screenDPI->width;
patternYPos++;
patternYPos %= patternYSpace;
}
}
void Restore()
{
if (_rainPixelsCount > 0)
{
uint32 numPixels = (_screenDPI->width + _screenDPI->pitch) * _screenDPI->height;
uint8 * bits = _screenDPI->bits;
for (uint32 i = 0; i < _rainPixelsCount; i++)
{
RainPixel rainPixel = _rainPixels[i];
if (rainPixel.Position >= numPixels)
{
// Pixel out of bounds, bail
break;
}
bits[rainPixel.Position] = rainPixel.Colour;
}
_rainPixelsCount = 0;
}
}
};
class SoftwareDrawingEngine : public IDrawingEngine
{
private:
@ -54,6 +166,8 @@ private:
rct_drawpixelinfo _bitsDPI = { 0 };
RainDrawer _rainDrawer;
public:
SoftwareDrawingEngine()
{
@ -150,13 +264,19 @@ public:
void Draw() override
{
redraw_rain();
_rainDrawer.SetDPI(&_bitsDPI);
_rainDrawer.Restore();
gfx_invalidate_pickedup_peep();
gfx_draw_pickedup_peep();
DrawAllDirtyBlocks();
window_update_all_viewports();
DrawAllDirtyBlocks();
window_update_all();
DrawRain(&_rainDrawer);
rct2_draw();
Display();
}

View File

@ -1,223 +0,0 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "../addresses.h"
#include "../interface/window.h"
#include "../world/climate.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 = gWindowNextSlot;
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 = &gScreenDPI;
short left = screenDPI->x;
short right = left + screenDPI->width;
short top = screenDPI->y;
short bottom = top + screenDPI->height;
rct_window* newWindow = gWindowNextSlot;
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()
{
// Get rain draw function and draw rain
uint32 draw_rain_func = gClimateCurrentRainLevel;
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 = -(int)gScenarioTicks + 8;
int y_start = (gScenarioTicks * 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 = -(int)gScenarioTicks + 0x18;
y_start = (gScenarioTicks * 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 = -(int)gScenarioTicks;
int y_start = gScenarioTicks * 5;
y_start = -y_start;
x_start += left;
y_start += top;
gfx_draw_rain(left, top, width, height, x_start, y_start);
x_start = -(int)gScenarioTicks + 0x10;
y_start = (gScenarioTicks * 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 = -(int)gScenarioTicks + 8;
y_start = (gScenarioTicks * 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 = -(int)gScenarioTicks + 0x18;
y_start = (gScenarioTicks * 4) + 0x0D;
y_start = -y_start;
x_start += left;
y_start += top;
gfx_draw_rain(left, top, width, height, x_start, y_start);
}

237
src/drawing/rain.cpp Normal file
View File

@ -0,0 +1,237 @@
#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/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.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
extern "C"
{
#include "../addresses.h"
#include "../interface/window.h"
#include "../world/climate.h"
#include "drawing.h"
}
#include "IDrawingEngine.h"
#include "Rain.h"
typedef void (* DrawRainFunc)(IRainDrawer * rainDrawer, sint32 left, sint32 top, sint32 width, sint32 height);
static void DrawLightRain(IRainDrawer * rainDrawer, sint32 left, sint32 top, sint32 width, sint32 height);
static void DrawHeavyRain(IRainDrawer * rainDrawer, sint32 left, sint32 top, sint32 width, sint32 height);
/**
*
* rct2: 0x009AC058
*/
const DrawRainFunc DrawRainFunctions[] =
{
nullptr,
&DrawLightRain,
&DrawHeavyRain
};
/**
*
* rct2: 0x00684383
*/
static void CallDrawRainFunc(IRainDrawer * rainDrawer,
rct_window * w,
sint16 left,
sint16 right,
sint16 top,
sint16 bottom,
uint32 rainType)
{
rct_viewport * vp = w->viewport;
if (vp == nullptr)
{
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;
}
sint32 width = right - left;
sint32 height = bottom - top;
DrawRainFunctions[rainType](rainDrawer, left, top, width, height);
}
/**
*
* rct2: 0x006842AF
* From 0x00684383 on: split into call_draw_rain_func
*/
static void DrawRainWindow(IRainDrawer * rainDrawer,
rct_window * original_w,
sint16 left,
sint16 right,
sint16 top,
sint16 bottom,
uint32 rainType)
{
rct_window * newWindow = gWindowNextSlot;
rct_window * w = original_w + 1; // Start from second window
for (; ; w++)
{
if (w >= newWindow)
{
// Loop ended, draw rain for original_w
CallDrawRainFunc(rainDrawer, original_w, left, right, top, bottom, rainType);
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;
}
DrawRainWindow(rainDrawer, original_w, left, w->x, top, bottom, rainType);
left = w->x;
DrawRainWindow(rainDrawer, original_w, left, right, top, bottom, rainType);
return;
}
sint16 w_right = RCT_WINDOW_RIGHT(w);
if (right > w_right) {
DrawRainWindow(rainDrawer, original_w, left, w_right, top, bottom, rainType);
left = w_right;
DrawRainWindow(rainDrawer, original_w, left, right, top, bottom, rainType);
return;
}
if (top < w->y) {
DrawRainWindow(rainDrawer, original_w, left, right, top, w->y, rainType);
top = w->y;
DrawRainWindow(rainDrawer, original_w, left, right, top, bottom, rainType);
return;
}
sint16 w_bottom = RCT_WINDOW_BOTTOM(w);
if (bottom > w_bottom)
{
DrawRainWindow(rainDrawer, original_w, left, right, top, w_bottom, rainType);
top = w_bottom;
DrawRainWindow(rainDrawer, original_w, left, right, top, bottom, rainType);
return;
}
}
/**
*
* rct2: 0x00684266
*/
static void DrawRainAnimation(IRainDrawer * rainDrawer, uint32 rainType)
{
rct_drawpixelinfo * screenDPI = &gScreenDPI;
sint32 left = screenDPI->x;
sint32 right = left + screenDPI->width;
sint32 top = screenDPI->y;
sint32 bottom = top + screenDPI->height;
rct_window * newWindow = gWindowNextSlot;
for (rct_window * w = g_window_list; w < newWindow; w++)
{
DrawRainWindow(rainDrawer, w, left, right, top, bottom, rainType);
}
}
/**
*
* rct2: 0x00684218
*/
void DrawRain(IRainDrawer * rainDrawer)
{
// Get rain draw function and draw rain
uint32 rainType = gClimateCurrentRainLevel;
if (rainType > 0 && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1))
{
DrawRainAnimation(rainDrawer, rainType);
}
}
/**
*
* rct2: 0x00684114
*/
static void DrawLightRain(IRainDrawer * rainDrawer, sint32 left, sint32 top, sint32 width, sint32 height)
{
int x_start = -(int)gScenarioTicks + 8;
int y_start = (gScenarioTicks * 3) + 7;
y_start = -y_start;
x_start += left;
y_start += top;
rainDrawer->Draw(left, top, width, height, x_start, y_start);
x_start = -(int)gScenarioTicks + 0x18;
y_start = (gScenarioTicks * 4) + 0x0D;
y_start = -y_start;
x_start += left;
y_start += top;
rainDrawer->Draw(left, top, width, height, x_start, y_start);
}
/**
*
* rct2: 0x0068416D
*/
static void DrawHeavyRain(IRainDrawer * rainDrawer, sint32 left, sint32 top, sint32 width, sint32 height)
{
int x_start = -(int)gScenarioTicks;
int y_start = gScenarioTicks * 5;
y_start = -y_start;
x_start += left;
y_start += top;
rainDrawer->Draw(left, top, width, height, x_start, y_start);
x_start = -(int)gScenarioTicks + 0x10;
y_start = (gScenarioTicks * 6) + 5;
y_start = -y_start;
x_start += left;
y_start += top;
rainDrawer->Draw(left, top, width, height, x_start, y_start);
x_start = -(int)gScenarioTicks + 8;
y_start = (gScenarioTicks * 3) + 7;
y_start = -y_start;
x_start += left;
y_start += top;
rainDrawer->Draw(left, top, width, height, x_start, y_start);
x_start = -(int)gScenarioTicks + 0x18;
y_start = (gScenarioTicks * 4) + 0x0D;
y_start = -y_start;
x_start += left;
y_start += top;
rainDrawer->Draw(left, top, width, height, x_start, y_start);
}

View File

@ -42,7 +42,7 @@ void screenshot_check()
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, uint8) != 0) {
RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, uint8)--;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREENSHOT_COUNTDOWN, uint8) == 0) {
update_rain_animation();
// update_rain_animation();
screenshotIndex = screenshot_dump();
if (screenshotIndex != -1) {
@ -55,7 +55,7 @@ void screenshot_check()
}
RCT2_GLOBAL(0x009A8C29, uint8) &= ~1;
redraw_rain();
// redraw_rain();
}
}
}

View File

@ -281,9 +281,9 @@ void rct2_draw()
// redraw_rain();
// window_update_all();
gfx_invalidate_pickedup_peep();
gfx_draw_pickedup_peep();
update_rain_animation();
// gfx_invalidate_pickedup_peep();
// gfx_draw_pickedup_peep();
// update_rain_animation();
update_palette_effects();
chat_draw();

View File

@ -485,7 +485,7 @@ static void title_update_showcase()
game_logic_update();
}
update_palette_effects();
update_rain_animation();
// update_rain_animation();
}
} while (gTitleScriptSkipTo != -1 && gTitleScriptSkipLoad == -1);
}