From 309ebf281aa46c91f0b4d139e71a386e0101c3ea Mon Sep 17 00:00:00 2001 From: cellos51 Date: Wed, 16 Jul 2025 00:55:27 -0400 Subject: [PATCH] Major refactor, too much else to list, check the git changes. --- graphics/background_blind_select_gfx.png | Bin 3675 -> 3653 bytes graphics/background_gfx.png | Bin 2657 -> 2924 bytes graphics/background_shop_gfx.png | Bin 3428 -> 3429 bytes include/blind.h | 3 + include/graphic_utils.h | 19 + source/blind.c | 8 +- source/game.c | 514 +++++++++++------------ source/graphic_utils.c | 44 +- 8 files changed, 321 insertions(+), 267 deletions(-) diff --git a/graphics/background_blind_select_gfx.png b/graphics/background_blind_select_gfx.png index e901bfd7b7ad85e16b9c4b94df1f3d15fd3ec534..9f5487434fbf585bd475dda4eb3cdcb8bf15b100 100644 GIT binary patch delta 3497 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 ah|D&>rNuw#qA2<&1D&?AKUsYOfBQc>y15?! delta 3485 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 diff --git a/graphics/background_gfx.png b/graphics/background_gfx.png index d1f8d6da48f2724540889cb8e0f5c083a8434464..3517421859e326ec2673be4f66a31365c0ef12cb 100644 GIT binary patch delta 2730 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 diff --git a/graphics/background_shop_gfx.png b/graphics/background_shop_gfx.png index b63d0554a15aa28b2ee492d42f542985e5cbcfd9..b4215e128923892e97a2323c4199085b0ba05d35 100644 GIT binary patch delta 3262 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 literal 3428 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 diff --git a/include/blind.h b/include/blind.h index b559e29..e42f88d 100644 --- a/include/blind.h +++ b/include/blind.h @@ -26,6 +26,9 @@ static const int ante_lut[MAX_ANTE + 1] = {100, 300, 800, 2000, 5000, 11000, 200 #define BLIND_SHADOW_COLOR_INDEX 2 #define BLIND_HIGHLIGHT_COLOR_INDEX 3 #define BLIND_MAIN_COLOR_INDEX 4 +#define BLIND_BACKGROUND_MAIN_COLOR_INDEX 5 +#define BLIND_BACKGROUND_SECONDARY_COLOR_INDEX 6 +#define BLIND_BACKGROUND_SHADOW_COLOR_INDEX 7 enum BlindState { diff --git a/include/graphic_utils.h b/include/graphic_utils.h index e505f74..cf118bf 100644 --- a/include/graphic_utils.h +++ b/include/graphic_utils.h @@ -21,6 +21,7 @@ #define TTE_CBB 0 #define AFFINE_BG_SBB 2 #define AFFINE_BG_CBB 2 +#define PAL_ROW_LEN 16 /* Dimensions for a screenblock. * A 1024 size screenblock is arranged in a grid of 32x32 screen entries @@ -45,6 +46,12 @@ typedef struct #define UNDEFINED -1 +/* Gets the screenblock tile for the given coordinates (x, y). + * x and y are in number of tiles. + * Returns the screenblock tile. + */ +u16 main_bg_se_get_tile(int x, int y); + /* Clears a rect in the main background. * The se_rect dimensions need to be in number of tiles. */ @@ -56,6 +63,18 @@ void main_bg_se_clear_rect(Rect se_rect); */ void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction); +/* Copies a rect in the main background from se_rect to the position (x, y). + * se_rect dimensions are in number of tiles. + * x and y are the coordinates in number of tiles. + */ +void main_bg_se_copy_rect(Rect se_rect, int x, int y); + +/* Copies a tile 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_copy_tile_to_rect(u16 tile, Rect se_rect); + // A wrapper for tte_erase_rect that would use the rect struct void tte_erase_rect_wrapper(Rect rect); diff --git a/source/blind.c b/source/blind.c index 79971d3..aaf560e 100644 --- a/source/blind.c +++ b/source/blind.c @@ -1,12 +1,12 @@ #include #include "blind.h" - #include "blinds_gfx.h" +#include "graphic_utils.h" -static const u16 small_blind_token_palette[5] = {0x0000, 0x7FFF, 0x34A1, 0x5DCB, 0x5104}; -static const u16 big_blind_token_palette[5] = {0x0000, 0x2527, 0x15F5, 0x36FC, 0x1E9C}; -static const u16 boss_blind_token_palette[5] = {0x0000, 0x2CC9, 0x3D0D, 0x5E14, 0x5171}; // This variable is temporary, each boss blind will have its own unique palette +static const u16 small_blind_token_palette[PAL_ROW_LEN] = {0x0000, 0x7FFF, 0x34A1, 0x5DCB, 0x5104, 0x55A0, 0x2D01, 0x34E0}; +static const u16 big_blind_token_palette[PAL_ROW_LEN] = {0x0000, 0x2527, 0x15F5, 0x36FC, 0x1E9C, 0x01B4, 0x0D0A, 0x010E}; +static const u16 boss_blind_token_palette[PAL_ROW_LEN] = {0x0000, 0x2CC9, 0x3D0D, 0x5E14, 0x5171}; // This variable is temporary, each boss blind will have its own unique palette void blinds_init() { diff --git a/source/game.c b/source/game.c index 65fa248..55140df 100644 --- a/source/game.c +++ b/source/game.c @@ -10,6 +10,7 @@ #include "card.h" #include "blind.h" #include "graphic_utils.h" +#include "tonc_video.h" #include "background_gfx.h" #include "background_round_end_gfx.h" @@ -18,7 +19,11 @@ #include "soundbank.h" -static int timer = 0; // This might already exist in libtonc but idk so i'm just making my own +// This seed system is temporary. +static uint rng_seed = 2048; +static bool seeded = false; + +static uint timer = 0; // This might already exist in libtonc but idk so i'm just making my own static int game_speed = 1; static int background = 0; @@ -36,9 +41,14 @@ static Sprite *blind_select_tokens[MAX_BLINDS] = {NULL}; // The sprites that dis static int current_blind = SMALL_BLIND; static enum BlindState blinds[MAX_BLINDS] = {BLIND_CURRENT, BLIND_UPCOMING, BLIND_UPCOMING}; // The current state of the blinds, this is used to determine what the game is doing at any given time -static int hands = 4; -static int discards = 4; +// Red deck default (can later be moved to a deck.h file or something) +static int max_hands = 4; +static int max_discards = 4; +// Set in game_init and game_round_init +static int hands = 0; +static int discards = 0; +static int round = 0; static int ante = 1; static int money = 4; static int score = 0; @@ -109,15 +119,15 @@ static inline Card *discard_pop() return discard_pile[discard_top--]; } - // Consts // Rects left top right bottom // Screenblock rects -static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 21 }; +static const Rect ROUND_END_MENU_RECT = {9, 7, 24, 20 }; -static const Rect POP_MENU_ANIM_RECT_DOWN = {9, 6, 24, 32 }; -static const Rect POP_MENU_ANIM_RECT_UP = {9, 7, 24, 32 }; +static const Rect POP_MENU_ANIM_RECT_DOWN = {9, 6, 24, 30 }; +static const Rect POP_MENU_ANIM_RECT_UP = {9, 7, 24, 31 }; +static const Rect BLIND_SELECT_MENU_CLIP_RECT = {9, 6, 24, 7 }; // The rects for popping menu animations (round end, shop, blinds) // - extends beyond the visible screen to the end of the screenblock // It includes both the target and source position rects. @@ -137,6 +147,7 @@ static const Rect HAND_SIZE_RECT_PLAYING = {128, 152, 152, 160 }; static const Rect HAND_TYPE_RECT = {8, 64, 64, 72 }; // Score displayed in the same place as the hand type static const Rect TEMP_SCORE_RECT = {8, 64, 64, 72 }; +static const Rect SCORE_RECT = {32, 48, 64, 56 }; static const Rect PLAYED_CARDS_SCORES_RECT = {72, 48, 240, 56 }; static const Rect BLIND_TOKEN_TEXT_RECT = {80, 72, 200, 160 }; @@ -144,12 +155,12 @@ static const Rect MONEY_TEXT_RECT = {8, 120, 64, 120 }; static const Rect CHIPS_TEXT_RECT = {8, 80, 32, 88 }; static const Rect MULT_TEXT_RECT = {40, 80, 64, 88 }; static const Rect BLIND_REWARD_RECT = {40, 32, 64, 40 }; +static const Rect BLIND_REQ_TEXT_RECT = {40, 24, 64, 32 }; // Rects with UNDEFINED are only used in tte_printf, they need to be fully defined // to be used with tte_erase_rect_wrapper() static const Rect HANDS_TEXT_RECT = {16, 104, UNDEFINED, UNDEFINED }; static const Rect DISCARDS_TEXT_RECT = {48, 104, UNDEFINED, UNDEFINED }; -static const Rect BLIND_REQ_TEXT_RECT = {40, 24, UNDEFINED, UNDEFINED }; static const Rect DECK_SIZE_RECT = {200, 152, UNDEFINED, UNDEFINED }; static const Rect ROUND_TEXT_RECT = {48, 144, UNDEFINED, UNDEFINED }; static const Rect ANTE_TEXT_RECT = {8, 144, UNDEFINED, UNDEFINED }; @@ -163,6 +174,16 @@ static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEF #define MENU_POP_OUT_ANIM_FRAMES 20 // General functions +void set_seed(int seed) +{ + if (!seeded) + { + seeded = true; + rng_seed = seed; + srand(rng_seed); + } +} + void sort_hand_by_suit() { for (int a = 0; a < hand_top; a++) @@ -390,18 +411,16 @@ void change_background(int id) memcpy16(&se_mem[MAIN_BG_SBB][32 * y_to], &se_mem[MAIN_BG_SBB][32 * y_from], 9); } + Rect rect = {0, 1, 9, 2}; + main_bg_se_copy_rect(rect, 0, 21); // Copy the blind name to the bottom of the screen. This is used for the blind panel animation in game_blind_select() + // 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 - // memset16(&pal_bg_mem[17], blind_get_color(current_blind, BLIND_HIGHLIGHT_COLOR_INDEX), 1); - // memset16(&pal_bg_mem[5], blind_get_color(current_blind, BLIND_MAIN_COLOR_INDEX), 1); - // memset16(&pal_bg_mem[13], blind_get_color(current_blind, BLIND_SHADOW_COLOR_INDEX), 1); + memset16(&pal_bg_mem[17], blind_get_color(current_blind, BLIND_BACKGROUND_MAIN_COLOR_INDEX), 1); + memset16(&pal_bg_mem[16], blind_get_color(current_blind, BLIND_BACKGROUND_SECONDARY_COLOR_INDEX), 1); + memset16(&pal_bg_mem[5], blind_get_color(current_blind, BLIND_BACKGROUND_SHADOW_COLOR_INDEX), 1); } else if (id == BG_ID_CARD_PLAYING) { - // REG_DISPCNT |= DCNT_WIN0; - // memcpy(pal_bg_mem, background_gfxPal, 64); - // GRIT_CPY(&tile8_mem[MAIN_BG_CBB], background_gfxTiles); - // GRIT_CPY(&se_mem[MAIN_BG_SBB], background_gfxMap); - if (background != BG_ID_CARD_SELECTING) { change_background(BG_ID_CARD_SELECTING); @@ -410,30 +429,23 @@ void change_background(int id) 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_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_DOWN, SE_DOWN); } tte_erase_rect_wrapper(HAND_SIZE_RECT_SELECT); } else if (id == BG_ID_ROUND_END) { + if (background != BG_ID_CARD_SELECTING) + { + change_background(BG_ID_CARD_SELECTING); + background = BG_ID_ROUND_END; + } + REG_DISPCNT &= ~DCNT_WIN0; // Disable window 0 so it doesn't make the cashout menu transparent - memcpy(pal_bg_mem, background_round_end_gfxPal, 64); - memcpy(&tile_mem[MAIN_BG_CBB], background_round_end_gfxTiles, background_round_end_gfxTilesLen); - memcpy(&se_mem[MAIN_BG_SBB], background_round_end_gfxMap, background_round_end_gfxMapLen); - - // 1024 0x0400 is when sprites are flipped horizontally, 2048 0x0800 is when they are flipped vertically, 3072 0x0C00 is when they are flipped both horizontally and vertically - // Not sure why this comment is here but note there are bit macros SE_HFLIP and SE_VFLIP for those. - - // 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: 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 tte_erase_rect_wrapper(HAND_SIZE_RECT); - } else if (id == BG_ID_SHOP) { @@ -443,8 +455,8 @@ void change_background(int id) GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_shop_gfxTiles); GRIT_CPY(&se_mem[MAIN_BG_SBB], background_shop_gfxMap); - // Set the outline colors for the shop background - memset16(&pal_bg_mem[27], 0x213D, 1); + // Set the outline colors for the shop background. This is used for the alternate shop palettes when opening packs + memset16(&pal_bg_mem[26], 0x213D, 1); memset16(&pal_bg_mem[6], 0x10B4, 1); memset16(&pal_bg_mem[14], 0x32BE, 1); // Reset the shop lights to correct colors @@ -574,6 +586,13 @@ void set_temp_score(int value) void set_score(int value) { + if (value == 0) // Clear if 0 + { + Rect rect = SCORE_RECT; + rect.left += 1; + tte_erase_rect_wrapper(rect); + } + int x_offset = 32; tte_printf("#{P:%d,48; cx:0xF000}%d", x_offset, value); } @@ -598,6 +617,24 @@ void set_mult(int value) tte_printf("#{P:%d,%d; cx:0xF000;}%d", MULT_TEXT_RECT.left, MULT_TEXT_RECT.top, value); // Mult } +void set_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); +} + +void set_hands(int value) +{ + //tte_erase_rect_wrapper(HANDS_TEXT_RECT); + tte_printf("#{P:%d,%d; cx:0xD000}%d", HANDS_TEXT_RECT.left, HANDS_TEXT_RECT.top, hands); // Hand +} + +void set_discards(int value) +{ + //tte_erase_rect_wrapper(DISCARDS_TEXT_RECT); + tte_printf("#{P:%d,%d; cx:0xE000}%d", DISCARDS_TEXT_RECT.left, DISCARDS_TEXT_RECT.top, discards); // Discard +} + static void print_hand_type(const char* hand_type_str) { if (hand_type_str == NULL) @@ -788,9 +825,13 @@ int deck_get_max_size() void deck_shuffle() { - if (hand_state == HAND_SHUFFLING) return; // Prevent multiple shuffles at the same time - hand_state = HAND_SHUFFLING; - card_focused = 0; + for (int i = deck_top; i > 0; i--) + { + int j = rand() % (i + 1); + Card *temp = deck[i]; + deck[i] = deck[j]; + deck[j] = temp; + } } void increment_blind(enum BlindState increment_reason) @@ -812,6 +853,13 @@ void increment_blind(enum BlindState increment_reason) 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); + + hand_state = HAND_DRAW; + cards_drawn = 0; + hand_selections = 0; + playing_blind_token = blind_token_new(current_blind, 8, 18, 33); // Create the blind token sprite at the top left corner // TODO: Hide blind token and display it after sliding blind rect animation //if (playing_blind_token != NULL) @@ -819,6 +867,7 @@ void game_round_init() // obj_hide(playing_blind_token->obj); // Hide the blind token sprite for now //} round_end_blind_token = blind_token_new(current_blind, 82, 86, 34); // Create the blind token sprite for round end + if (round_end_blind_token != NULL) { obj_hide(round_end_blind_token->obj); // Hide the blind token sprite for now @@ -826,8 +875,8 @@ void game_round_init() tte_printf("#{P:%d,%d; cx:0xE000}%d", BLIND_REQ_TEXT_RECT.left, BLIND_REQ_TEXT_RECT.top, blind_get_requirement(current_blind, ante)); // 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 - // TODO: Add round variable for current round - tte_printf("#{P:%d,%d; cx:0xC000}%d", ROUND_TEXT_RECT.left, ROUND_TEXT_RECT.top, 1); // Round + + deck_shuffle(); // Shuffle the deck at the start of the round } void init_game_state(enum GameState game_state_to_init) @@ -861,6 +910,9 @@ void game_set_state(enum GameState new_game_state) void game_init() { + hands = max_hands; + discards = max_discards; + blind_select_tokens[SMALL_BLIND] = blind_token_new(SMALL_BLIND, 8, 18, 35); blind_select_tokens[BIG_BLIND] = blind_token_new(BIG_BLIND, 8, 18, 36); blind_select_tokens[BOSS_BLIND] = blind_token_new(BOSS_BLIND, 8, 18, 37); @@ -879,27 +931,18 @@ void game_init() } } - // TODO: Move to external function - // Shuffle the deck - for (int i = 0; i < MAX_DECK_SIZE; i++) - { - int j = rand() % MAX_DECK_SIZE; - Card *temp = deck[i]; - deck[i] = deck[j]; - deck[j] = temp; - } - 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 + set_round(round); // Set the round display set_score(score); // Set the score display set_chips(chips); // Set the chips display set_mult(mult); // Set the multiplier display - tte_printf("#{P:%d,%d; cx:0xD000}%d", HANDS_TEXT_RECT.left, HANDS_TEXT_RECT.top, hands); // Hand - tte_printf("#{P:%d,%d; cx:0xE000}%d", DISCARDS_TEXT_RECT.left, DISCARDS_TEXT_RECT.top, discards); // Discard + set_hands(hands); // Hand + set_discards(discards); // Discard //tte_printf("#{P:24,120; cx:0xC000}$%d", money); // Money set_money(money); // Set the money display @@ -1054,7 +1097,6 @@ static void game_playing_discarded_cards_loop() if (discard_top == -1 && discarded_card_object == NULL) // If there are no more discarded cards, stop shuffling { - hand_state = HAND_SELECT; // Reset the hand state to the functional default game_set_state(GAME_ROUND_END); // Set the game state back to playing } } @@ -1540,6 +1582,20 @@ static void game_playing_ui_text_update() } } +static void game_round_end_cashout() +{ + money += hands + blind_get_reward(current_blind); // Reward the player + set_money(money); + + hands = max_hands; // Reset the hands to the maximum + discards = max_discards; // Reset the discards to the maximum + set_hands(hands); // Set the hands display + set_discards(discards); // Set the discards display + + score = 0; + set_score(score); // Set the score display +} + void game_playing() { // TODO: Blind rect sliding into view animation... @@ -1586,16 +1642,9 @@ void game_round_end_cleanup() // TODO: Reuse sprites for blind selection? } -void game_round_end() // Writing this kind a made me want to kms. If somewone wants to rewrite this, please do so. +void game_round_end() { - /* 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 static int blind_reward = 0; static int hand_reward = 0; @@ -1609,7 +1658,6 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa { change_background(BG_ID_ROUND_END); // Change the background to the round end background state = 1; // Change the state to the next one - sequence_step = 0; timer = 0; // Reset the timer blind_reward = blind_get_reward(current_blind); hand_reward = hands; @@ -1618,50 +1666,9 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa } case 1: // This creates the top 16 by 7 tiles of the pop up. It places it in vram, moving it up one tile each frame, not clearing the previous row of tiles so they fill the blank space as it moves up. { - const int bottom_of_screen = 19; - int y = bottom_of_screen - timer; + main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_UP); - // 1st row - const unsigned short tile_map1[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x0026, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0027, 0x0426}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map1, sizeof(tile_map1)); - - // 2nd row - y += 1; - if (y > bottom_of_screen) break; - const unsigned short tile_map2[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x042D, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x002D, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map2, sizeof(tile_map2)); - - // 3rd row - y += 1; - if (y > bottom_of_screen) break; - unsigned short tile_map3[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map3, sizeof(tile_map3)); - - // 4th row - y += 1; - if (y > bottom_of_screen) break; - tile_map3[0] = se_mem[MAIN_BG_SBB][8 + 32 * y]; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map3, sizeof(tile_map3)); - - // 5th row - y += 1; - if (y > bottom_of_screen) break; - tile_map3[0] = se_mem[MAIN_BG_SBB][8 + 32 * y]; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map3, sizeof(tile_map3)); - - // 6th row - y += 1; - if (y > bottom_of_screen) break; - const unsigned short tile_map4[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x0055, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0455, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map4, sizeof(tile_map4)); - - // 7th row - y += 1; - if (y > bottom_of_screen) break; - const unsigned short tile_map5[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map5, sizeof(tile_map5)); - - if (timer >= 12) + if (timer == 13) { state = 2; timer = 0; @@ -1674,13 +1681,13 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa tte_printf("#{P:%d,%d; cx:0xE000}%d", ROUND_END_BLIND_REQ_RECT.left, ROUND_END_BLIND_REQ_RECT.top, blind_get_requirement(current_blind, ante)); - int y = 13; - - const unsigned short tile_map1[17] = {se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x002A, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], tile_map1, sizeof(tile_map1)); - - const unsigned short tile_map2[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x0055, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0455, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map2, sizeof(tile_map2)); + if (timer == 1) + { + Rect single_line_rect = ROUND_END_MENU_RECT; + single_line_rect.top = 11; + single_line_rect.bottom = single_line_rect.top + 1; + main_bg_se_copy_rect_1_tile_vert(single_line_rect, SE_DOWN); + } if (timer >= 30) { @@ -1691,11 +1698,15 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa } case 3: // Sequentially display the "score min" text over the next 4 frames { - // "Score Min" text - const unsigned short tile_map3[4] = {0x003E, 0x003F, 0x0040, 0x0041}; + int timer_offset = timer - 1; - int temp_offset = timer; - memcpy(&se_mem[MAIN_BG_SBB][12 + temp_offset + 32 * 11], &tile_map3[temp_offset - 1], sizeof(tile_map3[0])); + int x_from = 0; + int y_from = 29; + + int x_to = 13; + int y_to = 11; + + memcpy16(&se_mem[MAIN_BG_SBB][x_to + timer_offset + 32 * y_to], &se_mem[MAIN_BG_SBB][x_from + timer_offset + 32 * y_from], 1); if (timer >= 4) { @@ -1710,121 +1721,56 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa // TODO: Add sound effect here - sequence_step++; - - 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_REQ_RECT.top, blind_get_reward(current_blind) - blind_reward); - - if (blind_reward <= 0) + 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_REQ_RECT.top, blind_get_reward(current_blind) - blind_reward); + } + else if (timer > FRAMES(20)) { tte_erase_rect_wrapper(BLIND_REWARD_RECT); + tte_erase_rect_wrapper(BLIND_REQ_TEXT_RECT); obj_hide(playing_blind_token->obj); state = 5; - sequence_step = 0; timer = 0; } break; } - case 5: // This is just an incredibly convoluted way to slide the "small blind" panel out of view. It was made this way because I didn't know the better way at the time AND because I was being a perfectionist and wanted to make the bottom row of tiles on the panel not connected to the "SCORE" panel. + case 5: // Slide the "small blind" panel out of view { - if (timer < FRAMES(20)) break; - - sequence_step++; + if (timer < 8) { - int y = 5; + main_bg_se_copy_rect_1_tile_vert(SHOP_ICON_RECT, SE_UP); - if (sequence_step == 1) // Erase the score text from the small blind panel and move it all up by one tile + if (timer == 1) // Copied from shop. Feels slightly too niche of a function for me personally to make one. { - tte_erase_rect(40, 16, 64, 40); - - const unsigned short tile_map1[10] = {0x0064, 0x0065, 0x0065, 0x0066, 0x0067, 0x0067, 0x0067, 0x0068, 0x0464, se_mem[MAIN_BG_SBB][32 * y + 9]}; // Swaps the top of the score panel tiles with ones that aren't connected to the small blind panel - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map1, sizeof(tile_map1)); - - y -= 1; - const unsigned short tile_map2[10] = {0x006F, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x0070, 0x046F, se_mem[MAIN_BG_SBB][32 * y + 9]}; // Swaps the bottom of the small blind panel tiles with ones that aren't connected to the score panel - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map2, sizeof(tile_map2)); - - // These just move everything else up by one tile - y = 1; - const unsigned short tile_map3[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map3, sizeof(tile_map3)); - - y = 2; - const unsigned short tile_map4[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map4, sizeof(tile_map4)); - - y = 3; - const unsigned short tile_map5[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map5, sizeof(tile_map5)); + int y = 6; + memset16(&se_mem[MAIN_BG_SBB][32 * (y - 1)], 0x0006, 1); + memset16(&se_mem[MAIN_BG_SBB][1 + 32 * (y - 1)], 0x0007, 2); + memset16(&se_mem[MAIN_BG_SBB][3 + 32 * (y - 1)], 0x0008, 1); + memset16(&se_mem[MAIN_BG_SBB][4 + 32 * (y - 1)], 0x0009, 4); + memset16(&se_mem[MAIN_BG_SBB][7 + 32 * (y - 1)], 0x000A, 1); + memset16(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x0406, 1); } - else if (sequence_step == 2) + else if (timer == 2) { - - y = 1; - const unsigned short tile_map3[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map3, sizeof(tile_map3)); - - y = 2; - const unsigned short tile_map4[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map4, sizeof(tile_map4)); - - y = 3; - const unsigned short tile_map5[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map5, sizeof(tile_map5)); - - y = 4; - const unsigned short tile_map6[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map6, sizeof(tile_map6)); - - y = 4; - const unsigned short tile_map2[10] = {0x046B, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x006B, se_mem[MAIN_BG_SBB][32 * y + 9]}; // This sets the uncleared bottom row of the small blind panel to empty tiles that match the stats panel - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map2, sizeof(tile_map2)); + int y = 5; + memset16(&se_mem[MAIN_BG_SBB][32 * (y - 1)], 0x0001, 1); + memset16(&se_mem[MAIN_BG_SBB][1 + 32 * (y - 1)], 0x0002, 7); + memset16(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x0401, 1); } - else // The rest of this just moves the panel tiles up in vram until they're gone - { - y = 1; - const unsigned short tile_map3[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map3, sizeof(tile_map3)); - - y = 2; - const unsigned short tile_map4[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map4, sizeof(tile_map4)); - - y = 3; - const unsigned short tile_map5[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map5, sizeof(tile_map5)); - - y = 4; - const unsigned short tile_map6[10] = {se_mem[MAIN_BG_SBB][32 * y], se_mem[MAIN_BG_SBB][32 * y + 1], se_mem[MAIN_BG_SBB][32 * y + 2], se_mem[MAIN_BG_SBB][32 * y + 3], se_mem[MAIN_BG_SBB][32 * y + 4], se_mem[MAIN_BG_SBB][32 * y + 5], se_mem[MAIN_BG_SBB][32 * y + 6], se_mem[MAIN_BG_SBB][32 * y + 7], se_mem[MAIN_BG_SBB][32 * y + 8], se_mem[MAIN_BG_SBB][32 * (y - 1) + 9]}; - y -= 1; - memcpy(&se_mem[MAIN_BG_SBB][32 * y], &tile_map6, sizeof(tile_map6)); - } - } - - if (sequence_step == 6) + } + else if (timer > FRAMES(20)) { memset16(&pal_bg_mem[18], 0x1483, 1); state = 6; timer = 0; - sequence_step = 0; } break; } case 6: // This state handles displaying the rewards earned from the completed round { - if (timer < FRAMES(20)) break; - int hand_y = 0; int interest_y = 0; @@ -1839,39 +1785,33 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa // interest_y = 1 + hand_y; // } - if (sequence_step == 0) // Expand the black part of the panel down by one tile + if (timer == 1) // Expand the black part of the panel down by one tile { - int y = 14; - - const unsigned short tile_map1[17] = {se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x002A, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], tile_map1, sizeof(tile_map1)); - - const unsigned short tile_map2[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x0055, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0455, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map2, sizeof(tile_map2)); + Rect single_line_rect = ROUND_END_MENU_RECT; + single_line_rect.top = 12; + single_line_rect.bottom = single_line_rect.top + 1; + main_bg_se_copy_rect_1_tile_vert(single_line_rect, SE_DOWN); } - else if (sequence_step < 15) // Use TTE to print '.' until the end of the panel width + else if (timer < 16) // Use TTE to print '.' until the end of the panel width { // Print the separator dots - int x = (9 + sequence_step) * 8; + int x = (8 + timer) * 8; int y = (13) * 8; tte_printf("#{P:%d,%d; cx:0xF000}.", x, y); } - else if (sequence_step >= 30 && hand_reward > 0) // Wait an additional 15 frames since the last sequenced action + else if (timer >= 30 && hand_reward > 0) // Wait an additional 15 frames since the last sequenced action { - if (sequence_step == 30) // Expand the black part of the panel down by one tile again + if (timer == 30) // Expand the black part of the panel down by one tile again { - int y = 14 + hand_y; // This was intended for modularity so that I can add interest rewards later - - const unsigned short tile_map1[17] = {se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x002A, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], tile_map1, sizeof(tile_map1)); - - const unsigned short tile_map2[17] = {se_mem[MAIN_BG_SBB][8 + 32 * y], 0x002A, 0x0055, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0056, 0x0455, 0x042A}; - memcpy(&se_mem[MAIN_BG_SBB][8 + 32 * y], tile_map2, sizeof(tile_map2)); + Rect single_line_rect = ROUND_END_MENU_RECT; + single_line_rect.top = 12 + hand_y; + 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 } - else if (sequence_step > 45 && timer % FRAMES(20) == 0) // After 15 frames, every 20 frames, increment the hand reward text until the hand reward variable is depleted + 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) * 8; hand_reward--; @@ -1879,11 +1819,8 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa } } - sequence_step++; - if (hand_reward <= 0 && interest_reward <= 0) // Once all rewards are accounted for go to the next state { - sequence_step = 0; timer = 0; // Reset the timer state = 7; // Go to the next state } @@ -1894,31 +1831,31 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa { if (timer == FRAMES(40)) // Put the "cash out" button onto the round end panel { - int y = 8; + Rect left_rect = {4, 29, 5, 33}; + main_bg_se_copy_rect(left_rect, 10, 8); - // 1st row - const unsigned short tile_map1[14] = {0x002B, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x002C, 0x042B}; - memcpy(&se_mem[MAIN_BG_SBB][10 + 32 * y], tile_map1, sizeof(tile_map1)); + Rect right = {7, 29, 8, 33}; + main_bg_se_copy_rect(right, 23, 8); - // 2nd row - y += 1; - const unsigned short tile_map2[14] = {0x0030, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0031, 0x0430}; - memcpy(&se_mem[MAIN_BG_SBB][10 + 32 * y], tile_map2, sizeof(tile_map2)); + Rect top = {11, 8, 23, 9}; + main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(6, 29), top); - // 3rd row - y += 1; - unsigned short tile_map3[14] = {0x0037, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0038, 0x0437}; - memcpy(&se_mem[MAIN_BG_SBB][10 + 32 * y], tile_map3, sizeof(tile_map3)); + Rect middle = {11, 9, 23, 10}; + main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(6, 30), middle); + + Rect bottom = {11, 10, 23, 11}; + main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(6, 31), bottom); 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 } else if (timer > FRAMES(40) && key_hit(KEY_A)) // Wait until the player presses A to cash out - { - state = 8; // Go to the next state - money += hands + blind_get_reward(current_blind); // Reward the player - set_money(money); - memset16(&pal_bg_mem[6], 0x0174, 1); + { + game_round_end_cashout(); + state = 8; // Go to the next state + timer = 0; // Reset the timer + + memset16(&pal_bg_mem[6], 0x0174, 1); obj_hide(round_end_blind_token->obj); // Hide the blind token object tte_erase_rect_wrapper(BLIND_TOKEN_TEXT_RECT); // Erase the blind token text } @@ -1927,19 +1864,17 @@ 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 { - sequence_step++; main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_DOWN, SE_DOWN); - if (sequence_step >= 20) + if (timer >= 20) { - sequence_step = 0; timer = 0; state = 9; } break; } default: - sequence_step = 0; + timer = 0; state = 0; blind_reward = 0; hand_reward = 0; @@ -1967,7 +1902,7 @@ void game_shop() if (timer % 20 == 0) // Shift palette around the border of the shop icon { - unsigned short shifted_palette[4]; + COLOR shifted_palette[4]; memcpy16(&shifted_palette[0], &pal_bg_mem[14], 1); memcpy16(&shifted_palette[1], &pal_bg_mem[17], 1); memcpy16(&shifted_palette[2], &pal_bg_mem[22], 1); @@ -1998,12 +1933,12 @@ void game_shop() { 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; int y_to = 0 + y; - memcpy16(&se_mem[MAIN_BG_SBB][32 * y_to], &se_mem[MAIN_BG_SBB][32 * y_from], 9); + Rect from = {0, y_from, 9, y_from + 1}; + main_bg_se_copy_rect(from, 0, y_to); } } @@ -2136,8 +2071,6 @@ void game_shop() void game_blind_select() { - change_background(BG_ID_BLIND_SELECT); - static int state = 0; static bool top_row = true; // There's only one row in this game state, but this is here for consistency with the shop state if we make these variables global or something @@ -2146,6 +2079,7 @@ void game_blind_select() { case 0: // Intro sequence (menu coming into frame) { + change_background(BG_ID_BLIND_SELECT); main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_UP); for (int i = 0; i < MAX_BLINDS; i++) @@ -2155,7 +2089,7 @@ void game_blind_select() if (timer == 12) { - state = 1; + state++; timer = 0; // Reset the timer } @@ -2174,10 +2108,11 @@ void game_blind_select() } else if (key_hit(KEY_A)) { - if (top_row) + if (top_row) // Blind selected { - state = 2; + state++; timer = 0; + set_round(++round); } else if (current_blind != BOSS_BLIND) { @@ -2186,7 +2121,7 @@ void game_blind_select() background = -1; // Force refresh of the background change_background(BG_ID_BLIND_SELECT); - for (int i = 0; i < 12; i++) + for (int i = 0; i < 12; i++) // This shouldn't be direct accessing vram to do this because it causes flickering. Ideally, in the future, we should use a buffer and then copy it to VRAM in one go. { main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_UP, SE_UP); } @@ -2219,25 +2154,73 @@ void game_blind_select() { main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT_DOWN, SE_DOWN); + main_bg_se_clear_rect(BLIND_SELECT_MENU_CLIP_RECT); + 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); } } - // TODO: Currently selecting other blinds crashes, remove this condition once fixed - else if (current_blind == SMALL_BLIND && timer >= MENU_POP_OUT_ANIM_FRAMES) + else if (timer >= MENU_POP_OUT_ANIM_FRAMES) { for (int i = 0; i < MAX_BLINDS; i++) { obj_hide(blind_select_tokens[i]->obj); } - game_set_state(GAME_PLAYING); - state = 0; // Reset the state + state++; // Reset the state + timer = 0; // Reset the timer } break; } + case 3: // Move the blind panel into view + { + if (timer < 7) + { + if (timer == 1) // Switches to the selecting background and clears the blind panel area + { + change_background(BG_ID_CARD_SELECTING); + + main_bg_se_clear_rect(POP_MENU_ANIM_RECT_DOWN); + + for (int y = 0; y < 5; y++) + { + int y_from = 28; + int y_to = 0 + y; + Rect from = {0, y_from, 9, y_from + 1}; + main_bg_se_copy_rect(from, 0, y_to); + } + + int y = 6; + memset16(&se_mem[MAIN_BG_SBB][32 * (y - 1)], 0x0006, 1); + memset16(&se_mem[MAIN_BG_SBB][1 + 32 * (y - 1)], 0x0007, 2); + memset16(&se_mem[MAIN_BG_SBB][3 + 32 * (y - 1)], 0x0008, 1); + memset16(&se_mem[MAIN_BG_SBB][4 + 32 * (y - 1)], 0x0009, 4); + memset16(&se_mem[MAIN_BG_SBB][7 + 32 * (y - 1)], 0x000A, 1); + memset16(&se_mem[MAIN_BG_SBB][8 + 32 * (y - 1)], 0x0406, 1); + } + + for (int y = 0; y < timer; y++) // Shift the blind panel down onto screen + { + int y_from = 26 + y - timer; + int y_to = 0 + y; + Rect from = {0, y_from, 9, y_from + 1}; + main_bg_se_copy_rect(from, 0, y_to); + } + } + else + { + state++; + } + + break; + } default: + state = 0; + timer = 0; + top_row = true; + background = -1; + game_set_state(GAME_PLAYING); break; } } @@ -2246,6 +2229,15 @@ void game_update() { timer++; + if (seeded == false) + { + rng_seed++; + if (key_curr_state() != key_prev_state()) // If the keys have changed, make it more pseudo-random + { + rng_seed *= 2; + } + } + switch (game_state) { case GAME_PLAYING: diff --git a/source/graphic_utils.c b/source/graphic_utils.c index 79cf708..8e87dcf 100644 --- a/source/graphic_utils.c +++ b/source/graphic_utils.c @@ -23,6 +23,10 @@ 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(int x, int y) +{ + return se_mem[MAIN_BG_SBB][x + SE_ROW_LEN * y]; +} void main_bg_se_clear_rect(Rect se_rect) { @@ -58,10 +62,46 @@ void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction) &se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y], se_rect.right - se_rect.left + 1); } +} - if (direction == SE_DOWN) +void main_bg_se_copy_rect(Rect se_rect, int x, int y) +{ + if (se_rect.left > se_rect.right || se_rect.top > se_rect.bottom) + return; + + // Clip to avoid screenblock overflow + clip_se_rect_to_screenblock(&se_rect); + + u16 tile_map[se_rect.bottom - se_rect.top][se_rect.right - se_rect.left]; + + // Copy the rect to the tile map + for (int sy = 0; sy < se_rect.bottom - se_rect.top; sy++) { - 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. + for (int sx = 0; sx < se_rect.right - se_rect.left; sx++) + { + tile_map[sy][sx] = main_bg_se_get_tile(se_rect.left + sx, se_rect.top + sy); + } + } + + for (int sy = 0; sy < se_rect.bottom - se_rect.top; sy++) + { + memcpy16(&se_mem[MAIN_BG_SBB][x + SE_ROW_LEN * (y + sy)], + &tile_map[sy][0], + se_rect.right - se_rect.left); + } +} + +void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect) +{ + if (se_rect.left > se_rect.right || se_rect.top > se_rect.bottom) + return; + + // Clip to avoid screenblock overflow + clip_se_rect_to_screenblock(&se_rect); + + for (int sy = 0; sy < se_rect.bottom - se_rect.top; sy++) + { + memset16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (se_rect.top + sy)], tile, se_rect.right - se_rect.left); } }