Fixed generic main_bg_se_copy_rect_1_tile_vert() function and replaced some code with it

This commit is contained in:
MeirGavish
2025-07-10 20:59:04 +03:00
parent 6ef1f51c55
commit 05f4cc2abb
3 changed files with 51 additions and 61 deletions

View File

@@ -31,6 +31,10 @@
#define SE_ROW_LEN 32
#define SE_COL_LEN 32
// Since y direction goes from the top of the screen to the bottom
#define SE_UP -1
#define SE_DOWN 1
typedef struct
{
int left;
@@ -46,12 +50,11 @@ typedef struct
*/
void main_bg_se_clear_rect(Rect se_rect);
/* Copies a rect in the main background a single tile up.
* The se_rect dimensions need to be in number of tiles.
* This is for the pop menu animation, can later be generalized to more tiles
* or other directions
/* Copies a rect in the main background vertically in direction by a single tile.
* direction must be either SE_UP or SE_DOWN.
* se_rect dimensions are in number of tiles.
*/
void main_bg_se_copy_rect_1_tile_up(Rect se_rect);
void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction);
// A wrapper for tte_erase_rect that would use the rect struct
void tte_erase_rect_wrapper(Rect rect);

View File

@@ -113,14 +113,18 @@ static inline Card *discard_pop()
// Rects left top right bottom
// Screenblock rects
static const Rect ROUND_END_MENU_RECT = {9, 7, 25, 21 };
static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 21 };
static const Rect POP_MENU_ANIM_RECT = {9, 7, 25, 32 };
// The rect for popping menu animations - includes both the target and source position
// rects. The source position extends beyond the visible screen to the end
// of the screenblock
// The target position is blank so we just animate the whole thing so we don't
// have to track its position
static const Rect POP_MENU_ANIM_RECT = {9, 6, 24, 32 };
// The rect for popping menu animations (round end, shop, blinds) - includes both the
// target and source position rects.
// Extends beyond the visible screen to the end of the screenblock
// This is because when popping, the target position is blank so we just animate the whole thing
// so we don't have to track its position
//
// When unpopping we include another row above the menu assuming it's blank so it's copied into it
static const Rect SHOP_ICON_RECT = { 0, 0, 8, 4 };
// Rects for TTE (in pixels)
static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING
@@ -373,7 +377,7 @@ void change_background(int id)
// Incoming hack! Clear the round end menu so that we can slowly display it with an animation later. The reason this isn't optimal is because the full background is already loaded into the vram at this point.
// I'm just doing it this way because it's easier than doing some weird shit with Grit in order to get a proper tilemap. I'm not the biggest fan of Grit.
// TODO: See TODO comment in game_round_end(), once that is properly done, remove this.
// TODO: Remove this if game_round_end() is fixed to use main_bg_se_copy_rect_1_tile_vert() for the pop menu
main_bg_se_clear_rect(ROUND_END_MENU_RECT);
//tte_erase_rect(0, 0, 64, 48); // Clear top left corner where the blind stats are displayed
@@ -1460,9 +1464,11 @@ void game_playing()
void game_round_end() // Writing this kind a made me want to kms. If somewone wants to rewrite this, please do so.
{
/* TODO: The correct way to do this is the same as game_shop(),
* put the menu in VRAM outside the screen and copy it from there.
* That code needs to be extracted to a function and reused here.
/* TODO: I could use main_bg_se_copy_rect_1_tile_vert() to replace the menu pop up here
* But there are a bunch of other manual hard-coded tilemap animations in here that
* are very hard to understand, and if I change the background image for the pop up
* it will change the tile charblock layout and screw them up so it's all or nothing...
* - Meir
*/
static int state = 0;
static int sequence_step = 0; // Reusable variable for the animations in states
@@ -1799,12 +1805,7 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa
case 8:
{
sequence_step++;
int x = 9;
for (int y = 19; y > 5; y--)
{
memcpy16(&se_mem[MAIN_BG_SBB][x + 32 * (y + 1)], &se_mem[MAIN_BG_SBB][x + 32 * y], 16);
}
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_DOWN);
if (sequence_step >= 20)
{
@@ -1868,16 +1869,13 @@ void game_shop()
{
case 0: // Intro sequence (menu and shop icon coming into frame)
{
for (int y = 7; y < 40; y++) // Shift the shop panel
{
int x = 9;
memcpy16(&se_mem[MAIN_BG_SBB][x + 32 * (y - 1)], &se_mem[MAIN_BG_SBB][x + 32 * y], 16);
}
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP);
if (timer >= 7) // Shift the shop icon
{
int timer_offset = timer - 6;
// TODO: Extract to generic function?
for (int y = 0; y < timer_offset; y++)
{
int y_from = 26 + y - timer_offset;
@@ -1969,19 +1967,10 @@ void game_shop()
}
case 2: // Outro sequence (menu and shop icon going out of frame)
{
// This is reused from game_round_end()
// Shift the shop panel
int x = 9;
for (int y = 19; y > 5; y--)
{
memcpy16(&se_mem[MAIN_BG_SBB][x + 32 * (y + 1)], &se_mem[MAIN_BG_SBB][x + 32 * y], 16);
}
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_DOWN);
// Shift the shop icon
for (int y = 0; y < 5; y++)
{
memcpy16(&se_mem[MAIN_BG_SBB][32 * (y - 1)], &se_mem[MAIN_BG_SBB][32 * y], 9);
}
main_bg_se_copy_rect_1_tile_vert(SHOP_ICON_RECT, SE_UP);
if (timer == 1)
{
@@ -2033,13 +2022,9 @@ void game_blind_select()
switch (state) // I'm only using magic numbers here for the sake of simplicity since it's just sequential, but you can replace them with named constants or enums if it makes it clearer
{
case 0: // Intro sequence (menu and shop icon coming into frame)
case 0: // Intro sequence (menu coming into frame)
{
for (int y = 7; y < 40; y++)
{
int x = 9;
memcpy16(&se_mem[MAIN_BG_SBB][x + 32 * (y - 1)], &se_mem[MAIN_BG_SBB][x + 32 * y], 16);
}
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP);
if (timer == 12)
{

View File

@@ -4,19 +4,15 @@
#include "graphic_utils.h"
/*
*
*/
const Rect FULL_SCREENBLOCK_RECT = { 0, 0, SE_ROW_LEN, SE_COL_LEN };
// Clips a rect of screenblock entries to a specified rect
static void clip_se_rect_to_bounding_rect(Rect* rect, const Rect* bounding_rect)
{
rect->right = min(rect->right, SE_ROW_LEN);
rect->bottom = min(rect->bottom, SE_COL_LEN);
rect->left = max(rect->left, 0);
rect->top = max(rect->top, 0);
rect->right = min(rect->right, bounding_rect->right);
rect->bottom = min(rect->bottom, bounding_rect->bottom);
rect->left = max(rect->left, bounding_rect->left);
rect->top = max(rect->top, bounding_rect->top);
}
// Can be unstaticed if needed
@@ -32,29 +28,35 @@ void main_bg_se_clear_rect(Rect se_rect)
{
if (se_rect.left > se_rect.right)
return;
// Just to make sure we're not overflowing the boundaries
// Clip to avoid screenblock overflow
clip_se_rect_to_screenblock(&se_rect);
for (int y = se_rect.top; y < se_rect.bottom; y++)
{
memset16(&(se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y]), 0x0000, se_rect.right - se_rect.left);
memset16(&(se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y]), 0x0000, se_rect.right - se_rect.left + 1);
}
}
void main_bg_se_copy_rect_1_tile_up(Rect se_rect)
void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction)
{
if (se_rect.left > se_rect.right)
if (se_rect.left > se_rect.right
|| (direction != SE_UP && direction != SE_DOWN))
return;
// Clip to avoid read/write overflow of the screenblock
Rect bounding_rect = FULL_SCREENBLOCK_RECT;
bounding_rect.top = 1; // Since we're going up, need to clip to 1 to not overflow
bounding_rect.top = 1;
bounding_rect.bottom = SE_COL_LEN - 1;
clip_se_rect_to_bounding_rect(&se_rect, &bounding_rect);
for (int y = se_rect.top; y < se_rect.bottom; y++)
int start = (direction == SE_UP) ? se_rect.top : se_rect.bottom;
int end = (direction == SE_UP) ? se_rect.bottom : se_rect.top;
for (int y = start; y != end - direction; y -= direction)
{
memcpy16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (y - 1)],
memcpy16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (y + direction)],
&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y],
se_rect.right - se_rect.left);
se_rect.right - se_rect.left + 1);
}
}