Merge pull request #33 from MeirGavish/refactors
Added move/copy rect functions in graphic_utils
This commit is contained in:
@@ -35,6 +35,9 @@
|
|||||||
#define SE_UP -1
|
#define SE_UP -1
|
||||||
#define SE_DOWN 1
|
#define SE_DOWN 1
|
||||||
|
|
||||||
|
// Tile size in pixels, both height and width as tiles are square
|
||||||
|
#define TILE_SIZE 8
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int left;
|
int left;
|
||||||
@@ -45,6 +48,19 @@ typedef struct
|
|||||||
|
|
||||||
#define UNDEFINED -1
|
#define UNDEFINED -1
|
||||||
|
|
||||||
|
INLINE int rect_width(const Rect* rect)
|
||||||
|
{
|
||||||
|
/* Extra parens to avoid issues in case compiler turns INLINE into macro
|
||||||
|
* Not sure if necessary, could be just paranoia
|
||||||
|
*/
|
||||||
|
return (((rect)->right) - ((rect)->left) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE int rect_height(const Rect* rect)
|
||||||
|
{
|
||||||
|
return (((rect)->bottom) - ((rect)->top) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clears a rect in the main background.
|
/* Clears a rect in the main background.
|
||||||
* The se_rect dimensions need to be in number of tiles.
|
* The se_rect dimensions need to be in number of tiles.
|
||||||
*/
|
*/
|
||||||
@@ -56,6 +72,20 @@ void main_bg_se_clear_rect(Rect se_rect);
|
|||||||
*/
|
*/
|
||||||
void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction);
|
void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction);
|
||||||
|
|
||||||
|
/* Moves a rect in the main background vertically in direction by a single tile.
|
||||||
|
* Note that tiles in the previous location will be transparent (0x000)
|
||||||
|
* so maybe copy would be a better choice if you don't want to delete things
|
||||||
|
* direction must be either SE_UP or SE_DOWN.
|
||||||
|
* se_rect dimensions are in number of tiles.
|
||||||
|
*/
|
||||||
|
void main_bg_se_move_rect_1_tile_vert(Rect se_rect, int direction);
|
||||||
|
|
||||||
|
/* Copies the rect in rect_from into rect_to.
|
||||||
|
* Notice there may be overlaps and overwrites due to them.
|
||||||
|
* Both rects must be the same size
|
||||||
|
*/
|
||||||
|
void main_bg_se_copy_rect(Rect rect_to, Rect rect_from);
|
||||||
|
|
||||||
// A wrapper for tte_erase_rect that would use the rect struct
|
// A wrapper for tte_erase_rect that would use the rect struct
|
||||||
void tte_erase_rect_wrapper(Rect rect);
|
void tte_erase_rect_wrapper(Rect rect);
|
||||||
|
|
||||||
|
|||||||
+64
-36
@@ -116,19 +116,36 @@ static inline Card *discard_pop()
|
|||||||
// Screenblock rects
|
// Screenblock rects
|
||||||
static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 21 };
|
static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 21 };
|
||||||
|
|
||||||
static const Rect POP_MENU_ANIM_RECT_DOWN = {9, 6, 24, 32 };
|
// TODO: Currently unused, remove?
|
||||||
static const Rect POP_MENU_ANIM_RECT_UP = {9, 7, 24, 32 };
|
//static const Rect POP_MENU_ANIM_RECT_SRC = {9, 19, 24, 31 };
|
||||||
// The rects for popping menu animations (round end, shop, blinds)
|
//static const Rect POP_MENU_ANIM_RECT_DEST = {9, 7, 24, 19 };
|
||||||
|
|
||||||
|
static const Rect POP_MENU_ANIM_RECT = {9, 7, 24, 31 };
|
||||||
|
// The rect for popping menu animations (round end, shop, blinds)
|
||||||
// - extends beyond the visible screen to the end of the screenblock
|
// - extends beyond the visible screen to the end of the screenblock
|
||||||
// It includes both the target and source position rects.
|
// It includes both the target and source position rects.
|
||||||
// This is because when popping, the target position is blank so we just animate
|
// This is because when popping, the target position is blank so we just animate
|
||||||
// the whole rect so we don't have to track its position
|
// the whole rect so we don't have to track its position
|
||||||
//
|
|
||||||
// In the down version we include another row above the menu assuming it's blank so it's copied into it
|
|
||||||
|
|
||||||
static const Rect SINGLE_BLIND_SELECT_RECT = { 9, 7, 13, 32 };
|
static const Rect SINGLE_BLIND_SELECT_RECT = {9, 7, 13, 31 };
|
||||||
|
|
||||||
static const Rect SHOP_ICON_RECT = { 0, 0, 8, 4 };
|
static const Rect HAND_BG_RECT_SELECTING = {9, 11, 24, 15 };
|
||||||
|
// TODO: Currently unused, remove?
|
||||||
|
//static const Rect HAND_BG_RECT_PLAYING = {9, 14, 24, 18 };
|
||||||
|
|
||||||
|
static const Rect TOP_LEFT_ITEM_SRC_RECT = {0, 20, 8, 25 };
|
||||||
|
static const Rect TOP_LEFT_PANEL_RECT = {0, 0, 8, 5 };
|
||||||
|
static const Rect TOP_LEFT_PANEL_ANIM_RECT = {0, 0, 8, 4 };
|
||||||
|
/* Contains the shop icon/current blind etc.
|
||||||
|
* The difference between TOP_LEFT_PANEL_ANIM_RECT and TOP_LEFT_PANEL_RECT
|
||||||
|
* is due to an overlap between the bottom of the top left panel
|
||||||
|
* and the top of the score panel in the tiles connecting them.
|
||||||
|
* TOP_LEFT_PANEL_ANIM_RECT should be used for animations,
|
||||||
|
* TOP_LEFT_PANEL_RECT for copies etc. but mind the overlap
|
||||||
|
*/
|
||||||
|
static const Rect TOP_LEFT_BLIND_TITLE_RECT = {0, 1, 8, 1 };
|
||||||
|
static const Rect BIG_BLIND_TITLE_SRC_RECT = {0, 26, 8, 26 };
|
||||||
|
static const Rect BOSS_BLIND_TITLE_SRC_RECT = {0, 27, 8, 27 };
|
||||||
|
|
||||||
// Rects for TTE (in pixels)
|
// Rects for TTE (in pixels)
|
||||||
static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING
|
static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING
|
||||||
@@ -159,7 +176,7 @@ static const Rect ROUND_END_NUM_HANDS_RECT = {88, 116, UNDEFINED, UNDEF
|
|||||||
static const Rect HAND_REWARD_RECT = {168, UNDEFINED, UNDEFINED, UNDEFINED };
|
static const Rect HAND_REWARD_RECT = {168, UNDEFINED, UNDEFINED, UNDEFINED };
|
||||||
static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED };
|
static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED };
|
||||||
|
|
||||||
//TODO: Different number ? 11 ?
|
//TODO: Properly define and use
|
||||||
#define MENU_POP_OUT_ANIM_FRAMES 20
|
#define MENU_POP_OUT_ANIM_FRAMES 20
|
||||||
|
|
||||||
// General functions
|
// General functions
|
||||||
@@ -353,6 +370,14 @@ enum HandType hand_get_type()
|
|||||||
return res_hand_type;
|
return res_hand_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copies the appropriate item into the top left panel (blind/shop icon)
|
||||||
|
* from where it was put outside the screenview
|
||||||
|
*/
|
||||||
|
void bg_copy_current_item_to_top_left_panel()
|
||||||
|
{
|
||||||
|
main_bg_se_copy_rect(TOP_LEFT_PANEL_RECT, TOP_LEFT_ITEM_SRC_RECT);
|
||||||
|
}
|
||||||
|
|
||||||
void change_background(int id)
|
void change_background(int id)
|
||||||
{
|
{
|
||||||
if (background == id)
|
if (background == id)
|
||||||
@@ -370,24 +395,19 @@ void change_background(int id)
|
|||||||
|
|
||||||
tte_erase_rect_wrapper(HAND_SIZE_RECT_PLAYING);
|
tte_erase_rect_wrapper(HAND_SIZE_RECT_PLAYING);
|
||||||
|
|
||||||
for (int y = 0; y < 6; y++) // Copies the blind panel from the bottom of the screen to the top. This code is identical to the one used in game_shop()
|
/* TODO: The blind panel should come in with an animation when it's selected,
|
||||||
{
|
* probably should happen elsewhere
|
||||||
int y_from = 20 + y;
|
*/
|
||||||
int y_to = 0 + y;
|
bg_copy_current_item_to_top_left_panel();
|
||||||
memcpy16(&se_mem[MAIN_BG_SBB][32 * y_to], &se_mem[MAIN_BG_SBB][32 * y_from], 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO: These cases are still untested
|
||||||
if (current_blind == BIG_BLIND) // Change text and palette depending on blind type
|
if (current_blind == BIG_BLIND) // Change text and palette depending on blind type
|
||||||
{
|
{
|
||||||
int y_from = 26;
|
main_bg_se_copy_rect(TOP_LEFT_BLIND_TITLE_RECT, BIG_BLIND_TITLE_SRC_RECT);
|
||||||
int y_to = 1;
|
|
||||||
memcpy16(&se_mem[MAIN_BG_SBB][32 * y_to], &se_mem[MAIN_BG_SBB][32 * y_from], 9);
|
|
||||||
}
|
}
|
||||||
else if (current_blind == BOSS_BLIND)
|
else if (current_blind == BOSS_BLIND)
|
||||||
{
|
{
|
||||||
int y_from = 27;
|
main_bg_se_copy_rect(TOP_LEFT_BLIND_TITLE_RECT, BOSS_BLIND_TITLE_SRC_RECT);
|
||||||
int y_to = 1;
|
|
||||||
memcpy16(&se_mem[MAIN_BG_SBB][32 * y_to], &se_mem[MAIN_BG_SBB][32 * y_from], 9);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This would change the palette of the background to match the blind, but the backgroun doesn't use the blind token's exact colors so a different approach is required
|
// This would change the palette of the background to match the blind, but the backgroun doesn't use the blind token's exact colors so a different approach is required
|
||||||
@@ -408,9 +428,12 @@ void change_background(int id)
|
|||||||
background = BG_ID_CARD_PLAYING;
|
background = BG_ID_CARD_PLAYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect curr_hand_bg_rect = HAND_BG_RECT_SELECTING;
|
||||||
for (int i = 0; i <= 2; i++)
|
for (int i = 0; i <= 2; i++)
|
||||||
{
|
{
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_DOWN);
|
main_bg_se_move_rect_1_tile_vert(curr_hand_bg_rect, SE_DOWN);
|
||||||
|
curr_hand_bg_rect.top++;
|
||||||
|
curr_hand_bg_rect.bottom++;
|
||||||
}
|
}
|
||||||
|
|
||||||
tte_erase_rect_wrapper(HAND_SIZE_RECT_SELECT);
|
tte_erase_rect_wrapper(HAND_SIZE_RECT_SELECT);
|
||||||
@@ -428,7 +451,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.
|
// 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.
|
// 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: Remove this if game_round_end() is fixed to use main_bg_se_copy_rect_1_tile_vert() for the pop menu
|
// TODO: Remove this if game_round_end() is fixed to use main_bg_se_copy/move_rect_1_tile_vert() for the pop menu
|
||||||
main_bg_se_clear_rect(ROUND_END_MENU_RECT);
|
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
|
//tte_erase_rect(0, 0, 64, 48); // Clear top left corner where the blind stats are displayed
|
||||||
@@ -461,7 +484,7 @@ void change_background(int id)
|
|||||||
obj_unhide(blind_select_tokens[BIG_BLIND]->obj, 0);
|
obj_unhide(blind_select_tokens[BIG_BLIND]->obj, 0);
|
||||||
obj_unhide(blind_select_tokens[BOSS_BLIND]->obj, 0);
|
obj_unhide(blind_select_tokens[BOSS_BLIND]->obj, 0);
|
||||||
|
|
||||||
const int default_y = 89 + (8 * 12); // Default y position for the blind select tokens. 8 is the size of a tile and 12 is the amound of tiles the background is shifted down by
|
const int default_y = 89 + (TILE_SIZE * 12); // Default y position for the blind select tokens. 8 is the size of a tile and 12 is the amound of tiles the background is shifted down by
|
||||||
sprite_position(blind_select_tokens[SMALL_BLIND], 80, default_y);
|
sprite_position(blind_select_tokens[SMALL_BLIND], 80, default_y);
|
||||||
sprite_position(blind_select_tokens[BIG_BLIND], 120, default_y);
|
sprite_position(blind_select_tokens[BIG_BLIND], 120, default_y);
|
||||||
sprite_position(blind_select_tokens[BOSS_BLIND], 160, default_y);
|
sprite_position(blind_select_tokens[BOSS_BLIND], 160, default_y);
|
||||||
@@ -482,6 +505,7 @@ void change_background(int id)
|
|||||||
{
|
{
|
||||||
if (blinds[i] != BLIND_CURRENT && (i == SMALL_BLIND || i == BIG_BLIND)) // Make the skip button gray
|
if (blinds[i] != BLIND_CURRENT && (i == SMALL_BLIND || i == BIG_BLIND)) // Make the skip button gray
|
||||||
{
|
{
|
||||||
|
// TODO: Switch all the copies here to use main_bg_se_copy_rect()
|
||||||
int x_from = 0;
|
int x_from = 0;
|
||||||
int y_from = 24 + (i * 4);
|
int y_from = 24 + (i * 4);
|
||||||
|
|
||||||
@@ -503,9 +527,9 @@ void change_background(int id)
|
|||||||
|
|
||||||
Rect blind_rect = SINGLE_BLIND_SELECT_RECT;
|
Rect blind_rect = SINGLE_BLIND_SELECT_RECT;
|
||||||
|
|
||||||
// + 1 to get to the start of the next blind, no gap between them
|
// There's no gap between them
|
||||||
blind_rect.left += i * (SINGLE_BLIND_SELECT_RECT.right - SINGLE_BLIND_SELECT_RECT.left + 1);
|
blind_rect.left += i * rect_width(&SINGLE_BLIND_SELECT_RECT);
|
||||||
blind_rect.right += i * (SINGLE_BLIND_SELECT_RECT.right - SINGLE_BLIND_SELECT_RECT.left + 1);
|
blind_rect.right += i * rect_width(&SINGLE_BLIND_SELECT_RECT);
|
||||||
main_bg_se_copy_rect_1_tile_vert(blind_rect, SE_UP);
|
main_bg_se_copy_rect_1_tile_vert(blind_rect, SE_UP);
|
||||||
|
|
||||||
int x_to = blind_rect.left;
|
int x_to = blind_rect.left;
|
||||||
@@ -521,9 +545,10 @@ void change_background(int id)
|
|||||||
y_from = 30;
|
y_from = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: What is this doing? More importantly, why?
|
||||||
memcpy16(&se_mem[MAIN_BG_SBB][x_to + 32 * y_to], &se_mem[MAIN_BG_SBB][x_from + 32 * y_from], 5);
|
memcpy16(&se_mem[MAIN_BG_SBB][x_to + 32 * y_to], &se_mem[MAIN_BG_SBB][x_from + 32 * y_from], 5);
|
||||||
|
|
||||||
sprite_position(blind_select_tokens[i], blind_select_tokens[i]->pos.x, blind_select_tokens[i]->pos.y - 8); // Move token up by a tile
|
sprite_position(blind_select_tokens[i], blind_select_tokens[i]->pos.x, blind_select_tokens[i]->pos.y - TILE_SIZE); // Move token up by a tile
|
||||||
}
|
}
|
||||||
else if (blinds[i] == BLIND_UPCOMING) // Change the select icon to "NEXT"
|
else if (blinds[i] == BLIND_UPCOMING) // Change the select icon to "NEXT"
|
||||||
{
|
{
|
||||||
@@ -1928,7 +1953,7 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa
|
|||||||
case 8: // Shift the round end panel back out of view and go to the next state
|
case 8: // Shift the round end panel back out of view and go to the next state
|
||||||
{
|
{
|
||||||
sequence_step++;
|
sequence_step++;
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_DOWN, SE_DOWN);
|
main_bg_se_move_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_DOWN);
|
||||||
|
|
||||||
if (sequence_step >= 20)
|
if (sequence_step >= 20)
|
||||||
{
|
{
|
||||||
@@ -1992,7 +2017,7 @@ void game_shop()
|
|||||||
{
|
{
|
||||||
case 0: // Intro sequence (menu and shop icon coming into frame)
|
case 0: // Intro sequence (menu and shop icon coming into frame)
|
||||||
{
|
{
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_UP);
|
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP);
|
||||||
|
|
||||||
if (timer >= 7) // Shift the shop icon
|
if (timer >= 7) // Shift the shop icon
|
||||||
{
|
{
|
||||||
@@ -2091,9 +2116,9 @@ void game_shop()
|
|||||||
case 2: // Outro sequence (menu and shop icon going out of frame)
|
case 2: // Outro sequence (menu and shop icon going out of frame)
|
||||||
{
|
{
|
||||||
// Shift the shop panel
|
// Shift the shop panel
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_DOWN, SE_DOWN);
|
main_bg_se_move_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_DOWN);
|
||||||
|
|
||||||
main_bg_se_copy_rect_1_tile_vert(SHOP_ICON_RECT, SE_UP);
|
main_bg_se_copy_rect_1_tile_vert(TOP_LEFT_PANEL_ANIM_RECT, SE_UP);
|
||||||
|
|
||||||
if (timer == 1)
|
if (timer == 1)
|
||||||
{
|
{
|
||||||
@@ -2146,7 +2171,7 @@ void game_blind_select()
|
|||||||
{
|
{
|
||||||
case 0: // Intro sequence (menu coming into frame)
|
case 0: // Intro sequence (menu coming into frame)
|
||||||
{
|
{
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_UP);
|
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP);
|
||||||
|
|
||||||
for (int i = 0; i < MAX_BLINDS; i++)
|
for (int i = 0; i < MAX_BLINDS; i++)
|
||||||
{
|
{
|
||||||
@@ -2186,14 +2211,15 @@ void game_blind_select()
|
|||||||
background = -1; // Force refresh of the background
|
background = -1; // Force refresh of the background
|
||||||
change_background(BG_ID_BLIND_SELECT);
|
change_background(BG_ID_BLIND_SELECT);
|
||||||
|
|
||||||
|
// TODO: Create a generic vertical move by any number of tiles to avoid for loops?
|
||||||
for (int i = 0; i < 12; i++)
|
for (int i = 0; i < 12; i++)
|
||||||
{
|
{
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_UP);
|
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < MAX_BLINDS; i++)
|
for (int i = 0; i < MAX_BLINDS; i++)
|
||||||
{
|
{
|
||||||
sprite_position(blind_select_tokens[i], blind_select_tokens[i]->pos.x, blind_select_tokens[i]->pos.y - (8 * 12));
|
sprite_position(blind_select_tokens[i], blind_select_tokens[i]->pos.x, blind_select_tokens[i]->pos.y - (TILE_SIZE * 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
timer = 0;
|
timer = 0;
|
||||||
@@ -2217,11 +2243,13 @@ void game_blind_select()
|
|||||||
{
|
{
|
||||||
if (timer < 15)
|
if (timer < 15)
|
||||||
{
|
{
|
||||||
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_DOWN, SE_DOWN);
|
Rect blinds_rect = POP_MENU_ANIM_RECT;
|
||||||
|
blinds_rect.top -= 1; // Because of the raised blind
|
||||||
|
main_bg_se_move_rect_1_tile_vert(blinds_rect, SE_DOWN);
|
||||||
|
|
||||||
for (int i = 0; i < MAX_BLINDS; i++)
|
for (int i = 0; i < MAX_BLINDS; i++)
|
||||||
{
|
{
|
||||||
sprite_position(blind_select_tokens[i], blind_select_tokens[i]->pos.x, blind_select_tokens[i]->pos.y + 8);
|
sprite_position(blind_select_tokens[i], blind_select_tokens[i]->pos.x, blind_select_tokens[i]->pos.y + TILE_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Currently selecting other blinds crashes, remove this condition once fixed
|
// TODO: Currently selecting other blinds crashes, remove this condition once fixed
|
||||||
|
|||||||
+51
-9
@@ -7,6 +7,7 @@
|
|||||||
const Rect FULL_SCREENBLOCK_RECT = { 0, 0, SE_ROW_LEN, SE_COL_LEN };
|
const Rect FULL_SCREENBLOCK_RECT = { 0, 0, SE_ROW_LEN, SE_COL_LEN };
|
||||||
|
|
||||||
// Clips a rect of screenblock entries to a specified rect
|
// Clips a rect of screenblock entries to a specified rect
|
||||||
|
// The bounding rect is not required to be within screenblock boundaries
|
||||||
static void clip_se_rect_to_bounding_rect(Rect* rect, const Rect* bounding_rect)
|
static void clip_se_rect_to_bounding_rect(Rect* rect, const Rect* bounding_rect)
|
||||||
{
|
{
|
||||||
rect->right = min(rect->right, bounding_rect->right);
|
rect->right = min(rect->right, bounding_rect->right);
|
||||||
@@ -17,12 +18,20 @@ static void clip_se_rect_to_bounding_rect(Rect* rect, const Rect* bounding_rect)
|
|||||||
|
|
||||||
// Can be unstaticed if needed
|
// Can be unstaticed if needed
|
||||||
// Clips a rect of screenblock entries to screenblock boundaries
|
// Clips a rect of screenblock entries to screenblock boundaries
|
||||||
// The bounding rect is not required to be within screenblock boundaries
|
|
||||||
static void clip_se_rect_to_screenblock(Rect* rect)
|
static void clip_se_rect_to_screenblock(Rect* rect)
|
||||||
{
|
{
|
||||||
clip_se_rect_to_bounding_rect(rect, &FULL_SCREENBLOCK_RECT);
|
clip_se_rect_to_bounding_rect(rect, &FULL_SCREENBLOCK_RECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clips a rect of screenblock entries to be within one step of
|
||||||
|
// screenblock boundaries vertically (1 step from top, 1 step from bottom.
|
||||||
|
static void clip_se_rect_within_step_of_full_screen_vert(Rect* se_rect)
|
||||||
|
{
|
||||||
|
Rect bounding_rect = FULL_SCREENBLOCK_RECT;
|
||||||
|
bounding_rect.top += 1;
|
||||||
|
bounding_rect.bottom -= -1;
|
||||||
|
clip_se_rect_to_bounding_rect(se_rect, &bounding_rect);
|
||||||
|
}
|
||||||
|
|
||||||
void main_bg_se_clear_rect(Rect se_rect)
|
void main_bg_se_clear_rect(Rect se_rect)
|
||||||
{
|
{
|
||||||
@@ -33,7 +42,7 @@ void main_bg_se_clear_rect(Rect se_rect)
|
|||||||
|
|
||||||
for (int y = se_rect.top; y < se_rect.bottom; y++)
|
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 + 1);
|
memset16(&(se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y]), 0x0000, rect_width(&se_rect));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,13 +50,12 @@ 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))
|
|| (direction != SE_UP && direction != SE_DOWN))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Clip to avoid read/write overflow of the screenblock
|
// Clip to avoid read/write overflow of the screenblock
|
||||||
Rect bounding_rect = FULL_SCREENBLOCK_RECT;
|
clip_se_rect_within_step_of_full_screen_vert(&se_rect);
|
||||||
bounding_rect.top = 1;
|
|
||||||
bounding_rect.bottom = SE_COL_LEN - 1;
|
|
||||||
clip_se_rect_to_bounding_rect(&se_rect, &bounding_rect);
|
|
||||||
|
|
||||||
int start = (direction == SE_UP) ? se_rect.top : se_rect.bottom;
|
int start = (direction == SE_UP) ? se_rect.top : se_rect.bottom;
|
||||||
int end = (direction == SE_UP) ? se_rect.bottom : se_rect.top;
|
int end = (direction == SE_UP) ? se_rect.bottom : se_rect.top;
|
||||||
@@ -56,12 +64,46 @@ void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction)
|
|||||||
{
|
{
|
||||||
memcpy16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (y + direction)],
|
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_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y],
|
||||||
se_rect.right - se_rect.left + 1);
|
rect_width(&se_rect));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_bg_se_move_rect_1_tile_vert(Rect se_rect, int direction)
|
||||||
|
{
|
||||||
|
if (se_rect.left > se_rect.right
|
||||||
|
|| (direction != SE_UP && direction != SE_DOWN))
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction == SE_DOWN)
|
// Clip to avoid read/write overflow of the screenblock
|
||||||
|
clip_se_rect_within_step_of_full_screen_vert(&se_rect);
|
||||||
|
|
||||||
|
int deleted_y = (direction == SE_UP) ? se_rect.bottom : se_rect.top;
|
||||||
|
|
||||||
|
main_bg_se_copy_rect_1_tile_vert(se_rect, direction);
|
||||||
|
|
||||||
|
memset16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (deleted_y)], 0x0000, rect_width(&se_rect));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_bg_se_copy_rect(Rect rect_to, Rect rect_from)
|
||||||
|
{
|
||||||
|
if (rect_from.left > rect_from.right
|
||||||
|
|| rect_from.top > rect_from.bottom
|
||||||
|
|| rect_to.left > rect_to.right
|
||||||
|
|| rect_from.top > rect_from.bottom
|
||||||
|
// Check equal dimensions
|
||||||
|
|| rect_width(&rect_from) != rect_width(&rect_to)
|
||||||
|
|| rect_height(&rect_from) != rect_height(&rect_to))
|
||||||
{
|
{
|
||||||
memset16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (end)], 0x0000, se_rect.right - se_rect.left + 1); // This clears the top row when going down, or the bottom row when going up.
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < rect_height(&rect_from); y++)
|
||||||
|
{
|
||||||
|
memcpy16(&(se_mem[MAIN_BG_SBB][rect_to.left + SE_ROW_LEN * (rect_to.top + y)]),
|
||||||
|
&(se_mem[MAIN_BG_SBB][rect_from.left + SE_ROW_LEN * (rect_from.top + y)]),
|
||||||
|
rect_width(&rect_from));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user