From 835e44e4db1bf283e7520a3cf1279f2826af0f51 Mon Sep 17 00:00:00 2001 From: Rickey Date: Sun, 29 Mar 2026 14:32:21 -0700 Subject: [PATCH] Introduce the game variables struct (#338) Co-authored-by: emiyl * Introduce the game variables struct * Fix clang format * Move game variables into their own file --- include/game.h | 10 ++++-- include/game_variables.h | 20 +++++++++++ include/splash_screen.h | 8 +++-- source/game.c | 74 +++++++++++++++++++++------------------- source/splash_screen.c | 6 ++-- 5 files changed, 73 insertions(+), 45 deletions(-) create mode 100644 include/game_variables.h diff --git a/include/game.h b/include/game.h index f9ff549..87ae121 100644 --- a/include/game.h +++ b/include/game.h @@ -1,6 +1,8 @@ #ifndef GAME_H #define GAME_H +#include "game_variables.h" + #include #define MAX_HAND_SIZE 16 @@ -129,12 +131,14 @@ typedef struct ContainedHandTypes } ContainedHandTypes; // clang-format on +typedef void (*GameStateCallback)(GameVariables* gs); + typedef struct { int substate; - void (*on_init)(); - void (*on_update)(); - void (*on_exit)(); + GameStateCallback on_init; + GameStateCallback on_update; + GameStateCallback on_exit; } StateInfo; // Game functions diff --git a/include/game_variables.h b/include/game_variables.h new file mode 100644 index 0000000..d82dc36 --- /dev/null +++ b/include/game_variables.h @@ -0,0 +1,20 @@ +/** + * @file game_variables.h + * + * @brief Game global game variables struct definition + */ +#ifndef GAME_VARIABLES_H +#define GAME_VARIABLES_H + +/** + * @brief A central location for all game variables. + * + * **NOTE**: This is currently WIP and will be populated with a refactor effort. + * NOT ALL VARIABLES ARE LOCATED HERE YET + */ +typedef struct +{ + +} GameVariables; + +#endif // GAME_VARIABLES_H diff --git a/include/splash_screen.h b/include/splash_screen.h index 579d8d6..c1b8755 100644 --- a/include/splash_screen.h +++ b/include/splash_screen.h @@ -7,6 +7,8 @@ #ifndef SPLASH_SCREEN_H #define SPLASH_SCREEN_H +#include "game.h" + #include /** @name Splash screen timing variables @@ -23,16 +25,16 @@ /** * @brief Initialize the splash screen by printing the splash screen text. */ -void splash_screen_on_init(void); +void splash_screen_on_init(GameVariables* vars); /** * @brief Update splash screen timers and print the remaining time accordingly. */ -void splash_screen_on_update(void); +void splash_screen_on_update(GameVariables* vars); /** * @brief Exit the splash screen */ -void splash_screen_on_exit(void); +void splash_screen_on_exit(GameVariables* vars); #endif // SPLASH_SCREEN_H diff --git a/source/game.c b/source/game.c index 5a9981a..e56e0b2 100644 --- a/source/game.c +++ b/source/game.c @@ -189,7 +189,7 @@ typedef struct // efficient. Well, this is the answer. // Thanks! // https://github.com/cellos51/balatro-gba/issues/137#issuecomment-3322485129 -static void noop(void) +static void noop(GameVariables* vars) { } @@ -199,22 +199,22 @@ static void noop(void) // This could be done, and maybe should be done, // with an X macro, but I'll leave that to the // reviewer(s). -static void game_main_menu_on_init(void); -static void game_main_menu_on_update(void); -static void game_round_on_init(void); -static void game_playing_on_update(void); -static void game_round_end_on_update(void); -static void game_round_end_on_exit(void); -static void game_shop_on_update(void); -static void game_shop_on_exit(void); -static void game_blind_select_on_init(void); -static void game_blind_select_on_update(void); -static void game_blind_select_on_exit(void); -static void game_lose_on_init(void); -static void game_lose_on_update(void); -static void game_over_on_exit(void); -static void game_win_on_init(void); -static void game_win_on_update(void); +static void game_main_menu_on_init(GameVariables* vars); +static void game_main_menu_on_update(GameVariables* vars); +static void game_round_on_init(GameVariables* vars); +static void game_playing_on_update(GameVariables* vars); +static void game_round_end_on_update(GameVariables* vars); +static void game_round_end_on_exit(GameVariables* vars); +static void game_shop_on_update(GameVariables* vars); +static void game_shop_on_exit(GameVariables* vars); +static void game_blind_select_on_init(GameVariables* vars); +static void game_blind_select_on_update(GameVariables* vars); +static void game_blind_select_on_exit(GameVariables* vars); +static void game_lose_on_init(GameVariables* vars); +static void game_lose_on_update(GameVariables* vars); +static void game_over_on_exit(GameVariables* vars); +static void game_win_on_init(GameVariables* vars); +static void game_win_on_update(GameVariables* vars); static void game_shop_intro(void); static void game_shop_process_user_input(void); static void game_shop_outro(void); @@ -650,6 +650,8 @@ static int shortcut_joker_count = 0; static int four_fingers_joker_count = 0; +static GameVariables game_vars; + GBAL_UNUSED static inline bool is_shop_joker_avail(int joker_id) { @@ -872,7 +874,7 @@ void game_update() jokers_update_loop(); - state_info[game_state].on_update(); + state_info[game_state].on_update(&game_vars); } void game_change_state(enum GameState new_game_state) @@ -882,12 +884,12 @@ void game_change_state(enum GameState new_game_state) if (game_state >= 0 && game_state < GAME_STATE_MAX) { state_info[game_state].substate = 0; - state_info[game_state].on_exit(); + state_info[game_state].on_exit(&game_vars); } if (new_game_state >= 0 && new_game_state < GAME_STATE_MAX) { - state_info[new_game_state].on_init(); + state_info[new_game_state].on_init(&game_vars); game_state = new_game_state; } @@ -1912,7 +1914,7 @@ static inline void deck_shuffle(void) } } -static void game_round_on_init() +static void game_round_on_init(GameVariables* vars) { hand_state = HAND_DRAW; cards_drawn = 0; @@ -1979,7 +1981,7 @@ static void game_round_on_init() game_playing_selection_grid.selection = GAME_PLAYING_INIT_SEL; } -static void game_main_menu_on_init() +static void game_main_menu_on_init(GameVariables* vars) { affine_background_change_background(AFFINE_BG_MAIN_MENU); change_background(BG_MAIN_MENU); @@ -2002,14 +2004,14 @@ static void game_over_init(void) main_bg_se_copy_rect(NEW_RUN_BTN_SRC_RECT, NEW_RUN_BTN_DEST_POS); } -static void game_lose_on_init() +static void game_lose_on_init(GameVariables* vars) { game_over_init(); // Using the text color to match the "Game Over" text affine_background_set_color(TEXT_CLR_RED); } -static void game_win_on_init() +static void game_win_on_init(GameVariables* vars) { game_over_init(); // Using the text color to match the "You Win" text @@ -3483,7 +3485,7 @@ static inline void game_playing_process_flaming_score(void) } } -static void game_playing_on_update(void) +static void game_playing_on_update(GameVariables* vars) { // 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) @@ -3522,7 +3524,7 @@ static int calculate_interest_reward(void) return reward; } -static void game_round_end_on_exit() +static void game_round_end_on_exit(GameVariables* vars) { // Cleanup blind tokens from this round to avoid accumulating // allocated blind sprites each round @@ -3534,7 +3536,7 @@ static void game_round_end_on_exit() // TODO: Reuse sprites for blind selection? } -static void game_round_end_on_update() +static void game_round_end_on_update(GameVariables* vars) { if (state_info[game_state].substate == ROUND_END_EXIT) { @@ -4470,7 +4472,7 @@ static inline void game_shop_lights_anim_frame(void) memcpy16(&pal_bg_mem[SHOP_LIGHTS_1_PID], &shifted_palette[3], 1); } -static void game_shop_on_update() +static void game_shop_on_update(GameVariables* vars) { change_background(BG_SHOP); @@ -4503,7 +4505,7 @@ static void game_shop_on_update() shop_state_actions[substate](); } -static void game_shop_on_exit() +static void game_shop_on_exit(GameVariables* vars) { ListItr itr = list_itr_create(&_shop_jokers_list); JokerObject* joker_object; @@ -4523,7 +4525,7 @@ static void game_shop_on_exit() increment_blind(BLIND_STATE_DEFEATED); // TODO: Move to game_round_end()? } -static void game_blind_select_on_init() +static void game_blind_select_on_init(GameVariables* vars) { change_background(BG_BLIND_SELECT); selection_x = 0; @@ -4532,7 +4534,7 @@ static void game_blind_select_on_init() play_sfx(SFX_POP, MM_BASE_PITCH_RATE, SFX_DEFAULT_VOLUME); } -static void game_blind_select_on_update() +static void game_blind_select_on_update(GameVariables* vars) { if (state_info[game_state].substate == BLIND_SELECT_MAX) { @@ -4802,7 +4804,7 @@ static void game_blind_select_display_blind_panel() } } -static void game_blind_select_on_exit() +static void game_blind_select_on_exit(GameVariables* vars) { selection_y = 0; background = UNDEFINED; @@ -4871,7 +4873,7 @@ static inline void game_start(void) game_change_state(GAME_STATE_BLIND_SELECT); } -static void game_main_menu_on_update() +static void game_main_menu_on_update(GameVariables* vars) { change_background(BG_MAIN_MENU); @@ -4936,7 +4938,7 @@ static inline void game_over_process_user_input() } } -static void game_lose_on_update() +static void game_lose_on_update(GameVariables* vars) { if (timer < GAME_OVER_ANIM_FRAMES) { @@ -4958,7 +4960,7 @@ static void game_lose_on_update() // This function isn't set in stone. This is just a placeholder // allowing the player to restart the game. Thought it would be nice to have // util we decide what we want to do after a game over. -static void game_over_on_exit() +static void game_over_on_exit(GameVariables* vars) { while (list_get_len(&_owned_jokers_list) > 0) { @@ -5006,7 +5008,7 @@ static void game_over_on_exit() affine_background_load_palette(affine_background_gfxPal); } -static void game_win_on_update() +static void game_win_on_update(GameVariables* vars) { if (timer < GAME_OVER_ANIM_FRAMES) { diff --git a/source/splash_screen.c b/source/splash_screen.c index 358a05d..11a34a5 100644 --- a/source/splash_screen.c +++ b/source/splash_screen.c @@ -11,7 +11,7 @@ static const Rect COUNTDOWN_TIMER_RECT = {208, 144, 240, 152}; static uint timer = 0; -void splash_screen_on_init() +void splash_screen_on_init(GameVariables* vars) { timer = 0; @@ -25,7 +25,7 @@ void splash_screen_on_init() tte_printf("#{P:8,144; cx:0xF000}(Press any key to skip)"); } -void splash_screen_on_update() +void splash_screen_on_update(GameVariables* vars) { timer++; @@ -49,7 +49,7 @@ void splash_screen_on_update() tte_erase_screen(); } -void splash_screen_on_exit() +void splash_screen_on_exit(GameVariables* vars) { mmStart(MOD_MAIN_THEME, MM_PLAY_LOOP); }