From d41503e6733600de226af8eced28320c9718ffe2 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Mon, 4 Aug 2025 20:25:53 +0300 Subject: [PATCH 01/11] Created game over background image --- graphics/background_game_over.png | Bin 0 -> 2158 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 graphics/background_game_over.png diff --git a/graphics/background_game_over.png b/graphics/background_game_over.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f1e29e84ce2ceb066f60e4e7e2206e60951870 GIT binary patch literal 2158 zcmbW3do&x!8o+~k)Vs$P)nZwfODWn^EL~~6rINNvh-cc=sz<7|(W;_cx3s18XuX@H zqCr(yLQ+zZ(xq)kQlTEHU|aPTizY(ErswQA_uTu(y?1xcnVIv=d^7WXbH3kvbLTY7 zOGDK_6#xKe_;|bf$@&#p<)|ph+V91SPXGXwqdx8@{F5Fnjd$c6m@!mdnen~raq9%t z3HG>q(zRgO`$2k+S<(J$_h~@aGuWQm-Me-aGk|lhDwc5{J)blUw%xW0*_FvHJ^Sz* zc`x}pw6F|Sa)5(JkUgk;xT6d!9#3`YXDu?1u@gk&GuJ;)mysUYm-!ZRseBmsBo|}U ze?KZ(IR3FE$eIFYL(Lyd=O+?^h4BGqn-h)8TOCbL?*hhkkSf0ECU$aJj9vQje@2KM zghqE=E|;K9cecw1x0Neuy)gwlyB&Eq!8Ufg;G^>F`%x8jy+{hhZw!ZHBOLEE0vTc1 z*K*Gev1E3&Np?Q!FDNI*^fFEv8CE~^8>3x4{XCRPzqW*InJNu0$K`}8MFm#buiRR~ zj!l~{9H$y6Cf$gtx!U%|i9_;~V_nT#;Fq8iE7CNBPNCCzm`vL^!4tuZS8S^8#YP7P zy8UH4=Vt`$Q#vC?;gNCgkHZT+&wCi0Mo-k_P!Q$f_cYwiP@B9jK?^|(iqIn5YkRO0 zgy-x`(lVJg4(vHlEPnUy;wgs=E212|{pJtbTT@^VqU2@hc&7_yFVd!{#&5GX>k3)V z;Oni`H>+(+#B0zY)M*-x<`yXT-fv7EU$Rn-q0KVK3{hq-Uh&Tn|)OjFQ`yvU*u${3TkezZ+fwH?oWrQhK6M31Mfi_^vnZBWyRx~p90bKv( zf6yGPembG-Gg<6uW#0ib3=?agh*k^L#aZNOo;s#$6G+l4Gh{=UwqxN^akHpC#Q65F zgJH9>SuVddQ>U^vB>vgr+Kpk&@R0Bt7Z32a+Ao9USlQ9HbxHGHm9=T3KX)UV;OT4U zYSnt96~foWb;bpR&7#C6lV;N5+Y5&gu!&@6s4W!4C-n)u4G5Ca->m!THy-Kc`~u&$ zKqlS${Axbd7R}Aq40Fj1Kd|XJ>Y;s%rTD8`(a6LVR={yt&X8Eae4GJZb2r4Vb;E!WAXVuA12H=kuuXcy+;+0Dg0WzYQ0}u683W zbnB;jNEH_N*I5aB2N#otZIWc^kwiJRHgY!jOevX7Djrrx!z1-JUn~+^6>?x7Xb}fk zlH_*@!k=uqLJcP4lGyX$jd^Domr+9J<`W(!p*En@wrx(IQq|_?~^6FtvV6Q%FRMe64>iw_eFb#1Q@bOrid&!=fD#S(gXEL+;9UvoW8e!2+L{>DV0A&kY zCoLv)X{y*^h|7g9huS!aB|4OEWfrtEcUREgyUyt+wS`uTIt&$3V5d z!@7#EOqQ=4yN)RpHW@+ujC1%A{w^5P2`I}2pK6_aso!Vm z{k-dpTcMwoI@HA)-F0?dVc=8mB*BiV{SFp1+JEdM~m)Ba%OyZU^$60JSC=izS& zZ`QI78Jp^VsedRNLPc5V{@dFK0JIz~XA)R-L#i@ zHGUz2&1%ygcUnAKk$$Fj8ns*bZ%A?)xyphLa<0Lz`9(&~Q}?Dtom;4p;*oP^e=*tp zUkTFs!}ti{a(0)#=|q{`-{h8y_NU}Ud|IhCV{}ybnlmdGj<>y@Qk4A;{!2-Blqv&D Vs-(yLN10#Md^}+84X((4{0?YR5o-Vd literal 0 HcmV?d00001 From 3e775f2ac689d01406045f54bb21a61350f6c13a Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sat, 16 Aug 2025 12:27:31 +0300 Subject: [PATCH 02/11] Added game over menu tiles to background_gfx.png and removed dedicated background file --- graphics/background_game_over.png | Bin 2158 -> 0 bytes graphics/background_gfx.png | Bin 3749 -> 3845 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 graphics/background_game_over.png diff --git a/graphics/background_game_over.png b/graphics/background_game_over.png deleted file mode 100644 index e1f1e29e84ce2ceb066f60e4e7e2206e60951870..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2158 zcmbW3do&x!8o+~k)Vs$P)nZwfODWn^EL~~6rINNvh-cc=sz<7|(W;_cx3s18XuX@H zqCr(yLQ+zZ(xq)kQlTEHU|aPTizY(ErswQA_uTu(y?1xcnVIv=d^7WXbH3kvbLTY7 zOGDK_6#xKe_;|bf$@&#p<)|ph+V91SPXGXwqdx8@{F5Fnjd$c6m@!mdnen~raq9%t z3HG>q(zRgO`$2k+S<(J$_h~@aGuWQm-Me-aGk|lhDwc5{J)blUw%xW0*_FvHJ^Sz* zc`x}pw6F|Sa)5(JkUgk;xT6d!9#3`YXDu?1u@gk&GuJ;)mysUYm-!ZRseBmsBo|}U ze?KZ(IR3FE$eIFYL(Lyd=O+?^h4BGqn-h)8TOCbL?*hhkkSf0ECU$aJj9vQje@2KM zghqE=E|;K9cecw1x0Neuy)gwlyB&Eq!8Ufg;G^>F`%x8jy+{hhZw!ZHBOLEE0vTc1 z*K*Gev1E3&Np?Q!FDNI*^fFEv8CE~^8>3x4{XCRPzqW*InJNu0$K`}8MFm#buiRR~ zj!l~{9H$y6Cf$gtx!U%|i9_;~V_nT#;Fq8iE7CNBPNCCzm`vL^!4tuZS8S^8#YP7P zy8UH4=Vt`$Q#vC?;gNCgkHZT+&wCi0Mo-k_P!Q$f_cYwiP@B9jK?^|(iqIn5YkRO0 zgy-x`(lVJg4(vHlEPnUy;wgs=E212|{pJtbTT@^VqU2@hc&7_yFVd!{#&5GX>k3)V z;Oni`H>+(+#B0zY)M*-x<`yXT-fv7EU$Rn-q0KVK3{hq-Uh&Tn|)OjFQ`yvU*u${3TkezZ+fwH?oWrQhK6M31Mfi_^vnZBWyRx~p90bKv( zf6yGPembG-Gg<6uW#0ib3=?agh*k^L#aZNOo;s#$6G+l4Gh{=UwqxN^akHpC#Q65F zgJH9>SuVddQ>U^vB>vgr+Kpk&@R0Bt7Z32a+Ao9USlQ9HbxHGHm9=T3KX)UV;OT4U zYSnt96~foWb;bpR&7#C6lV;N5+Y5&gu!&@6s4W!4C-n)u4G5Ca->m!THy-Kc`~u&$ zKqlS${Axbd7R}Aq40Fj1Kd|XJ>Y;s%rTD8`(a6LVR={yt&X8Eae4GJZb2r4Vb;E!WAXVuA12H=kuuXcy+;+0Dg0WzYQ0}u683W zbnB;jNEH_N*I5aB2N#otZIWc^kwiJRHgY!jOevX7Djrrx!z1-JUn~+^6>?x7Xb}fk zlH_*@!k=uqLJcP4lGyX$jd^Domr+9J<`W(!p*En@wrx(IQq|_?~^6FtvV6Q%FRMe64>iw_eFb#1Q@bOrid&!=fD#S(gXEL+;9UvoW8e!2+L{>DV0A&kY zCoLv)X{y*^h|7g9huS!aB|4OEWfrtEcUREgyUyt+wS`uTIt&$3V5d z!@7#EOqQ=4yN)RpHW@+ujC1%A{w^5P2`I}2pK6_aso!Vm z{k-dpTcMwoI@HA)-F0?dVc=8mB*BiV{SFp1+JEdM~m)Ba%OyZU^$60JSC=izS& zZ`QI78Jp^VsedRNLPc5V{@dFK0JIz~XA)R-L#i@ zHGUz2&1%ygcUnAKk$$Fj8ns*bZ%A?)xyphLa<0Lz`9(&~Q}?Dtom;4p;*oP^e=*tp zUkTFs!}ti{a(0)#=|q{`-{h8y_NU}Ud|IhCV{}ybnlmdGj<>y@Qk4A;{!2-Blqv&D Vs-(yLN10#Md^}+84X((4{0?YR5o-Vd diff --git a/graphics/background_gfx.png b/graphics/background_gfx.png index 15315a0ff78017d79919f9dca12b858d834352a9..fa7cc7bea83903c0730e59ce7849e0c8815175c6 100644 GIT binary patch literal 3845 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 delta 3450 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 Date: Tue, 19 Aug 2025 16:31:32 +0300 Subject: [PATCH 03/11] Affine background now turns red on game over + other WIP changes for game over screen --- graphics/background_gfx.png | Bin 3845 -> 3861 bytes include/graphic_utils.h | 19 +++++++------------ source/game.c | 23 +++++++++++++++-------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/graphics/background_gfx.png b/graphics/background_gfx.png index fa7cc7bea83903c0730e59ce7849e0c8815175c6..798282f47e2b6437df8bf864e28a69cfb9430b3d 100644 GIT binary patch delta 3544 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 delta 3504 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 - ((rect)->left) + 1); + /* 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); + return (((rect)->bottom) - ((rect)->top) + 1); } /* Clears a rect in the main background. diff --git a/source/game.c b/source/game.c index dd19796..14e9520 100644 --- a/source/game.c +++ b/source/game.c @@ -205,6 +205,8 @@ static const Rect TOP_LEFT_PANEL_ANIM_RECT = {0, 0, 8, 4 }; static const BG_POINT TOP_LEFT_BLIND_TITLE_POINT = {0, 21, }; static const Rect BIG_BLIND_TITLE_SRC_RECT = {0, 26, 8, 26 }; static const Rect BOSS_BLIND_TITLE_SRC_RECT = {0, 27, 8, 27 }; +// static const BG_POINT GAME_OVER_SRC_RECT_3X3_POS = {25, 29}; +// static const Rect GAME_OVER_MSG_DEST_RECT = {10, 6, 24, 10 }; // Rects for TTE (in pixels) static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING @@ -236,7 +238,8 @@ static const Rect ROUND_END_BLIND_REWARD_RECT = { 168, 96, UNDEFINED, UNDEF static const Rect ROUND_END_NUM_HANDS_RECT = {88, 116, UNDEFINED, UNDEFINED }; static const Rect HAND_REWARD_RECT = {168, UNDEFINED, UNDEFINED, UNDEFINED }; static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED }; -static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED }; +static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED }; +// static const Rect GAME_OVER_MSG_TEXT_RECT = {104, 56, UNDEFINED, UNDEFINED}; static const BG_POINT HELD_JOKERS_POS = {108, 10}; static const BG_POINT JOKER_DISCARD_TARGET = {240, 30}; @@ -974,6 +977,12 @@ void game_round_init() deck_shuffle(); // Shuffle the deck at the start of the round } +void game_lose_init() +{ + affine_background_set_color(CLR_RED); // TODO: Use text color? + +} + void init_game_state(enum GameState game_state_to_init) { // Switch written out, add init for states as needed @@ -989,6 +998,7 @@ void init_game_state(enum GameState game_state_to_init) case GAME_BLIND_SELECT: break; case GAME_LOSE: + game_lose_init(); break; default: break; @@ -1753,6 +1763,10 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection display_ante(++ante); } } + else if (hands <= 0) + { + game_set_state(GAME_LOSE); + } else { hand_state = HAND_DRAW; @@ -1870,13 +1884,6 @@ static void game_round_end_cashout() void game_playing() { - // TODO: Blind rect sliding into view animation... - if (hand_state == HAND_SELECT && hands == 0) - { - // TODO: Check if it's safe to change to game_set_state() without side effects - game_state = GAME_LOSE; - } - // Background logic (thissss might be moved to the card'ssss logic later. I'm a sssssnake) if (hand_state == HAND_DRAW || hand_state == HAND_DISCARD || hand_state == HAND_SELECT) { From 42a0e94afd12e4ba428a703c52374447cd5f9368 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 19 Aug 2025 17:47:24 +0300 Subject: [PATCH 04/11] Refactor - Added defines for text colors and used them in all usses of tte_printf --- include/graphic_utils.h | 13 ++++++++++ source/game.c | 53 ++++++++++++++++++++--------------------- source/main.c | 10 ++++---- 3 files changed, 44 insertions(+), 32 deletions(-) diff --git a/include/graphic_utils.h b/include/graphic_utils.h index 2b5d65b..70cb379 100644 --- a/include/graphic_utils.h +++ b/include/graphic_utils.h @@ -24,6 +24,19 @@ #define PAL_ROW_LEN 16 #define NUM_PALETTES 16 +#define TTE_BIT_UNPACK_OFFSET 14 +#define TTE_BIT_ON_CLR_IDX TTE_BIT_UNPACK_OFFSET + 1 + +#define TTE_YELLOW_PB 12 // 0xC +#define TTE_BLUE_PB 13 // 0xD +#define TTE_RED_PB 14 // 0xE +#define TTE_WHITE_PB 15 // 0xF + +#define TEXT_CLR_YELLOW RGB15(31, 20, 0) // 0x029F +#define TEXT_CLR_BLUE RGB15(0, 18, 31) // 0x7E40 +#define TEXT_CLR_RED RGB15(31, 9, 8) // 0x213F +#define TEXT_CLR_WHITE CLR_WHITE + /* Dimensions for a screenblock. * A 1024 size screenblock is arranged in a grid of 32x32 screen entries * Interestingly since each block is 8x8 pixels, the 240x160 GBA screen diff --git a/source/game.c b/source/game.c index 14e9520..f833907 100644 --- a/source/game.c +++ b/source/game.c @@ -519,7 +519,7 @@ void change_background(int id) obj_unhide(blind_select_tokens[BIG_BLIND]->obj, 0); obj_unhide(blind_select_tokens[BOSS_BLIND]->obj, 0); - 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 + const int default_y = 89 + (TILE_SIZE * 12); // Default y position for the blind select tokens. 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[BIG_BLIND], 120, default_y); sprite_position(blind_select_tokens[BOSS_BLIND], 160, default_y); @@ -635,7 +635,7 @@ void display_temp_score(int value) { int x_offset = 40 - get_digits_even(value) * TILE_SIZE; tte_erase_rect_wrapper(TEMP_SCORE_RECT); - tte_printf("#{P:%d,%d; cx:0xF000}%d", x_offset, TEMP_SCORE_RECT.top, value); + tte_printf("#{P:%d,%d; cx:0x%X000}%d", x_offset, TEMP_SCORE_RECT.top, TTE_WHITE_PB, value); } void display_score(int value) @@ -664,14 +664,14 @@ void display_score(int value) int rect_width = SCORE_RECT.right - SCORE_RECT.left; int x_offset = SCORE_RECT.left + (rect_width - text_width) / 2; - tte_printf("#{P:%d,48; cx:0xF000}%d%c", x_offset, display_value, score_suffix); + tte_printf("#{P:%d,48; cx:0x%X000}%d%c", x_offset, TTE_WHITE_PB, display_value, score_suffix); } void display_money(int value) { int x_offset = 32 - get_digits_odd(value) * TILE_SIZE; tte_erase_rect_wrapper(MONEY_TEXT_RECT); - tte_printf("#{P:%d,%d; cx:0xC000}$%d", x_offset, MONEY_TEXT_RECT.top, value); + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", x_offset, MONEY_TEXT_RECT.top, TTE_YELLOW_PB, value); } void display_chips(int value) @@ -679,19 +679,19 @@ void display_chips(int value) Rect chips_text_rect = CHIPS_TEXT_RECT; tte_erase_rect_wrapper(CHIPS_TEXT_RECT); update_text_rect_to_right_align_num(&chips_text_rect, value, OVERFLOW_LEFT); - tte_printf("#{P:%d,%d; cx:0xF000;}%d", chips_text_rect.left, chips_text_rect.top, value); + tte_printf("#{P:%d,%d; cx:0x%X000;}%d", chips_text_rect.left, chips_text_rect.top, TTE_WHITE_PB, value); } void display_mult(int value) { tte_erase_rect_wrapper(MULT_TEXT_RECT); - tte_printf("#{P:%d,%d; cx:0xF000;}%d", MULT_TEXT_RECT.left, MULT_TEXT_RECT.top, value); // Mult + tte_printf("#{P:%d,%d; cx:0x%X000;}%d", MULT_TEXT_RECT.left, MULT_TEXT_RECT.top, TTE_WHITE_PB, value); // Mult } void display_round(int value) { //tte_erase_rect_wrapper(ROUND_TEXT_RECT); - tte_printf("#{P:%d,%d; cx:0xC000}%d", ROUND_TEXT_RECT.left, ROUND_TEXT_RECT.top, round); + tte_printf("#{P:%d,%d; cx:0x%X000}%d", ROUND_TEXT_RECT.left, ROUND_TEXT_RECT.top, TTE_YELLOW_PB, round); } void display_ante(int value) @@ -715,7 +715,7 @@ static void print_hand_type(const char* hand_type_str) { if (hand_type_str == NULL) return; // NULL-checking paranoia - tte_printf("#{P:%d,%d; cx:0xF000}%s", HAND_TYPE_RECT.left, HAND_TYPE_RECT.top, hand_type_str); + tte_printf("#{P:%d,%d; cx:0x%X000}%s", HAND_TYPE_RECT.left, HAND_TYPE_RECT.top, TTE_WHITE_PB, hand_type_str); } void set_hand() @@ -971,8 +971,8 @@ void game_round_init() blind_req_text_rect.left -= TILE_SIZE; // Move left by one character width to make room for 'k' } - tte_printf("#{P:%d,%d; cx:0xE000}%d%c", blind_req_text_rect.left, blind_req_text_rect.top, blind_requirement, score_suffix); // Blind requirement - tte_printf("#{P:%d,%d; cx:0xC000}$%d", BLIND_REWARD_RECT.left, BLIND_REWARD_RECT.top, blind_get_reward(current_blind)); // Blind reward + tte_printf("#{P:%d,%d; cx:0x%X000}%d%c", blind_req_text_rect.left, blind_req_text_rect.top, TTE_RED_PB, blind_requirement, score_suffix); // Blind requirement + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", BLIND_REWARD_RECT.left, BLIND_REWARD_RECT.top, TTE_YELLOW_PB, blind_get_reward(current_blind)); // Blind reward deck_shuffle(); // Shuffle the deck at the start of the round } @@ -1058,7 +1058,7 @@ void game_init() change_background(BG_ID_BLIND_SELECT); - tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, deck_get_size(), deck_get_max_size()); // Deck size/max size + tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, TTE_WHITE_PB, deck_get_size(), deck_get_max_size()); // Deck size/max size display_round(round); // Set the round display display_score(score); // Set the score display @@ -1069,10 +1069,9 @@ void game_init() display_hands(hands); // Hand display_discards(discards); // Discard - //tte_printf("#{P:24,120; cx:0xC000}$%d", money); // Money display_money(money); // Set the money display - tte_printf("#{P:%d,%d; cx:0xC000}%d#{cx:0xF000}/%d", ANTE_TEXT_RECT.left, ANTE_TEXT_RECT.top, ante, MAX_ANTE); // Ante + tte_printf("#{P:%d,%d; cx:0x%X000}%d#{cx:0x%X000}/%d", ANTE_TEXT_RECT.left, ANTE_TEXT_RECT.top, TTE_YELLOW_PB, ante, TTE_WHITE_PB, MAX_ANTE); // Ante } static void game_playing_process_hand_select_input() @@ -1146,7 +1145,7 @@ static void game_playing_process_hand_select_input() selection_y = 0; display_hands(--discards); set_hand(); - tte_printf("#{P:%d,%d; cx:0xE000}%d", DISCARDS_TEXT_RECT.left, DISCARDS_TEXT_RECT.top, discards); + tte_printf("#{P:%d,%d; cx:0x%X000}%d", DISCARDS_TEXT_RECT.left, DISCARDS_TEXT_RECT.top, TTE_RED_PB, discards); } } } @@ -1854,14 +1853,14 @@ static void game_playing_ui_text_update() { if (background == BG_ID_CARD_SELECTING) { - tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", HAND_SIZE_RECT_SELECT.left, HAND_SIZE_RECT_SELECT.top, hand_get_size(), hand_get_max_size()); // Hand size/max size + tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", HAND_SIZE_RECT_SELECT.left, HAND_SIZE_RECT_SELECT.top, TTE_WHITE_PB, hand_get_size(), hand_get_max_size()); // Hand size/max size } else if (background == BG_ID_CARD_PLAYING) { - tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", HAND_SIZE_RECT_PLAYING.left, HAND_SIZE_RECT_PLAYING.top, hand_get_size(), hand_get_max_size()); // Hand size/max size + tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", HAND_SIZE_RECT_PLAYING.left, HAND_SIZE_RECT_PLAYING.top, TTE_WHITE_PB, hand_get_size(), hand_get_max_size()); // Hand size/max size } - tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, deck_get_size(), deck_get_max_size()); // Deck size/max size + tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, TTE_WHITE_PB, deck_get_size(), deck_get_max_size()); // Deck size/max size last_hand_size = hand_get_size(); last_deck_size = deck_get_size(); @@ -1963,7 +1962,7 @@ void game_round_end() int blind_req = blind_get_requirement(current_blind, current_ante); update_text_rect_to_right_align_num(&blind_req_rect, blind_req, OVERFLOW_RIGHT); - tte_printf("#{P:%d,%d; cx:0xE000}%d", blind_req_rect.left, blind_req_rect.top, blind_req); + tte_printf("#{P:%d,%d; cx:0x%X000}%d", blind_req_rect.left, blind_req_rect.top, TTE_RED_PB, blind_req); if (timer == 1) { @@ -2008,8 +2007,8 @@ void game_round_end() if (blind_reward > 0) { blind_reward--; - tte_printf("#{P:%d,%d; cx:0xC000}$%d", BLIND_REWARD_RECT.left , BLIND_REWARD_RECT.top, blind_reward); - tte_printf("#{P:%d,%d; cx:0xC000}$%d", ROUND_END_BLIND_REWARD_RECT.left, ROUND_END_BLIND_REWARD_RECT.top, blind_get_reward(current_blind) - blind_reward); + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", BLIND_REWARD_RECT.left , BLIND_REWARD_RECT.top, TTE_YELLOW_PB, blind_reward); + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", ROUND_END_BLIND_REWARD_RECT.left, ROUND_END_BLIND_REWARD_RECT.top, TTE_YELLOW_PB, blind_get_reward(current_blind) - blind_reward); } else if (timer > FRAMES(20)) { @@ -2090,7 +2089,7 @@ void game_round_end() int x = (8 + timer) * TILE_SIZE; int y = (13) * TILE_SIZE; - tte_printf("#{P:%d,%d; cx:0xF000}.", x, y); + tte_printf("#{P:%d,%d; cx:0x%X000}.", x, y, TTE_WHITE_PB); } else if (timer >= 30 && hand_reward > 0) // Wait an additional 15 frames since the last sequenced action { @@ -2101,13 +2100,13 @@ void game_round_end() single_line_rect.bottom = single_line_rect.top + 1; main_bg_se_copy_rect_1_tile_vert(single_line_rect, SE_DOWN); - tte_printf("#{P:%d,%d; cx:0xD000}%d #{cx:0xF000}Hands", ROUND_END_NUM_HANDS_RECT.left, ROUND_END_NUM_HANDS_RECT.top, hand_reward); // Print the hand reward + tte_printf("#{P:%d,%d; cx:0x%X000}%d #{cx:0x%X000}Hands", ROUND_END_NUM_HANDS_RECT.left, ROUND_END_NUM_HANDS_RECT.top, TTE_BLUE_PB, hand_reward, TTE_WHITE_PB); // Print the hand reward } else if (timer > 45 && timer % FRAMES(20) == 0) // After 15 frames, every 20 frames, increment the hand reward text until the hand reward variable is depleted { int y = (13 + hand_y) * TILE_SIZE; hand_reward--; - tte_printf("#{P:%d, %d; cx:0xC000}$%d", HAND_REWARD_RECT.left, y, hands - hand_reward); // Print the hand reward + tte_printf("#{P:%d, %d; cx:0x%X000}$%d", HAND_REWARD_RECT.left, y, TTE_YELLOW_PB, hands - hand_reward); // Print the hand reward } } @@ -2137,7 +2136,7 @@ void game_round_end() BG_POINT bottom_point = {6, 31}; main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(bottom_point), bottom_rect); - tte_printf("#{P:%d, %d; cx:0xF000}Cash Out: $%d", CASHOUT_RECT.left, CASHOUT_RECT.top, hands + blind_get_reward(current_blind)); // Print the cash out amount + tte_printf("#{P:%d, %d; cx:0x%X000}Cash Out: $%d", CASHOUT_RECT.left, CASHOUT_RECT.top, TTE_WHITE_PB, hands + blind_get_reward(current_blind)); // Print the cash out amount } else if (timer > FRAMES(40) && key_hit(SELECT_CARD)) // Wait until the player presses A to cash out { @@ -2193,7 +2192,7 @@ void print_price_under_sprite_object(SpriteObject *sprite_object, int price) { int x = fx2int(sprite_object->tx) + TILE_SIZE - (get_digits_even(price) - 1) * TILE_SIZE; int y = fx2int(sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE; // TODO: Should probably extract the sprite size - tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, price); + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", x, y, TTE_YELLOW_PB, price); } void erase_price_under_sprite_object(SpriteObject *sprite_object) @@ -2303,7 +2302,7 @@ static void game_shop_reroll(int *reroll_cost) } (*reroll_cost)++; - tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, *reroll_cost); + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, TTE_WHITE_PB, *reroll_cost); } static int jokers_sel_row_get_size() @@ -2510,7 +2509,7 @@ static void game_shop_process_user_input() // to trigger the selection change so the initial selection is visible shop_selection_grid.selection = SHOP_INIT_SEL; selection_grid_move_selection_horz(&shop_selection_grid, 1); - tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, reroll_cost); + tte_printf("#{P:%d,%d; cx:0x%X000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, TTE_WHITE_PB, reroll_cost); } // Shop input logic diff --git a/source/main.c b/source/main.c index 269fc09..646a7cb 100644 --- a/source/main.c +++ b/source/main.c @@ -28,15 +28,15 @@ void init() mmStart(MOD_MAIN_THEME, MM_PLAY_LOOP); // Initialize text engine - tte_init_se(0, BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB), 0, CLR_WHITE, 14, NULL, NULL); + tte_init_se(0, BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB), 0, CLR_WHITE, TTE_BIT_UNPACK_OFFSET, NULL, NULL); tte_erase_screen(); tte_init_con(); // TTE palette setup - pal_bg_bank[12][15] = 0x029F; // Yellow. honestly fuck libtonc because i cannot figure out how you're supposed to select a color from the palette index so i'm doing it like this - pal_bg_bank[13][15] = 0x7E40; // Blue - pal_bg_bank[14][15] = 0x213F; // Red - pal_bg_bank[15][15] = CLR_WHITE; + pal_bg_bank[TTE_YELLOW_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_YELLOW; // honestly fuck libtonc because i cannot figure out how you're supposed to select a color from the palette index so i'm doing it like this + pal_bg_bank[TTE_BLUE_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_BLUE; + pal_bg_bank[TTE_RED_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_RED; + pal_bg_bank[TTE_WHITE_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_WHITE; // Set up the video mode // BG0 is the TTE text layer From 065d846ac74324953c093ca576ea5efe5821c7b8 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 19 Aug 2025 17:59:26 +0300 Subject: [PATCH 05/11] Used text red color for game over background --- source/game.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/game.c b/source/game.c index f833907..b972527 100644 --- a/source/game.c +++ b/source/game.c @@ -979,7 +979,8 @@ void game_round_init() void game_lose_init() { - affine_background_set_color(CLR_RED); // TODO: Use text color? + // Using the text color to match the "Game Over" text, another shade of red could work better + affine_background_set_color(TEXT_CLR_RED); } From 5a70b002a9d08fa0c996acd44a70827de79fd93e Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 19 Aug 2025 18:33:47 +0300 Subject: [PATCH 06/11] graphic_utils refactors - renamed functions, optimized some code, used Tonc defines --- include/graphic_utils.h | 8 ++++---- source/game.c | 8 ++++---- source/graphic_utils.c | 22 ++++++++++------------ 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/include/graphic_utils.h b/include/graphic_utils.h index 70cb379..979e9f5 100644 --- a/include/graphic_utils.h +++ b/include/graphic_utils.h @@ -68,11 +68,11 @@ // When making this, missed that it already exists in tonc_math.h typedef RECT Rect; -/* Gets the screenblock tile for the given coordinates (x, y). +/* Gets the screenblock entry for the given coordinates (x, y). * x and y are in number of tiles. - * Returns the screenblock tile. + * Returns the screenblock entry. */ -u16 main_bg_se_get_tile(BG_POINT pos); +SE main_bg_se_get_se(BG_POINT pos); INLINE int rect_width(const Rect* rect) { @@ -108,7 +108,7 @@ void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos); * se_rect dimensions are in number of tiles. * The tile is copied to the top left corner of the rect. */ -void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect); +void main_bg_se_fill_rect_with_se(u16 tile, Rect se_rect); /* 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 diff --git a/source/game.c b/source/game.c index b972527..fc83856 100644 --- a/source/game.c +++ b/source/game.c @@ -981,7 +981,7 @@ void game_lose_init() { // Using the text color to match the "Game Over" text, another shade of red could work better affine_background_set_color(TEXT_CLR_RED); - + } void init_game_state(enum GameState game_state_to_init) @@ -2127,15 +2127,15 @@ void game_round_end() Rect top_rect = {11, 8, 22, 8}; BG_POINT top_point = {6, 29}; - main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(top_point), top_rect); + main_bg_se_fill_rect_with_se(main_bg_se_get_se(top_point), top_rect); Rect middle_rect = {11, 9, 22, 9}; BG_POINT middle_point = {6, 30}; - main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(middle_point), middle_rect); + main_bg_se_fill_rect_with_se(main_bg_se_get_se(middle_point), middle_rect); Rect bottom_rect = {11, 10, 22, 10}; BG_POINT bottom_point = {6, 31}; - main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(bottom_point), bottom_rect); + main_bg_se_fill_rect_with_se(main_bg_se_get_se(bottom_point), bottom_rect); tte_printf("#{P:%d, %d; cx:0x%X000}Cash Out: $%d", CASHOUT_RECT.left, CASHOUT_RECT.top, TTE_WHITE_PB, hands + blind_get_reward(current_blind)); // Print the cash out amount } diff --git a/source/graphic_utils.c b/source/graphic_utils.c index b568442..8c574e0 100644 --- a/source/graphic_utils.c +++ b/source/graphic_utils.c @@ -24,7 +24,7 @@ static void clip_se_rect_to_screenblock(Rect* rect) clip_se_rect_to_bounding_rect(rect, &FULL_SCREENBLOCK_RECT); } -u16 main_bg_se_get_tile(BG_POINT pos) +SE main_bg_se_get_se(BG_POINT pos) { return se_mat[MAIN_BG_SBB][pos.y][pos.x]; } @@ -108,20 +108,18 @@ void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos) int width = rect_width(&se_rect); int height = rect_height(&se_rect); - u16 tile_map[height][width]; + SE tile_map[height][width]; // Copy the rect to the tile map for (int sy = 0; sy < height; sy++) { - for (int sx = 0; sx < width; sx++) - { - BG_POINT pt; - pt.x = se_rect.left + sx; - pt.y = se_rect.top + sy; - tile_map[sy][sx] = main_bg_se_get_tile(pt); - } + memcpy16(&tile_map[sy][0], + &se_mat[MAIN_BG_SBB][se_rect.top + sy][se_rect.left], + width); } - + + // TODO: Avoid overflow + // Copy the tilemap to the new rect position for (int sy = 0; sy < height; sy++) { memcpy16(&se_mat[MAIN_BG_SBB][pos.y + sy][pos.x], @@ -130,7 +128,7 @@ void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos) } } -void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect) +void main_bg_se_fill_rect_with_se(SE se, Rect se_rect) { if (se_rect.left > se_rect.right || se_rect.top > se_rect.bottom) return; @@ -143,7 +141,7 @@ void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect) for (int sy = 0; sy < height; sy++) { - memset16(&se_mat[MAIN_BG_SBB][se_rect.top + sy][se_rect.left], tile, width); + memset16(&se_mat[MAIN_BG_SBB][se_rect.top + sy][se_rect.left], se, width); } } From c4b538c009163c5630b8747d3762524f56b257d9 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 19 Aug 2025 21:40:40 +0300 Subject: [PATCH 07/11] Basic game over screen + added main_bg_se_copy_expand_3x3_rect() --- include/graphic_utils.h | 14 +++++++++-- source/game.c | 11 +++++---- source/graphic_utils.c | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/include/graphic_utils.h b/include/graphic_utils.h index 979e9f5..eb74f0e 100644 --- a/include/graphic_utils.h +++ b/include/graphic_utils.h @@ -104,11 +104,21 @@ void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction); */ void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos); -/* Copies a tile to a rect in the main background. +/* Copies a screen entry to a rect in the main background. * se_rect dimensions are in number of tiles. * The tile is copied to the top left corner of the rect. */ -void main_bg_se_fill_rect_with_se(u16 tile, Rect se_rect); +void main_bg_se_fill_rect_with_se(SE tile, Rect se_rect); + +/* Copies a 3x3 rect into se_rect_dest, the 3x3 rect is stretched to fill se_rect_dest. + * The corners are copied, the sides are stretched, and the center is filled. + * The parameter se_rect_src_3x3_top_left points to the top left corner of the source + * 3x3 rect. + * Dest rect sides can be of length 2, then the sides are not copied, only the corners. + * But dest rect sides must be at least 2. + */ +void main_bg_se_copy_expand_3x3_rect(Rect se_rect_dest, BG_POINT se_rect_src_3x3_top_left); + /* 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 diff --git a/source/game.c b/source/game.c index fc83856..fb68de4 100644 --- a/source/game.c +++ b/source/game.c @@ -205,8 +205,8 @@ static const Rect TOP_LEFT_PANEL_ANIM_RECT = {0, 0, 8, 4 }; static const BG_POINT TOP_LEFT_BLIND_TITLE_POINT = {0, 21, }; static const Rect BIG_BLIND_TITLE_SRC_RECT = {0, 26, 8, 26 }; static const Rect BOSS_BLIND_TITLE_SRC_RECT = {0, 27, 8, 27 }; -// static const BG_POINT GAME_OVER_SRC_RECT_3X3_POS = {25, 29}; -// static const Rect GAME_OVER_MSG_DEST_RECT = {10, 6, 24, 10 }; +static const BG_POINT GAME_OVER_SRC_RECT_3X3_POS = {25, 29}; +static const Rect GAME_OVER_DIALOG_DEST_RECT= {11, 6, 23, 11 }; // Rects for TTE (in pixels) static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING @@ -239,7 +239,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 CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED }; static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED }; -// static const Rect GAME_OVER_MSG_TEXT_RECT = {104, 56, UNDEFINED, UNDEFINED}; +static const Rect GAME_OVER_MSG_TEXT_RECT = {104, 64, UNDEFINED, UNDEFINED}; static const BG_POINT HELD_JOKERS_POS = {108, 10}; static const BG_POINT JOKER_DISCARD_TARGET = {240, 30}; @@ -979,9 +979,12 @@ void game_round_init() void game_lose_init() { + // Disable window so it doesn't make the game over menu transparent + REG_DISPCNT &= ~DCNT_WIN0; // Using the text color to match the "Game Over" text, another shade of red could work better affine_background_set_color(TEXT_CLR_RED); - + main_bg_se_copy_expand_3x3_rect(GAME_OVER_DIALOG_DEST_RECT, GAME_OVER_SRC_RECT_3X3_POS); + tte_printf("#{P:%d,%d; cx:0x%X000}GAME OVER", GAME_OVER_MSG_TEXT_RECT.left, GAME_OVER_MSG_TEXT_RECT.top, TTE_RED_PB); } void init_game_state(enum GameState game_state_to_init) diff --git a/source/graphic_utils.c b/source/graphic_utils.c index 8c574e0..812f689 100644 --- a/source/graphic_utils.c +++ b/source/graphic_utils.c @@ -145,6 +145,59 @@ void main_bg_se_fill_rect_with_se(SE se, Rect se_rect) } } +void main_bg_se_copy_expand_3x3_rect(Rect se_dest_rect, BG_POINT src_top_left_pnt) +{ + clip_se_rect_to_screenblock(&se_dest_rect); + + int dest_rect_width = rect_width(&se_dest_rect); + int dest_rect_height = rect_height(&se_dest_rect); + + // Verify the dest rect is at least 2x2 + if (dest_rect_width < 2 || dest_rect_height < 2) + { + return; + } + + // Copy the corners + SE top_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y][src_top_left_pnt.x]; + se_mat[MAIN_BG_SBB][se_dest_rect.top][se_dest_rect.left] = top_left_se; + + SE top_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y][src_top_left_pnt.x + 2]; + se_mat[MAIN_BG_SBB][se_dest_rect.top][se_dest_rect.left + dest_rect_width - 1] = top_right_se; + + SE bottom_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 2][src_top_left_pnt.x]; + se_mat[MAIN_BG_SBB][se_dest_rect.top + dest_rect_height - 1][se_dest_rect.left] = bottom_left_se; + + SE bottom_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 2][src_top_left_pnt.x + 2]; + se_mat[MAIN_BG_SBB][se_dest_rect.top + dest_rect_height - 1][se_dest_rect.left + dest_rect_width - 1] = bottom_right_se; + + // Copy top and bottom sides + if (dest_rect_width > 2) + { + SE top_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y][src_top_left_pnt.x + 1]; + SE bottom_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 2][src_top_left_pnt.x + 1]; + memset16(&se_mat[MAIN_BG_SBB][se_dest_rect.top][se_dest_rect.left + 1], top_middle_se, dest_rect_width - 2); + memset16(&se_mat[MAIN_BG_SBB][se_dest_rect.bottom][se_dest_rect.left + 1], bottom_middle_se, dest_rect_width - 2); + } + + // Copy left and right sides + SE middle_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x]; + SE middle_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x + 2]; + for (int y = 1; y < dest_rect_height - 1; y++) + { + se_mat[MAIN_BG_SBB][se_dest_rect.top + y][se_dest_rect.left] = middle_left_se; + se_mat[MAIN_BG_SBB][se_dest_rect.top + y][se_dest_rect.left + dest_rect_width - 1] = middle_right_se; + } + + if (dest_rect_width > 2 && dest_rect_height > 2) + { + SE middle_fill_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x + 1]; + Rect dest_inner_fill_rect = {se_dest_rect.left + 1, se_dest_rect.top + 1, se_dest_rect.right - 1, se_dest_rect.bottom - 1}; + main_bg_se_fill_rect_with_se(middle_fill_se, dest_inner_fill_rect); + } + +} + void tte_erase_rect_wrapper(Rect rect) { tte_erase_rect(rect.left, rect.top, rect.right, rect.bottom); From a707927b2ffb266352643169d07e06176bbf9bb5 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Thu, 21 Aug 2025 19:07:02 +0300 Subject: [PATCH 08/11] Refactor - extracted card_in_hand_loop_handle_discard_and_shuffling() from cards_in_hand_update_loop() --- source/game.c | 233 ++++++++++++++++++++++++++------------------------ 1 file changed, 121 insertions(+), 112 deletions(-) diff --git a/source/game.c b/source/game.c index fb68de4..26ac9e6 100644 --- a/source/game.c +++ b/source/game.c @@ -1292,21 +1292,84 @@ static void game_playing_discarded_cards_loop() } } +static const int HAND_SPACING_LUT[MAX_HAND_SIZE] = { 28, 28, 28, 28, 27, 21, 18, 15, 13, 12, 10, 9, 9, 8, 8, 7 }; // This is a stupid way to do this but I don't care + +void card_in_hand_loop_handle_discard_and_shuffling(int card_idx, bool* discarded_card, FIXED* hand_x, FIXED* hand_y, bool* sound_played, bool* break_loop) +{ + *break_loop = false; + if (card_object_is_selected(hand[card_idx]) || hand_state == HAND_SHUFFLING) + { + if (!*discarded_card) + { + *hand_x = int2fx(240); + *hand_y = int2fx(70); + + if (!*sound_played) + { + play_sfx(SFX_CARD_DRAW, MM_BASE_PITCH_RATE + cards_drawn * PITCH_STEP_DISCARD_SFX); + *sound_played = true; + } + + if (hand[card_idx]->sprite_object->x >= *hand_x) + { + discard_push(hand[card_idx]->card); + card_object_destroy(&hand[card_idx]); + sort_cards(); + + hand_top--; + cards_drawn++; // This technically isn't drawing cards, I'm just reusing the variable + *sound_played = false; + timer = 0; + + *hand_y = hand[card_idx]->sprite_object->y; + *hand_x = hand[card_idx]->sprite_object->x; + } + + *discarded_card = true; + } + else + { + if (hand_state == HAND_DISCARD) + { + *hand_y -= int2fx(15); // Don't raise the card if we're mass discarding, it looks stupid. + } + else // hand_state == HAND_SHUFFLING + { + *hand_y += int2fx(24); + } + *hand_x = *hand_x + (int2fx(card_idx) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; + } + } + else + { + *hand_x = *hand_x + (int2fx(card_idx) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; + } + + if (card_idx == 0 && *discarded_card == false && timer % FRAMES(10) == 0) + { + hand_state = HAND_DRAW; + *sound_played = false; + cards_drawn = 0; + hand_selections = 0; + timer = 0; + *break_loop = true; + return; + }; +} + static void cards_in_hand_update_loop(bool* discarded_card, int* played_selections, bool* sound_played) { for (int i = hand_top + 1; i >= 0; i--) // Start from the end of the hand and work backwards because that's how Balatro does it { if (hand[i] != NULL) { - const int spacing_lut[MAX_HAND_SIZE] = { 28, 28, 28, 28, 27, 21, 18, 15, 13, 12, 10, 9, 9, 8, 8, 7 }; // This is a stupid way to do this but I don't care - FIXED hand_x = int2fx(120); FIXED hand_y = int2fx(90); switch (hand_state) { case HAND_DRAW: - hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; + hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; break; case HAND_SELECT: bool is_focused = (i == selection_x && selection_y == 0); @@ -1330,72 +1393,18 @@ static void cards_in_hand_update_loop(bool* discarded_card, int* played_selectio hand[i]->sprite_object->vy = 0; } - hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; // TODO: Change this later to reference a 2D LUT of positions + hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; // TODO: Change this later to reference a 2D LUT of positions break; case HAND_SHUFFLING: /* FALL THROUGH */ case HAND_DISCARD: // TODO: Add sound - if (card_object_is_selected(hand[i]) || hand_state == HAND_SHUFFLING) - { - if (!*discarded_card) - { - hand_x = int2fx(240); - hand_y = int2fx(70); - - if (!*sound_played) - { - play_sfx(SFX_CARD_DRAW, MM_BASE_PITCH_RATE + cards_drawn*PITCH_STEP_DISCARD_SFX); - *sound_played = true; - } - - if (hand[i]->sprite_object->x >= hand_x) - { - discard_push(hand[i]->card); - card_object_destroy(&hand[i]); - sort_cards(); - - hand_top--; - cards_drawn++; // This technically isn't drawing cards, I'm just reusing the variable - *sound_played = false; - timer = 0; - - hand_y = hand[i]->sprite_object->y; - hand_x = hand[i]->sprite_object->x; - } - - *discarded_card = true; - } - else - { - if (hand_state == HAND_DISCARD) - { - hand_y -= int2fx(15); // Don't raise the card if we're mass discarding, it looks stupid. - } - else - { - hand_y += int2fx(24); - } - hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; - } - } - else - { - hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; - } - - if (i == 0 && *discarded_card == false && timer % FRAMES(10) == 0) - { - hand_state = HAND_DRAW; - *sound_played = false; - cards_drawn = 0; - hand_selections = 0; - timer = 0; - break; - } + bool break_loop; + card_in_hand_loop_handle_discard_and_shuffling(i, discarded_card, &hand_x, &hand_y, sound_played, &break_loop); + if (break_loop) break; break; case HAND_PLAY: - hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; + hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; hand_y += int2fx(24); if (card_object_is_selected(hand[i]) && *discarded_card == false && timer % FRAMES(10) == 0) @@ -1569,7 +1578,7 @@ static void cards_in_hand_update_loop(bool* discarded_card, int* played_selectio break; case HAND_PLAYING: // Don't need to do anything here, just wait for the player to select cards - hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; + hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; hand_y += int2fx(24); break; } @@ -1799,55 +1808,6 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection } } -static void discarded_jokers_update_loop() -{ - if (discarded_jokers == NULL) - return; - - // Iterating backwards because of removal within loop - for (int i = list_get_size(discarded_jokers) - 1; i >= 0; i--) - { - JokerObject* joker_object = list_get(discarded_jokers, i); - joker_object_update(joker_object); - if (joker_object->sprite_object->x == joker_object->sprite_object->tx - && joker_object->sprite_object->y == joker_object->sprite_object->ty) - { - list_remove_by_idx(discarded_jokers, i); - joker_object_destroy(&joker_object); - } - } - -} - -static void held_jokers_update_loop() -{ - const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] = - { - {0, 0, 0, 0, 0}, - {13, -13, 0, 0, 0}, - {26, 0, -26, 0, 0}, - {39, 13, -13, -39, 0}, - {40, 20, 0, -20, -40} - }; - - FIXED hand_x = int2fx(HELD_JOKERS_POS.x); - - int jokers_top = list_get_size(jokers) - 1; - for (int i = jokers_top; i >= 0; i--) - { - JokerObject *joker = list_get(jokers, i); - joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]); - - joker_object_update(joker); - } -} - -static void jokers_update_loop() -{ - held_jokers_update_loop(); - discarded_jokers_update_loop(); -} - static void game_playing_ui_text_update() { static int last_hand_size = 0; @@ -2815,6 +2775,55 @@ void game_blind_select() } } +static void discarded_jokers_update_loop() +{ + if (discarded_jokers == NULL) + return; + + // Iterating backwards because of removal within loop + for (int i = list_get_size(discarded_jokers) - 1; i >= 0; i--) + { + JokerObject* joker_object = list_get(discarded_jokers, i); + joker_object_update(joker_object); + if (joker_object->sprite_object->x == joker_object->sprite_object->tx + && joker_object->sprite_object->y == joker_object->sprite_object->ty) + { + list_remove_by_idx(discarded_jokers, i); + joker_object_destroy(&joker_object); + } + } + +} + +static void held_jokers_update_loop() +{ + const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] = + { + {0, 0, 0, 0, 0}, + {13, -13, 0, 0, 0}, + {26, 0, -26, 0, 0}, + {39, 13, -13, -39, 0}, + {40, 20, 0, -20, -40} + }; + + FIXED hand_x = int2fx(HELD_JOKERS_POS.x); + + int jokers_top = list_get_size(jokers) - 1; + for (int i = jokers_top; i >= 0; i--) + { + JokerObject *joker = list_get(jokers, i); + joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]); + + joker_object_update(joker); + } +} + +static void jokers_update_loop() +{ + held_jokers_update_loop(); + discarded_jokers_update_loop(); +} + void game_update() { timer++; From 7f5ed5433fbd39b8ac6dde2b7715df5cb4ae9ca2 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Thu, 21 Aug 2025 23:33:51 +0300 Subject: [PATCH 09/11] Win screen + Game over animation with hand discard --- include/game.h | 1 + include/graphic_utils.h | 11 ++++ source/game.c | 129 ++++++++++++++++++++++++++++++++-------- source/graphic_utils.c | 26 ++++++-- 4 files changed, 137 insertions(+), 30 deletions(-) diff --git a/include/game.h b/include/game.h index 01c7d3d..ed65d3d 100644 --- a/include/game.h +++ b/include/game.h @@ -32,6 +32,7 @@ enum GameState GAME_SHOP, GAME_BLIND_SELECT, GAME_LOSE, + GAME_WIN }; enum HandState diff --git a/include/graphic_utils.h b/include/graphic_utils.h index eb74f0e..1df8e49 100644 --- a/include/graphic_utils.h +++ b/include/graphic_utils.h @@ -1,6 +1,8 @@ #ifndef GRAPHIC_UTILS_H #define GRAPHIC_UTILS_H +#include + /* This file contains general utils and wrappers that relate to * graphics/video/vram and generally displaying things on the screen. * Mostly wrappers and defines for using tonc. @@ -87,6 +89,15 @@ INLINE int rect_height(const Rect* rect) return (((rect)->bottom) - ((rect)->top) + 1); } +/* Copies an SE rect vertically in direction by a single tile. + * bg_sbb is the SBB of the background in which to move the rect + * direction must be either SE_UP or SE_DOWN. + * se_rect dimensions are in number of tiles. + * + * NOTE: This does not work with TTE_SBB, probably because it's 4BPP... + */ +void bg_se_copy_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction); + /* Clears a rect in the main background. * The se_rect dimensions need to be in number of tiles. */ diff --git a/source/game.c b/source/game.c index 26ac9e6..ce165ca 100644 --- a/source/game.c +++ b/source/game.c @@ -186,7 +186,7 @@ static const Rect POP_MENU_ANIM_RECT = {9, 7, 24, 31 }; // 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 -static const Rect SINGLE_BLIND_SELECT_RECT = { 9, 7, 13, 32 }; +static const Rect SINGLE_BLIND_SELECT_RECT = {9, 7, 13, 32 }; static const Rect HAND_BG_RECT_SELECTING = {9, 11, 24, 17 }; // TODO: Currently unused, remove? @@ -206,7 +206,8 @@ static const BG_POINT TOP_LEFT_BLIND_TITLE_POINT = {0, 21, }; static const Rect BIG_BLIND_TITLE_SRC_RECT = {0, 26, 8, 26 }; static const Rect BOSS_BLIND_TITLE_SRC_RECT = {0, 27, 8, 27 }; static const BG_POINT GAME_OVER_SRC_RECT_3X3_POS = {25, 29}; -static const Rect GAME_OVER_DIALOG_DEST_RECT= {11, 6, 23, 11 }; +static const Rect GAME_OVER_DIALOG_DEST_RECT= {11, 21, 23, 26}; +static const Rect GAME_OVER_ANIM_RECT = {11, 8, 23, 26}; // Rects for TTE (in pixels) static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING @@ -239,7 +240,9 @@ 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 CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED }; static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED }; -static const Rect GAME_OVER_MSG_TEXT_RECT = {104, 64, UNDEFINED, UNDEFINED}; +static const Rect GAME_LOSE_MSG_TEXT_RECT = {104, 72, UNDEFINED, UNDEFINED}; +// 1 character to the right oF GAME_LOSE +static const Rect GAME_WIN_MSG_TEXT_RECT = {112, 72, UNDEFINED, UNDEFINED}; static const BG_POINT HELD_JOKERS_POS = {108, 10}; static const BG_POINT JOKER_DISCARD_TARGET = {240, 30}; @@ -248,6 +251,7 @@ static const BG_POINT JOKER_DISCARD_TARGET = {240, 30}; //TODO: Properly define and use #define MENU_POP_OUT_ANIM_FRAMES 20 +#define GAME_OVER_ANIM_FRAMES 15 #define SCORED_CARD_TEXT_Y 48 @@ -925,7 +929,7 @@ void increment_blind(enum BlindState increment_reason) } } -void game_round_init() +static void game_round_init() { // once we have a main menu, move the seed set there. this is only here now because there isn't a way to set the seed to a psudorandom value unless there is something to wait on set_seed(rng_seed); @@ -977,17 +981,29 @@ void game_round_init() deck_shuffle(); // Shuffle the deck at the start of the round } -void game_lose_init() +static void game_over_init() { - // Disable window so it doesn't make the game over menu transparent - REG_DISPCNT &= ~DCNT_WIN0; - // Using the text color to match the "Game Over" text, another shade of red could work better - affine_background_set_color(TEXT_CLR_RED); + // Clears the round end menu + main_bg_se_clear_rect(POP_MENU_ANIM_RECT); main_bg_se_copy_expand_3x3_rect(GAME_OVER_DIALOG_DEST_RECT, GAME_OVER_SRC_RECT_3X3_POS); - tte_printf("#{P:%d,%d; cx:0x%X000}GAME OVER", GAME_OVER_MSG_TEXT_RECT.left, GAME_OVER_MSG_TEXT_RECT.top, TTE_RED_PB); } -void init_game_state(enum GameState game_state_to_init) +static void game_lose_init() +{ + game_over_init(); + // Using the text color to match the "Game Over" text + affine_background_set_color(TEXT_CLR_RED); + +} + +static void game_win_init() +{ + game_over_init(); + // Using the text color to match the "You Win" text + affine_background_set_color(TEXT_CLR_BLUE); +} + +static void init_game_state(enum GameState game_state_to_init) { // Switch written out, add init for states as needed switch (game_state_to_init) @@ -1004,13 +1020,16 @@ void init_game_state(enum GameState game_state_to_init) case GAME_LOSE: game_lose_init(); break; + case GAME_WIN: + game_win_init(); + break; default: break; } } // Game functions -void game_set_state(enum GameState new_game_state) +static void game_set_state(enum GameState new_game_state) { timer = 0; // Reset the timer init_game_state(new_game_state); @@ -1249,6 +1268,37 @@ static void game_playing_process_card_draw() } } +static bool game_round_is_over() +{ + return hands == 0 || score >= blind_get_requirement(current_blind, ante); +} + +static void game_playing_handle_round_over() +{ + enum GameState next_state = GAME_ROUND_END; + + if (score >= blind_get_requirement(current_blind, ante)) + { + if (current_blind == BOSS_BLIND) + { + if (ante < MAX_ANTE) + { + display_ante(++ante); + } + else + { + next_state = GAME_WIN; + } + } + } + else if (hands == 0) + { + next_state = GAME_LOSE; + } + + game_set_state(next_state); +} + static void game_playing_discarded_cards_loop() { // Discarded cards loop (mainly for shuffling) @@ -1287,7 +1337,8 @@ static void game_playing_discarded_cards_loop() if (discard_top == -1 && discarded_card_object == NULL) // If there are no more discarded cards, stop shuffling { - game_set_state(GAME_ROUND_END); // Set the game state back to playing + // After HAND_SHUFFLING the round is over + game_playing_handle_round_over(); } } } @@ -1296,6 +1347,12 @@ static const int HAND_SPACING_LUT[MAX_HAND_SIZE] = { 28, 28, 28, 28, 27, 21, 18, void card_in_hand_loop_handle_discard_and_shuffling(int card_idx, bool* discarded_card, FIXED* hand_x, FIXED* hand_y, bool* sound_played, bool* break_loop) { + if (hand_state != HAND_DISCARD && hand_state != HAND_SHUFFLING) + { + // Assumes hand_state is one of these + return; + } + *break_loop = false; if (card_object_is_selected(hand[card_idx]) || hand_state == HAND_SHUFFLING) { @@ -1347,6 +1404,7 @@ void card_in_hand_loop_handle_discard_and_shuffling(int card_idx, bool* discarde if (card_idx == 0 && *discarded_card == false && timer % FRAMES(10) == 0) { + // This is never reached in the case of HAND_SHUFFLING. // Not sure why but that's how it's supposed to be. hand_state = HAND_DRAW; *sound_played = false; cards_drawn = 0; @@ -1766,18 +1824,9 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection if (i == played_top) { - if (score >= blind_get_requirement(current_blind, ante)) + if (game_round_is_over()) { hand_state = HAND_SHUFFLING; - - if (current_blind == BOSS_BLIND) - { - display_ante(++ante); - } - } - else if (hands <= 0) - { - game_set_state(GAME_LOSE); } else { @@ -2824,6 +2873,35 @@ static void jokers_update_loop() discarded_jokers_update_loop(); } +static void game_over_anim_frame() +{ + main_bg_se_move_rect_1_tile_vert(GAME_OVER_ANIM_RECT, SE_UP); +} + +static void game_lose() +{ + if (timer < GAME_OVER_ANIM_FRAMES) + { + game_over_anim_frame(); + } + else if (timer == GAME_OVER_ANIM_FRAMES) + { + tte_printf("#{P:%d,%d; cx:0x%X000}GAME OVER", GAME_LOSE_MSG_TEXT_RECT.left, GAME_LOSE_MSG_TEXT_RECT.top, TTE_RED_PB); + } +} + +static void game_win() +{ + if (timer < GAME_OVER_ANIM_FRAMES) + { + game_over_anim_frame(); + } + else if (timer == GAME_OVER_ANIM_FRAMES) + { + tte_printf("#{P:%d,%d; cx:0x%X000}YOU WIN", GAME_WIN_MSG_TEXT_RECT.left, GAME_WIN_MSG_TEXT_RECT.top, TTE_BLUE_PB); + } +} + void game_update() { timer++; @@ -2854,7 +2932,10 @@ void game_update() game_blind_select(); break; case GAME_LOSE: - // Handle lose logic here + game_lose(); + break; + case GAME_WIN: + game_win(); break; } } \ No newline at end of file diff --git a/source/graphic_utils.c b/source/graphic_utils.c index 812f689..524d684 100644 --- a/source/graphic_utils.c +++ b/source/graphic_utils.c @@ -59,11 +59,10 @@ void main_bg_se_clear_rect(Rect se_rect) } } - // Internal static function to merge implementation of move/copy functions. -static void main_bg_se_copy_or_move_rect_1_tile_vert(Rect se_rect, int direction, bool move) +static void bg_se_copy_or_move_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction, bool move) { - if (se_rect.left > se_rect.right + if (se_rect.left > se_rect.right || (direction != SE_UP && direction != SE_DOWN)) { return; @@ -77,17 +76,32 @@ static void main_bg_se_copy_or_move_rect_1_tile_vert(Rect se_rect, int direction for (int y = start; y != end - direction; y -= direction) { - memcpy16(&(se_mat[MAIN_BG_SBB][y + direction][se_rect.left]), - &se_mat[MAIN_BG_SBB][y][se_rect.left], + memcpy16(&(se_mat[bg_sbb][y + direction][se_rect.left]), + &se_mat[bg_sbb][y][se_rect.left], rect_width(&se_rect)); } if (move) { - memset16(&se_mat[MAIN_BG_SBB][end][se_rect.left], 0x0000, rect_width(&se_rect)); + memset16(&se_mat[bg_sbb][end][se_rect.left], 0x0000, rect_width(&se_rect)); } } +static void main_bg_se_copy_or_move_rect_1_tile_vert(Rect se_rect, int direction, bool move) +{ + bg_se_copy_or_move_rect_1_tile_vert(MAIN_BG_SBB, se_rect, direction, move); +} + +void bg_se_copy_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction) +{ + bg_se_copy_or_move_rect_1_tile_vert(MAIN_BG_SBB, se_rect, direction, false); +} + +void bg_se_move_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction) +{ + bg_se_copy_or_move_rect_1_tile_vert(MAIN_BG_SBB, se_rect, direction, true); +} + void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction) { main_bg_se_copy_or_move_rect_1_tile_vert(se_rect, direction, false); From 854c52464f5c1dbb7d87044af48fac01ff2ae4f1 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Fri, 22 Aug 2025 00:37:02 +0300 Subject: [PATCH 10/11] Small refactor - extracted helper functiosn for main_bg_se_copy_expand_3x3_rect() --- source/graphic_utils.c | 72 ++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/source/graphic_utils.c b/source/graphic_utils.c index 524d684..2e76aae 100644 --- a/source/graphic_utils.c +++ b/source/graphic_utils.c @@ -159,6 +159,46 @@ void main_bg_se_fill_rect_with_se(SE se, Rect se_rect) } } +// Helper: Copy the corners of a 3x3 tile block +static void main_bg_se_expand_3x3_copy_corners(const Rect* se_dest_rect, const BG_POINT* src_top_left_pnt, int dest_rect_width, int dest_rect_height) +{ + SE top_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y][src_top_left_pnt->x]; + se_mat[MAIN_BG_SBB][se_dest_rect->top][se_dest_rect->left] = top_left_se; + + SE top_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y][src_top_left_pnt->x + 2]; + se_mat[MAIN_BG_SBB][se_dest_rect->top][se_dest_rect->left + dest_rect_width - 1] = top_right_se; + + SE bottom_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 2][src_top_left_pnt->x]; + se_mat[MAIN_BG_SBB][se_dest_rect->top + dest_rect_height - 1][se_dest_rect->left] = bottom_left_se; + + SE bottom_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 2][src_top_left_pnt->x + 2]; + se_mat[MAIN_BG_SBB][se_dest_rect->top + dest_rect_height - 1][se_dest_rect->left + dest_rect_width - 1] = bottom_right_se; +} + +// Helper: Copy the top and bottom sides of a 3x3 tile block +static void main_bg_se_expand_3x3_copy_top_bottom(const Rect* se_dest_rect, const BG_POINT* src_top_left_pnt, int dest_rect_width) +{ + if (dest_rect_width > 2) + { + SE top_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y][src_top_left_pnt->x + 1]; + SE bottom_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 2][src_top_left_pnt->x + 1]; + memset16(&se_mat[MAIN_BG_SBB][se_dest_rect->top][se_dest_rect->left + 1], top_middle_se, dest_rect_width - 2); + memset16(&se_mat[MAIN_BG_SBB][se_dest_rect->bottom][se_dest_rect->left + 1], bottom_middle_se, dest_rect_width - 2); + } +} + +// Helper: Copy the left and right sides of a 3x3 tile block +static void main_bg_se_expand_3x3_copy_left_right(const Rect* se_dest_rect, const BG_POINT* src_top_left_pnt, int dest_rect_width, int dest_rect_height) +{ + SE middle_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 1][src_top_left_pnt->x]; + SE middle_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 1][src_top_left_pnt->x + 2]; + for (int y = 1; y < dest_rect_height - 1; y++) + { + se_mat[MAIN_BG_SBB][se_dest_rect->top + y][se_dest_rect->left] = middle_left_se; + se_mat[MAIN_BG_SBB][se_dest_rect->top + y][se_dest_rect->left + dest_rect_width - 1] = middle_right_se; + } +} + void main_bg_se_copy_expand_3x3_rect(Rect se_dest_rect, BG_POINT src_top_left_pnt) { clip_se_rect_to_screenblock(&se_dest_rect); @@ -173,43 +213,21 @@ void main_bg_se_copy_expand_3x3_rect(Rect se_dest_rect, BG_POINT src_top_left_pn } // Copy the corners - SE top_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y][src_top_left_pnt.x]; - se_mat[MAIN_BG_SBB][se_dest_rect.top][se_dest_rect.left] = top_left_se; - - SE top_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y][src_top_left_pnt.x + 2]; - se_mat[MAIN_BG_SBB][se_dest_rect.top][se_dest_rect.left + dest_rect_width - 1] = top_right_se; - - SE bottom_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 2][src_top_left_pnt.x]; - se_mat[MAIN_BG_SBB][se_dest_rect.top + dest_rect_height - 1][se_dest_rect.left] = bottom_left_se; - - SE bottom_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 2][src_top_left_pnt.x + 2]; - se_mat[MAIN_BG_SBB][se_dest_rect.top + dest_rect_height - 1][se_dest_rect.left + dest_rect_width - 1] = bottom_right_se; + main_bg_se_expand_3x3_copy_corners(&se_dest_rect, &src_top_left_pnt, dest_rect_width, dest_rect_height); // Copy top and bottom sides - if (dest_rect_width > 2) - { - SE top_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y][src_top_left_pnt.x + 1]; - SE bottom_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 2][src_top_left_pnt.x + 1]; - memset16(&se_mat[MAIN_BG_SBB][se_dest_rect.top][se_dest_rect.left + 1], top_middle_se, dest_rect_width - 2); - memset16(&se_mat[MAIN_BG_SBB][se_dest_rect.bottom][se_dest_rect.left + 1], bottom_middle_se, dest_rect_width - 2); - } + main_bg_se_expand_3x3_copy_top_bottom(&se_dest_rect, &src_top_left_pnt, dest_rect_width); // Copy left and right sides - SE middle_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x]; - SE middle_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x + 2]; - for (int y = 1; y < dest_rect_height - 1; y++) - { - se_mat[MAIN_BG_SBB][se_dest_rect.top + y][se_dest_rect.left] = middle_left_se; - se_mat[MAIN_BG_SBB][se_dest_rect.top + y][se_dest_rect.left + dest_rect_width - 1] = middle_right_se; - } - + main_bg_se_expand_3x3_copy_left_right(&se_dest_rect, &src_top_left_pnt, dest_rect_width, dest_rect_height); + + // Fill the center if needed if (dest_rect_width > 2 && dest_rect_height > 2) { SE middle_fill_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x + 1]; Rect dest_inner_fill_rect = {se_dest_rect.left + 1, se_dest_rect.top + 1, se_dest_rect.right - 1, se_dest_rect.bottom - 1}; main_bg_se_fill_rect_with_se(middle_fill_se, dest_inner_fill_rect); } - } void tte_erase_rect_wrapper(Rect rect) From 3be49b1d808a0f699866f676e1354c55cd67adcc Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Fri, 22 Aug 2025 02:09:24 +0300 Subject: [PATCH 11/11] Removed old comment --- source/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/main.c b/source/main.c index 646a7cb..066d9a0 100644 --- a/source/main.c +++ b/source/main.c @@ -33,7 +33,7 @@ void init() tte_init_con(); // TTE palette setup - pal_bg_bank[TTE_YELLOW_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_YELLOW; // honestly fuck libtonc because i cannot figure out how you're supposed to select a color from the palette index so i'm doing it like this + pal_bg_bank[TTE_YELLOW_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_YELLOW; pal_bg_bank[TTE_BLUE_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_BLUE; pal_bg_bank[TTE_RED_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_RED; pal_bg_bank[TTE_WHITE_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_WHITE;