GBAlatro
A Demake of Balatro for the GBA
Loading...
Searching...
No Matches
run_setup.c
Go to the documentation of this file.
1
7#include "game/run_setup.h"
8
9#include "background_run_setup_gfx.h"
10#include "button.h"
11#include "card.h"
12#include "game.h"
13#include "game_variables.h"
14#include "graphic_utils.h"
15#include "save.h"
16#include "selection_grid.h"
17#include "sprite.h"
18#include "state_machine.h"
19#include "util.h"
20
21#include <string.h>
22#include <tonc.h>
23
24// Palette Indices
25
26#define CHANGE_DECK_BTN_MAIN_COLOR_PAL_IDX 1
27#define RED_BTN_MAIN_COLOR_PAL_IDX 10
28#define RED_DISABLED_BTN_MAIN_COLOR_PAL_IDX 11
29#define BLUE_BTN_MAIN_COLOR_PAL_IDX 12
30#define BLUE_DISABLED_BTN_MAIN_COLOR_PAL_IDX 13
31#define BACK_BTN_MAIN_COLOR_PAL_IDX 14
32
33#define NEW_RUN_BTN_OUTLINE_COLOR_PAL_IDX 30
34#define RESUME_BTN_OUTLINE_COLOR_PAL_IDX 31
35#define CHANGE_DECK_BTN_OUTLINE_COLOR_PAL_IDX 32
36#define SEED_CHECK_BTN_OUTLINE_COLOR_PAL_IDX 33
37#define SEED_DECK_BTN_OUTLINE_COLOR_PAL_IDX 34
38#define PLAY_BTN_OUTLINE_COLOR_PAL_IDX 35
39#define BACK_BTN_OUTLINE_COLOR_PAL_IDX 36
40
41#define KEYBOARD_1_BTN_OUTLINE_COLOR_PAL_IDX 40
42#define KEYBOARD_2_BTN_OUTLINE_COLOR_PAL_IDX 41
43#define KEYBOARD_3_BTN_OUTLINE_COLOR_PAL_IDX 42
44#define KEYBOARD_4_BTN_OUTLINE_COLOR_PAL_IDX 43
45#define KEYBOARD_5_BTN_OUTLINE_COLOR_PAL_IDX 44
46#define KEYBOARD_6_BTN_OUTLINE_COLOR_PAL_IDX 45
47#define KEYBOARD_7_BTN_OUTLINE_COLOR_PAL_IDX 46
48#define KEYBOARD_8_BTN_OUTLINE_COLOR_PAL_IDX 47
49#define KEYBOARD_9_BTN_OUTLINE_COLOR_PAL_IDX 48
50#define KEYBOARD_0_BTN_OUTLINE_COLOR_PAL_IDX 49
51
52#define KEYBOARD_A_BTN_OUTLINE_COLOR_PAL_IDX 50
53#define KEYBOARD_B_BTN_OUTLINE_COLOR_PAL_IDX 51
54#define KEYBOARD_C_BTN_OUTLINE_COLOR_PAL_IDX 52
55#define KEYBOARD_D_BTN_OUTLINE_COLOR_PAL_IDX 53
56#define KEYBOARD_E_BTN_OUTLINE_COLOR_PAL_IDX 54
57#define KEYBOARD_F_BTN_OUTLINE_COLOR_PAL_IDX 55
58#define KEYBOARD_G_BTN_OUTLINE_COLOR_PAL_IDX 56
59#define KEYBOARD_H_BTN_OUTLINE_COLOR_PAL_IDX 57
60#define KEYBOARD_I_BTN_OUTLINE_COLOR_PAL_IDX 58
61#define KEYBOARD_J_BTN_OUTLINE_COLOR_PAL_IDX 59
62
63#define KEYBOARD_K_BTN_OUTLINE_COLOR_PAL_IDX 60
64#define KEYBOARD_L_BTN_OUTLINE_COLOR_PAL_IDX 61
65#define KEYBOARD_M_BTN_OUTLINE_COLOR_PAL_IDX 62
66#define KEYBOARD_N_BTN_OUTLINE_COLOR_PAL_IDX 63
67#define KEYBOARD_O_BTN_OUTLINE_COLOR_PAL_IDX 64
68#define KEYBOARD_P_BTN_OUTLINE_COLOR_PAL_IDX 65
69#define KEYBOARD_Q_BTN_OUTLINE_COLOR_PAL_IDX 66
70#define KEYBOARD_R_BTN_OUTLINE_COLOR_PAL_IDX 67
71#define KEYBOARD_S_BTN_OUTLINE_COLOR_PAL_IDX 68
72#define KEYBOARD_T_BTN_OUTLINE_COLOR_PAL_IDX 69
73
74#define KEYBOARD_RAND_BTN_OUTLINE_COLOR_PAL_IDX 70
75#define KEYBOARD_U_BTN_OUTLINE_COLOR_PAL_IDX 71
76#define KEYBOARD_V_BTN_OUTLINE_COLOR_PAL_IDX 72
77#define KEYBOARD_W_BTN_OUTLINE_COLOR_PAL_IDX 73
78#define KEYBOARD_X_BTN_OUTLINE_COLOR_PAL_IDX 74
79#define KEYBOARD_Y_BTN_OUTLINE_COLOR_PAL_IDX 75
80#define KEYBOARD_Z_BTN_OUTLINE_COLOR_PAL_IDX 76
81#define KEYBOARD_DEL_BTN_OUTLINE_COLOR_PAL_IDX 77
82
83enum RunSetupSubstate
84{
85 RUN_SETUP_SUBSTATE_CHOOSE_DECK,
86 RUN_SETUP_SUBSTATE_CHOOSE_SEED,
87 RUN_SETUP_SUBSTATE_RESUME,
88 RUN_SETUP_SUBSTATE_MAX
89};
90
91static void choose_deck_substate_init(void);
92static void choose_deck_substate_update(void);
93
94static void seed_keyboard_substate_init(void);
95static void seed_keyboard_substate_update(void);
96
97static void resume_substate_init(void);
98
99static StateInfo state_info[] = {
100 STATE_INFO_INIT_UPDATE_FN(choose_deck_substate_init, choose_deck_substate_update),
102 STATE_INFO_INIT_UPDATE_FN(resume_substate_init, noop)
103};
104
105static StateMachine run_setup_sm = {
106 .state_infos = &state_info[0],
107 .num_infos = RUN_SETUP_SUBSTATE_MAX,
108};
109
110#pragma region LAYOUT
111/*******************************************************************************
112 * TILES LAYOUT
113 ******************************************************************************/
114
115// clang-format off
116// Uncomment when tab row is re-added
117//static const Rect RUN_SETUP_RESUME_TAB_DISABLED_SRC = {19, 22, 23, 23};
118//static const BG_POINT RUN_SETUP_RESUME_TAB_DISABLED_DEST_POS = {15, 1};
119
120static const BG_POINT RUN_SETUP_FRAME_BG_SE_FILL_SRC_POS = {9 , 31};
121
122static const Rect RUN_SETUP_CHOOSE_DECK_CHOICE_BG_9_PTCH_DEST = {6 , 4 , 23, 13};
123static const NinePatchRect RUN_SETUP_CHOOSE_DECK_CHOICE_BG_9_PTCH_SRC = {
124 { 0 , 21, 7 , 28},
125 { 5 , 3 , 2 , 4 }
126};
127
128static const Rect RUN_SETUP_CHOOSE_DECK_CLEAN_LEFT_DEST = {4 , 6 , 5 , 13};
129static const Rect RUN_SETUP_CHOOSE_DECK_CLEAN_RIGHT_DEST = {24, 6 ,25 , 13};
130
131static const Rect RUN_SETUP_CHOOSE_DECK_USE_SEED_BTN_OFF_SRC = {30, 8 , 31, 10};
132static const Rect RUN_SETUP_CHOOSE_DECK_USE_SEED_BTN_ON_SRC = {30, 11, 31, 13};
133static const BG_POINT RUN_SETUP_CHOOSE_DECK_USE_SEED_BTN_DEST_POS = {17, 14};
134
135static const BG_POINT RUN_SETUP_CHOOSE_DECK_SEED_BTN_3X3_SRC_POS = {0 , 29};
136static const BG_POINT RUN_SETUP_CHOOSE_DECK_SEED_BTN_DISABLED_3X3_SRC_POS = {3 , 29};
137static const Rect RUN_SETUP_CHOOSE_DECK_SEED_BTN_DEST = {19, 14, 24, 16};
138
139static const Rect RUN_SETUP_CHOOSE_SEED_FRAME_CLEAN_DEST = {4 , 3 , 25, 5 };
140static const Rect RUN_SETUP_CHOOSE_SEED_KEYBOARD_SRC = {10, 24, 31, 31};
141static const Rect RUN_SETUP_CHOOSE_SEED_FIELD_SRC = {24, 22, 31, 23};
142static const BG_POINT RUN_SETUP_CHOOSE_SEED_KEYBOARD_DEST_POS = {4 , 6};
143static const BG_POINT RUN_SETUP_CHOOSE_SEED_FIELD_DEST_POS = {11, 4};
144
145static const BG_POINT RUN_SETUP_CHOOSE_SEED_DECK_BTN_3X3_SRC_POS = RUN_SETUP_CHOOSE_DECK_SEED_BTN_3X3_SRC_POS;
146static const Rect RUN_SETUP_CHOOSE_SEED_DECK_BTN_DEST = {17, 14, 24, 16};
147
148// Pixel sizes
149#define RUN_SETUP_DECK_SPRITE_T_X 48
150#define RUN_SETUP_DECK_SPRITE_T_Y 54
151static const BG_POINT RUN_SETUP_DECK_NAME_TEXT_POS = {80 , 40 };
152static const BG_POINT RUN_SETUP_DECK_DESC_TEXT_POS = {80 , 56 };
153static const Rect RUN_SETUP_DECK_NAME_DESC_RECT = {80 , 40 ,176, 96 };
154static const BG_POINT RUN_SETUP_SEED_FIELD_TEXT_POS = {96 , 40 };
155static const BG_POINT RUN_SETUP_SEED_DECK_TEXT_POS = {152, 120};
156static const BG_POINT RUN_SETUP_PLAY_TEXT_POS = {76 , 120};
157static const BG_POINT RUN_SETUP_BACK_TEXT_POS = {104, 136};
158// clang-format on
159
160#pragma endregion
161
162#pragma region TAB BAR
163/*******************************************************************************
164 * TAB BAR BUTTONS
165 *
166 * Part of all substate but not state-dependent, they are always updated the
167 * same way, thus `run_setup_tabs_update()` will always be called.
168 ******************************************************************************/
169
170enum RunSetupTab
171{
172 RUN_SETUP_TAB_NEW_RUN,
173 RUN_SETUP_TAB_RESUME,
174 RUN_SETUP_TAB_MAX
175};
176
177static bool is_saved_game_valid = false;
178
179static void tab_set_highlight(enum RunSetupTab tab_sel);
180static void run_setup_tabs_update(void);
181
182// clang-format off
183static Button tabs_buttons[RUN_SETUP_TAB_MAX] = {
184 {NEW_RUN_BTN_OUTLINE_COLOR_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX, NULL, NULL},
185 {RESUME_BTN_OUTLINE_COLOR_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX, NULL, NULL},
186};
187// clang-format on
188
189#pragma endregion
190
191#pragma region BOTTOM BUTTONS
192/*******************************************************************************
193 * BOTTOM BUTTONS
194 *
195 * Declared before any SubState because they are common to all of them.
196 *
197 * The behaviour and appearance of the Seed/Deck button will change from state
198 * to state so these Buttons can't be defined here. functions related to their
199 * behaviour can, though.
200 *
201 * The Play and Back buttons will always be the same, but Play needs to be
202 * duplicated anyway to be integrated to each SubState's SelectionGrid, since
203 * the row it is on doesn't always have the same number of buttons.
204 ******************************************************************************/
205
206static int back_row_get_size(void);
207static void back_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection);
208
209static inline void toggle_seed_enabled(bool enable);
210static void use_seed_on_pressed(void);
211static void seed_on_pressed(void);
212static void deck_on_pressed(void);
213static void play_on_pressed(void);
214static void back_on_pressed(void);
215
216// clang-format off
217static Button back_button = {
218 BACK_BTN_OUTLINE_COLOR_PAL_IDX, BACK_BTN_MAIN_COLOR_PAL_IDX,
219 back_on_pressed, NULL
220};
221// clang-format on
222
223#pragma endregion
224
225#pragma region CHOOSE DECK
226/*******************************************************************************
227 * CHOOSE DECK SUBSTATE
228 ******************************************************************************/
229
230enum RunSetupDeckRows
231{
232 RUN_SETUP_DECK_ROW_CHANGE_DECK,
233 RUN_SETUP_DECK_ROW_SEED_PLAY,
234 RUN_SETUP_DECK_ROW_BACK,
235 RUN_SETUP_DECK_ROW_MAX
236};
237
238enum RunSetupDeckBottomButtons
239{
240 RUN_SETUP_DECK_BB_PLAY,
241 RUN_SETUP_DECK_BB_USE_SEED,
242 RUN_SETUP_DECK_BB_SEED,
243 RUN_SETUP_DECK_BB_MAX
244};
245
246// CHOOSE DECK SELECTION GRID
247
248static int change_deck_get_row_size(void);
250 SelectionGrid* selection_grid,
251 int row_idx,
252 const Selection* prev_selection,
253 const Selection* new_selection
254);
255static int seed_play_get_row_size(void);
256static void seed_play_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection);
257
258// clang-format off
259static SelectionGridRow choose_deck_rows[RUN_SETUP_DECK_ROW_MAX] = {
260 {
261 RUN_SETUP_DECK_ROW_CHANGE_DECK,
264 NULL,
265 {.wrap = true}
266 }, {
267 RUN_SETUP_DECK_ROW_SEED_PLAY,
271 {.wrap = false}
272 }, {
273 RUN_SETUP_DECK_ROW_BACK,
276 back_row_on_key_transit,
277 {.wrap = false}
278 }
279};
280// clang-format on
281
282static const Selection RUN_SETUP_CHOOSE_DECK_INIT_SEL = {0, 0};
283static const Selection RUN_SETUP_CHOOSE_DECK_SEL_FROM_SEED = {2, 1};
284
285static SelectionGrid choose_deck_selection_grid = {
286 choose_deck_rows,
287 RUN_SETUP_DECK_ROW_MAX,
288 RUN_SETUP_CHOOSE_DECK_INIT_SEL
289};
290
291// CHOOSE DECK BUTTONS
292
293static void change_deck_on_pressed(void);
294
295static Button change_deck_button = {
296 CHANGE_DECK_BTN_OUTLINE_COLOR_PAL_IDX,
297 CHANGE_DECK_BTN_MAIN_COLOR_PAL_IDX,
299 NULL
300};
301
302// clang-format off
303// Seed button is disabled by default but can be enabled by clicking the toggle just next to it
304static Button choose_deck_bottom_buttons[RUN_SETUP_DECK_BB_MAX] = {
305 {
306 PLAY_BTN_OUTLINE_COLOR_PAL_IDX, BLUE_BTN_MAIN_COLOR_PAL_IDX,
307 play_on_pressed, NULL
308 }, {
309 SEED_CHECK_BTN_OUTLINE_COLOR_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX,
311 }, {
312 SEED_DECK_BTN_OUTLINE_COLOR_PAL_IDX, BLUE_DISABLED_BTN_MAIN_COLOR_PAL_IDX,
313 seed_on_pressed, NULL
314 }
315};
316// clang-format on
317
318static bool use_seed = false;
319static CardObject* run_setup_deck = NULL;
320
321#pragma endregion
322
323#pragma region SEED KEYBOARD
324/*******************************************************************************
325 * SEED KEYBOARD SUBSTATE
326 ******************************************************************************/
327
328#define KEYBOARD_WIDTH 10
329#define KEYBOARD_HEIGHT 4
330
331enum RunSetupSeedRows
332{
333 RUN_SETUP_SEED_ROW_KEY0,
334 RUN_SETUP_SEED_ROW_KEY1,
335 RUN_SETUP_SEED_ROW_KEY2,
336 RUN_SETUP_SEED_ROW_KEY3,
337 RUN_SETUP_SEED_ROW_DECK_PLAY,
338 RUN_SETUP_SEED_ROW_BACK,
339 RUN_SETUP_SEED_ROW_MAX
340};
341
342enum RunSetupKeyboardButtons
343{
344 RUN_SETUP_KEYBOARD_BEGIN,
345 // Row 0
346 RUN_SETUP_KEYBOARD_1 = RUN_SETUP_KEYBOARD_BEGIN,
347 RUN_SETUP_KEYBOARD_2,
348 RUN_SETUP_KEYBOARD_3,
349 RUN_SETUP_KEYBOARD_4,
350 RUN_SETUP_KEYBOARD_5,
351 RUN_SETUP_KEYBOARD_6,
352 RUN_SETUP_KEYBOARD_7,
353 RUN_SETUP_KEYBOARD_8,
354 RUN_SETUP_KEYBOARD_9,
355 RUN_SETUP_KEYBOARD_0,
356 // Row 1
357 RUN_SETUP_KEYBOARD_A,
358 RUN_SETUP_KEYBOARD_B,
359 RUN_SETUP_KEYBOARD_C,
360 RUN_SETUP_KEYBOARD_D,
361 RUN_SETUP_KEYBOARD_E,
362 RUN_SETUP_KEYBOARD_F,
363 RUN_SETUP_KEYBOARD_G,
364 RUN_SETUP_KEYBOARD_H,
365 RUN_SETUP_KEYBOARD_I,
366 RUN_SETUP_KEYBOARD_J,
367 // Row 2
368 RUN_SETUP_KEYBOARD_K,
369 RUN_SETUP_KEYBOARD_L,
370 RUN_SETUP_KEYBOARD_M,
371 RUN_SETUP_KEYBOARD_N,
372 RUN_SETUP_KEYBOARD_O,
373 RUN_SETUP_KEYBOARD_P,
374 RUN_SETUP_KEYBOARD_Q,
375 RUN_SETUP_KEYBOARD_R,
376 RUN_SETUP_KEYBOARD_S,
377 RUN_SETUP_KEYBOARD_T,
378 // Row 3
379 RUN_SETUP_KEYBOARD_RAND,
380 RUN_SETUP_KEYBOARD_U,
381 RUN_SETUP_KEYBOARD_V,
382 RUN_SETUP_KEYBOARD_W,
383 RUN_SETUP_KEYBOARD_X,
384 RUN_SETUP_KEYBOARD_Y,
385 RUN_SETUP_KEYBOARD_Z,
386 RUN_SETUP_KEYBOARD_DEL,
387 RUN_SETUP_KEYBOARD_MAX
388};
389
390enum RunSetupSeedBottomButtons
391{
392 RUN_SETUP_SEED_BB_PLAY,
393 RUN_SETUP_SEED_BB_DECK,
394 RUN_SETUP_SEED_BB_MAX
395};
396
397// CHOOSE SEED SELECTION GRID
398
399static int choose_seed_get_keyboard_row_size(void);
401static int choose_seed_get_bottom_row_size(void);
402static void choose_seed_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection);
404 SelectionGrid* selection_grid,
405 int row_idx,
406 const Selection* prev_selection,
407 const Selection* new_selection
408);
409
410// clang-format off
411static SelectionGridRow choose_seed_selection_rows[] = {
412 // First 4 rows are the seed keyboard itself.
413 {
414 RUN_SETUP_SEED_ROW_KEY0,
418 {.wrap = true}
419 }, {
420 RUN_SETUP_SEED_ROW_KEY1,
424 {.wrap = true}
425 }, {
426 RUN_SETUP_SEED_ROW_KEY2,
430 {.wrap = true}
431 }, {
432 RUN_SETUP_SEED_ROW_KEY3,
436 {.wrap = true}
437 },
438 // Then we have the Deck/PLAY and Back rows
439 {
440 RUN_SETUP_SEED_ROW_DECK_PLAY,
444 {.wrap = false}
445 }, {
446 RUN_SETUP_SEED_ROW_BACK,
449 back_row_on_key_transit,
450 {.wrap = false}
451 }
452};
453// clang-format on
454
455static const Selection RUN_SETUP_CHOOSE_SEED_INIT_SEL = {1, 4};
456
457static SelectionGrid choose_seed_selection_grid = {
458 choose_seed_selection_rows,
459 RUN_SETUP_SEED_ROW_MAX,
460 RUN_SETUP_CHOOSE_SEED_INIT_SEL
461};
462
463// CHOOSE SEED BUTTONS
464
465static void keyboard_button_on_pressed(void);
466
467// clang-format off
468
469#define DEF_SEED_KEYBOARD_BUTTON_OBJECT(key) \
470 { \
471 KEYBOARD_##key##_BTN_OUTLINE_COLOR_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX, \
472 keyboard_button_on_pressed, NULL \
473 } \
474
475// Button at [3][0] is there for consistency but is not used since it corresponds to the "Random" key
476static Button keyboard_buttons[KEYBOARD_HEIGHT * KEYBOARD_WIDTH] = {
477 // Row 0
478 DEF_SEED_KEYBOARD_BUTTON_OBJECT(1),
479 DEF_SEED_KEYBOARD_BUTTON_OBJECT(2),
480 DEF_SEED_KEYBOARD_BUTTON_OBJECT(3),
481 DEF_SEED_KEYBOARD_BUTTON_OBJECT(4),
482 DEF_SEED_KEYBOARD_BUTTON_OBJECT(5),
483 DEF_SEED_KEYBOARD_BUTTON_OBJECT(6),
484 DEF_SEED_KEYBOARD_BUTTON_OBJECT(7),
485 DEF_SEED_KEYBOARD_BUTTON_OBJECT(8),
486 DEF_SEED_KEYBOARD_BUTTON_OBJECT(9),
487 DEF_SEED_KEYBOARD_BUTTON_OBJECT(0),
488 // Row 1
489 DEF_SEED_KEYBOARD_BUTTON_OBJECT(A),
490 DEF_SEED_KEYBOARD_BUTTON_OBJECT(B),
491 DEF_SEED_KEYBOARD_BUTTON_OBJECT(C),
492 DEF_SEED_KEYBOARD_BUTTON_OBJECT(D),
493 DEF_SEED_KEYBOARD_BUTTON_OBJECT(E),
494 DEF_SEED_KEYBOARD_BUTTON_OBJECT(F),
495 DEF_SEED_KEYBOARD_BUTTON_OBJECT(G),
496 DEF_SEED_KEYBOARD_BUTTON_OBJECT(H),
497 DEF_SEED_KEYBOARD_BUTTON_OBJECT(I),
498 DEF_SEED_KEYBOARD_BUTTON_OBJECT(J),
499 // Row 2
500 DEF_SEED_KEYBOARD_BUTTON_OBJECT(K),
501 DEF_SEED_KEYBOARD_BUTTON_OBJECT(L),
502 DEF_SEED_KEYBOARD_BUTTON_OBJECT(M),
503 DEF_SEED_KEYBOARD_BUTTON_OBJECT(N),
504 DEF_SEED_KEYBOARD_BUTTON_OBJECT(O),
505 DEF_SEED_KEYBOARD_BUTTON_OBJECT(P),
506 DEF_SEED_KEYBOARD_BUTTON_OBJECT(Q),
507 DEF_SEED_KEYBOARD_BUTTON_OBJECT(R),
508 DEF_SEED_KEYBOARD_BUTTON_OBJECT(S),
509 DEF_SEED_KEYBOARD_BUTTON_OBJECT(T),
510 // Row 3
511 DEF_SEED_KEYBOARD_BUTTON_OBJECT(RAND),
512 DEF_SEED_KEYBOARD_BUTTON_OBJECT(U),
513 DEF_SEED_KEYBOARD_BUTTON_OBJECT(V),
514 DEF_SEED_KEYBOARD_BUTTON_OBJECT(W),
515 DEF_SEED_KEYBOARD_BUTTON_OBJECT(X),
516 DEF_SEED_KEYBOARD_BUTTON_OBJECT(Y),
517 DEF_SEED_KEYBOARD_BUTTON_OBJECT(Z),
518 DEF_SEED_KEYBOARD_BUTTON_OBJECT(DEL)
519};
520
521static Button choose_seed_bottom_buttons[2] = {
522 {
523 PLAY_BTN_OUTLINE_COLOR_PAL_IDX, BLUE_BTN_MAIN_COLOR_PAL_IDX,
524 play_on_pressed, NULL
525 }, {
526 SEED_DECK_BTN_OUTLINE_COLOR_PAL_IDX, BLUE_BTN_MAIN_COLOR_PAL_IDX,
527 deck_on_pressed, NULL
528 }
529};
530
531static const char KEYBOARD_BUTTONS_TO_CHAR[KEYBOARD_HEIGHT * KEYBOARD_WIDTH] = {
532 '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
533 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
534 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
535 ' ', 'U', 'V', 'W', 'X', 'Y', 'Z'
536};
537// clang-format on
538
539// Size BASE36_MAX_DIGITS + 1 to always have '\0' at the end
540static char s_seed_str[BASE36_MAX_DIGITS + 1] = {'\0'};
541static u8 s_seed_cursor_pos = 0;
542
543#pragma endregion
544
545#pragma region RESUME
546/*******************************************************************************
547 * RESUME SUBSTATE
548 ******************************************************************************/
549
550enum RunSetupResumeRows
551{
552 RUN_SETUP_RESUME_ROW_PLAY,
553 RUN_SETUP_RESUME_ROW_BACK,
554 RUN_SETUP_RESUME_ROW_MAX
555};
556
557// RESUME SELECTION GRID
558
559// RESUME BUTTONS
560
561#pragma endregion
562
563#pragma region STATE FUNCTIONS
564/*******************************************************************************
565 * STATE FUNCTIONS
566 ******************************************************************************/
567
569{
570 tte_erase_screen();
571 GRIT_CPY(pal_bg_mem, background_run_setup_gfxPal);
572 GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_run_setup_gfxTiles);
573 GRIT_CPY(&se_mem[MAIN_BG_SBB], background_run_setup_gfxMap);
574}
575
577{
578 state_machine_register(&run_setup_sm);
580
581 // Apply the current use_seed value if seed is UNDEFINED
582 if (g_game_vars.rng_info.seed == UNDEFINED)
583 {
584 // Make the string empty instead of showing all zeroes
585 memset(s_seed_str, '\0', BASE36_MAX_DIGITS + 1);
586 s_seed_cursor_pos = 0;
587 }
588 // Or use previous Run's seed if it hasn't been reset
589 else
590 {
591 u32_to_base36(g_game_vars.rng_info.seed, s_seed_str);
592 s_seed_cursor_pos = BASE36_MAX_DIGITS;
593 use_seed = true;
594 }
595 toggle_seed_enabled(use_seed);
596
597 // Rank doesn't matter, won't see it
598 run_setup_deck = card_object_new(card_new(SPADES, ACE));
599
600 // We put it at the same layer as the main menu Ace card, but it's okay because
601 // both cards do not exist at the same time, one is destroyed before the other is created.
602 card_object_set_sprite_face_down(run_setup_deck, g_game_vars.deck, 0);
603
605 (SpriteObject*)run_setup_deck,
606 RUN_SETUP_DECK_SPRITE_T_X,
607 RUN_SETUP_DECK_SPRITE_T_Y
608 );
609
610 /* Uncomment these lines when we figure out how to properly restore a game save
611 is_saved_game_valid = is_game_data_valid();
612 if (is_saved_game_valid)
613 {
614 state_machine_change_state(&run_setup_sm, RUN_SETUP_SUBSTATE_RESUME);
615 }
616 */
617
618 // Land on the deck swapping button when landing on this state from the Main Menu
619 choose_deck_selection_grid.selection = RUN_SETUP_CHOOSE_DECK_INIT_SEL;
620 state_machine_change_state(&run_setup_sm, RUN_SETUP_SUBSTATE_CHOOSE_DECK);
621}
622
627
629{
630 state_machine_remove(&run_setup_sm);
631
632 card_destroy(&run_setup_deck->card);
633 card_object_destroy(&run_setup_deck);
634
635 tte_erase_screen();
636}
637
638#pragma endregion
639
640#pragma region IMPLEMENTATION
641/*******************************************************************************
642 * STATIC FUNCTIONS IMPLEMENTATION
643 ******************************************************************************/
644
645// CHOOSE DECK
646
651{
652 // Show Deck sprite, name and TODO: description
653 sprite_object_unhide((SpriteObject*)run_setup_deck);
654 print_deck_name(g_game_vars.deck, RUN_SETUP_DECK_NAME_TEXT_POS);
655 print_deck_description(g_game_vars.deck, RUN_SETUP_DECK_DESC_TEXT_POS);
656
657 // Clean frame and expand 9-patch for the Deck choice background
659 RUN_SETUP_CHOOSE_DECK_CLEAN_LEFT_DEST,
660 RUN_SETUP_FRAME_BG_SE_FILL_SRC_POS
661 );
663 RUN_SETUP_CHOOSE_DECK_CLEAN_RIGHT_DEST,
664 RUN_SETUP_FRAME_BG_SE_FILL_SRC_POS
665 );
667 RUN_SETUP_CHOOSE_DECK_CHOICE_BG_9_PTCH_DEST,
668 &RUN_SETUP_CHOOSE_DECK_CHOICE_BG_9_PTCH_SRC
669 );
670
671 // TODO: add left/right navigation arrows once more decks have been implemented
672
673 // Set Tab to "New Run"
674 // Uncomment when tab row is re-added (clang-format made it ugly, sorry)
675 // main_bg_se_copy_rect(RUN_SETUP_RESUME_TAB_DISABLED_SRC,
676 // RUN_SETUP_RESUME_TAB_DISABLED_DEST_POS); tab_set_highlight(RUN_SETUP_TAB_NEW_RUN);
677
678 // Set button highlights
679 button_set_highlight(&change_deck_button, true);
680 button_set_highlight(&choose_deck_bottom_buttons[RUN_SETUP_DECK_BB_USE_SEED], false);
681 button_set_highlight(&choose_deck_bottom_buttons[RUN_SETUP_DECK_BB_PLAY], false);
682 button_set_highlight(&back_button, false);
683 toggle_seed_enabled(use_seed);
684
685 // Print button text
686 tte_printf(
687 "#{P:%d,%d; cx:0x%X000}%s",
688 RUN_SETUP_PLAY_TEXT_POS.x,
689 RUN_SETUP_PLAY_TEXT_POS.y,
690 TTE_WHITE_PB,
691 "PLAY"
692 );
693 tte_printf(
694 "#{P:%d,%d; cx:0x%X000}%s",
695 RUN_SETUP_BACK_TEXT_POS.x,
696 RUN_SETUP_BACK_TEXT_POS.y,
697 TTE_WHITE_PB,
698 "Back"
699 );
700}
701
707{
708 selection_grid_process_input(&choose_deck_selection_grid);
709}
710
717{
718 return 1;
719}
720
727static inline Button* change_deck_get_button_from_sel(const Selection* sel)
728{
729 switch (sel->y)
730 {
731 case RUN_SETUP_DECK_ROW_CHANGE_DECK:
732 return &change_deck_button;
733
734 case RUN_SETUP_DECK_ROW_SEED_PLAY:
735 if (sel->x >= RUN_SETUP_DECK_BB_MAX)
736 return NULL;
737 return &choose_deck_bottom_buttons[sel->x];
738
739 case RUN_SETUP_DECK_ROW_BACK:
740 return &back_button;
741 }
742 return NULL;
743}
744
755 SelectionGrid* selection_grid,
756 int row_idx,
757 const Selection* prev_selection,
758 const Selection* new_selection
759)
760{
763
764 // TODO: detect left/right press on Change Deck row to allow swapping
765 // Decks need to be implemented for this
766
767 return true;
768}
769
776{
777 return 3;
778}
779
786static void seed_play_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection)
787{
788 if (key_hit(SELECT_CARD))
789 button_press(&choose_deck_bottom_buttons[selection->x]);
790}
791
792// CHOOSE SEED
793
797static inline void update_seed_text(void)
798{
799 tte_printf(
800 "#{P:%d,%d; cx:0x%X000}%-*s",
801 RUN_SETUP_SEED_FIELD_TEXT_POS.x,
802 RUN_SETUP_SEED_FIELD_TEXT_POS.y,
803 TTE_BLACK_PB,
804 BASE36_MAX_DIGITS + 1,
805 s_seed_str
806 );
807}
808
813{
814 choose_seed_selection_grid.selection = RUN_SETUP_CHOOSE_SEED_INIT_SEL;
815 tte_erase_rect_wrapper(RUN_SETUP_DECK_NAME_DESC_RECT);
816
817 // Hide Deck card sprite
818 sprite_object_hide((SpriteObject*)run_setup_deck);
819
820 // Clean deck swap screen with frame BG color
822 RUN_SETUP_CHOOSE_SEED_FRAME_CLEAN_DEST,
823 RUN_SETUP_FRAME_BG_SE_FILL_SRC_POS
824 );
825
826 // Copy keyboard tiles
828 RUN_SETUP_CHOOSE_SEED_KEYBOARD_SRC,
829 RUN_SETUP_CHOOSE_SEED_KEYBOARD_DEST_POS
830 );
831 main_bg_se_copy_rect(RUN_SETUP_CHOOSE_SEED_FIELD_SRC, RUN_SETUP_CHOOSE_SEED_FIELD_DEST_POS);
832
833 // Replace seed toggle and button by "Deck" button that allows going back to deck substate
835 RUN_SETUP_CHOOSE_SEED_DECK_BTN_DEST,
836 RUN_SETUP_CHOOSE_SEED_DECK_BTN_3X3_SRC_POS
837 );
838 tte_printf(
839 "#{P:%d,%d; cx:0x%X000}%s",
840 RUN_SETUP_SEED_DECK_TEXT_POS.x,
841 RUN_SETUP_SEED_DECK_TEXT_POS.y,
842 TTE_WHITE_PB,
843 "Deck " // extra space after to clean potential "Seed" text
844 );
845
846 // Set buttons highlight
847 for (enum RunSetupKeyboardButtons key = RUN_SETUP_KEYBOARD_BEGIN; key < RUN_SETUP_KEYBOARD_MAX;
848 key++)
849 {
850 button_set_highlight(&keyboard_buttons[key], false);
851 }
852 button_set_highlight(&choose_seed_bottom_buttons[RUN_SETUP_SEED_BB_PLAY], false);
853 button_set_highlight(&choose_seed_bottom_buttons[RUN_SETUP_SEED_BB_DECK], true);
854 button_set_highlight(&back_button, false);
855
856 // Print seed text
858}
859
865{
866 selection_grid_process_input(&choose_seed_selection_grid);
867}
868
875{
876 return KEYBOARD_WIDTH;
877}
878
885{
886 return KEYBOARD_WIDTH - 2;
887}
888
895{
896 return 2;
897}
898
902static inline void reroll_seed_str(void)
903{
904 // Need to roll a new seed and get a "real" random number. Otherwise the seed is still stuck at
905 // 0 and we'll have the same sequence of generated seeds each time.
906 // Also, don't use the shuffled seed as is, or we'll just end up with sequential seeds when
907 // rolling multiple times.
909 u32_to_base36(g_game_vars.rng_info.seed, s_seed_str);
911 s_seed_cursor_pos = BASE36_MAX_DIGITS;
912}
913
917static inline void delete_seed_char(void)
918{
919 if (s_seed_cursor_pos == 0)
920 return;
921
922 s_seed_str[--s_seed_cursor_pos] = '\0';
924}
925
931static inline void type_seed_char(enum RunSetupKeyboardButtons key)
932{
933 if (s_seed_cursor_pos >= BASE36_MAX_DIGITS)
934 return;
935
936 s_seed_str[s_seed_cursor_pos++] = KEYBOARD_BUTTONS_TO_CHAR[key];
938}
939
947static inline enum RunSetupKeyboardButtons get_keyboard_index_from_sel(const Selection* sel)
948{
949 return sel->x + KEYBOARD_WIDTH * sel->y;
950}
951
956{
957 // Type something only if the button pressed in on the keyboard
958 if (choose_seed_selection_grid.selection.y > RUN_SETUP_SEED_ROW_KEY3)
959 return;
960
961 // Type only if the seed string is not full.
962 // The cursor position is unsigned so always positive, but we still need to
963 // ensure it doersn't go out of bounds by more than 1 so that we can always
964 // substract 1 from it when erasing a character from the seed string.
965 if (s_seed_cursor_pos > BASE36_MAX_DIGITS)
966 s_seed_cursor_pos = BASE36_MAX_DIGITS;
967
968 if (key_hit(DESELECT_CARDS))
970
971 else if (key_hit(SELECT_CARD))
972 {
973 // Get keyboard button index from selection
974 enum RunSetupKeyboardButtons key =
975 get_keyboard_index_from_sel(&choose_seed_selection_grid.selection);
976
977 switch (key)
978 {
979 case RUN_SETUP_KEYBOARD_RAND:
981 break;
982
983 // Erase last character
984 case RUN_SETUP_KEYBOARD_DEL:
986 break;
987
988 default:
989 type_seed_char(key);
990 break;
991 }
992 }
993}
994
1001static inline Button* choose_seed_get_button_from_sel(const Selection* sel)
1002{
1003 switch (sel->y)
1004 {
1005 case RUN_SETUP_SEED_ROW_KEY0:
1006 case RUN_SETUP_SEED_ROW_KEY1:
1007 case RUN_SETUP_SEED_ROW_KEY2:
1008 case RUN_SETUP_SEED_ROW_KEY3:
1009 return &keyboard_buttons[get_keyboard_index_from_sel(sel)];
1010
1011 case RUN_SETUP_SEED_ROW_DECK_PLAY:
1012 return &choose_seed_bottom_buttons[sel->x];
1013
1014 case RUN_SETUP_SEED_ROW_BACK:
1015 return &back_button;
1016 }
1017 return NULL;
1018}
1019
1028static void choose_seed_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection)
1029{
1030 if (key_hit(SELECT_CARD) ||
1031 (selection->y <= RUN_SETUP_SEED_ROW_KEY3 && key_hit(DESELECT_CARDS)))
1032 {
1034 }
1035}
1036
1047 SelectionGrid* selection_grid,
1048 int row_idx,
1049 const Selection* prev_selection,
1050 const Selection* new_selection
1051)
1052{
1053 // TODO: since some rows don't have the same number of buttons but their widths line up,
1054 // need to find a way to shift selection.x to left or right to keep navigation consistent
1055 bool proceed_selection = true;
1056
1057 if (row_idx == prev_selection->y)
1059
1060 if (row_idx == new_selection->y)
1061 {
1062 Selection shifted_selection = *new_selection;
1063
1064 // From row 3 to 4
1065 if (prev_selection->y == RUN_SETUP_SEED_ROW_KEY2 &&
1066 new_selection->y == RUN_SETUP_SEED_ROW_KEY3 && prev_selection->x >= 5 &&
1067 prev_selection->x <= 8)
1068 {
1069 shifted_selection.x++;
1070 selection_grid->selection = shifted_selection;
1071 proceed_selection = false;
1072 }
1073
1074 // From row 4 to 3
1075 else if (prev_selection->y == RUN_SETUP_SEED_ROW_KEY3 &&
1076 new_selection->y == RUN_SETUP_SEED_ROW_KEY2 && prev_selection->x >= 1 &&
1077 prev_selection->x <= 3)
1078 {
1079 shifted_selection.x++;
1080 selection_grid->selection = shifted_selection;
1081 proceed_selection = false;
1082 }
1083
1084 button_set_highlight(choose_seed_get_button_from_sel(&shifted_selection), true);
1085 }
1086
1087 return proceed_selection;
1088}
1089
1093static void deck_on_pressed(void)
1094{
1095 state_machine_change_state(&run_setup_sm, RUN_SETUP_SUBSTATE_CHOOSE_DECK);
1096 choose_deck_selection_grid.selection = RUN_SETUP_CHOOSE_DECK_SEL_FROM_SEED;
1097 button_set_highlight(&change_deck_button, false);
1098 button_set_highlight(&choose_deck_bottom_buttons[RUN_SETUP_DECK_BB_SEED], true);
1099}
1100
1101// RESUME GAME
1102
1106static void resume_substate_init(void)
1107{
1108 tab_set_highlight(RUN_SETUP_TAB_RESUME);
1109
1110 // Show Deck card sprite
1111 sprite_object_unhide((SpriteObject*)run_setup_deck);
1112}
1113
1114// COMMON BUTTONS
1115
1123static inline void toggle_seed_enabled(bool enable)
1124{
1125 use_seed = enable;
1126
1127 // Apply right main color to the Button
1128 choose_deck_bottom_buttons[RUN_SETUP_DECK_BB_SEED].button_pal_idx =
1129 use_seed ? BLUE_BTN_MAIN_COLOR_PAL_IDX : BLUE_DISABLED_BTN_MAIN_COLOR_PAL_IDX;
1130 button_set_highlight(&choose_deck_bottom_buttons[RUN_SETUP_DECK_BB_SEED], false);
1131
1132 // Replace Seed button tiles with the disabled one's
1133 BG_POINT button_tiles = use_seed ? RUN_SETUP_CHOOSE_DECK_SEED_BTN_3X3_SRC_POS
1134 : RUN_SETUP_CHOOSE_DECK_SEED_BTN_DISABLED_3X3_SRC_POS;
1135 main_bg_se_copy_expand_3x3_rect(RUN_SETUP_CHOOSE_DECK_SEED_BTN_DEST, button_tiles);
1136
1137 // Print Seed button text with the right color
1138 tte_printf(
1139 "#{P:%d,%d; cx:0x%X000}%s",
1140 RUN_SETUP_SEED_DECK_TEXT_POS.x,
1141 RUN_SETUP_SEED_DECK_TEXT_POS.y,
1142 use_seed ? TTE_WHITE_PB : TTE_BLACK_PB,
1143 " Seed" // Extra space before to clean potential "Deck" text
1144 );
1145
1146 // Replace toggle button tiles with either checkmark of empty circle
1147 Rect toggle_tiles = use_seed ? RUN_SETUP_CHOOSE_DECK_USE_SEED_BTN_ON_SRC
1148 : RUN_SETUP_CHOOSE_DECK_USE_SEED_BTN_OFF_SRC;
1149 main_bg_se_copy_rect(toggle_tiles, RUN_SETUP_CHOOSE_DECK_USE_SEED_BTN_DEST_POS);
1150}
1151
1155static void use_seed_on_pressed(void)
1156{
1157 toggle_seed_enabled(!use_seed);
1158}
1159
1163static void seed_on_pressed(void)
1164{
1165 if (use_seed)
1166 state_machine_change_state(&run_setup_sm, RUN_SETUP_SUBSTATE_CHOOSE_SEED);
1167}
1168
1172static void play_on_pressed(void)
1173{
1174 // Apply provided Seed if enabled, and if we entered one. This prevents us from always using
1175 // seed "ZZZZZZ" if we enter the Seed menu and hit Play without typing anything.
1176 if (use_seed && strlen(s_seed_str) > 0)
1177 rng_set_seed(base36_to_u32(s_seed_str));
1178 else
1180
1181 use_seed = false;
1182
1183 game_change_state(GAME_STATE_GAME_START);
1184}
1185
1189static void back_on_pressed(void)
1190{
1191 game_change_state(GAME_STATE_MAIN_MENU);
1192}
1193
1197static void change_deck_on_pressed(void)
1198{
1199}
1200
1207static void tab_set_highlight(enum RunSetupTab tab_sel)
1208{
1209 for (enum RunSetupTab tab = 0; tab < RUN_SETUP_TAB_MAX; tab++)
1210 {
1211 button_set_highlight(&tabs_buttons[tab], tab == tab_sel);
1212 }
1213}
1214
1218static void run_setup_tabs_update(void)
1219{
1220 static enum RunSetupTab current_tab = RUN_SETUP_TAB_RESUME;
1221
1222 // Either not pressed anything or there is no saved data, "Resume" tab is left grayed out and
1223 // only one tab is available. Return early to not spend time on tab-changing logic
1224 if (!key_hit(KEY_ANY) || !is_saved_game_valid)
1225 return;
1226
1227 // Not all the way to the right and pressed R
1228 if (key_hit(TAB_RIGHT) && current_tab < RUN_SETUP_TAB_MAX - 1)
1229 {
1230 button_set_highlight(&tabs_buttons[current_tab], false);
1231 current_tab++;
1232 }
1233 // Not all the way to the left and pressed L
1234 else if (key_hit(TAB_LEFT) && current_tab > 0)
1235 {
1236 button_set_highlight(&tabs_buttons[current_tab], false);
1237 current_tab--;
1238 }
1239
1240 button_set_highlight(&tabs_buttons[current_tab], true);
1241
1242 switch (current_tab)
1243 {
1244 case RUN_SETUP_TAB_NEW_RUN:
1245 state_machine_change_state(&run_setup_sm, RUN_SETUP_SUBSTATE_CHOOSE_DECK);
1246 break;
1247
1248 case RUN_SETUP_TAB_RESUME:
1249 state_machine_change_state(&run_setup_sm, RUN_SETUP_SUBSTATE_RESUME);
1250 break;
1251
1252 default:
1253 break;
1254 }
1255}
1256
1263{
1264 return 1;
1265}
1266
1267static void back_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection)
1268{
1269 if (key_hit(SELECT_CARD))
1270 button_press(&back_button);
1271}
1272
1273#pragma endregion
A button structure containing the common button functionalities Including highlight and pressing func...
void button_press(Button *button)
Execute a button press, by calling the button's on_pressed function. This checks the button's can_be_...
Definition button.c:18
void button_set_highlight(Button *button, bool highlight)
Set the button highlight on or off.
Definition button.c:8
void print_deck_name(enum DeckType deck, BG_POINT pos)
Prints the Deck name string to the screen at the given position.
Definition deck_types.c:43
void print_deck_description(enum DeckType deck, BG_POINT pos)
Prints the Deck description string to the screen at the given position.
Definition deck_types.c:48
Game global game variables struct definition.
Graphic utility functions.
void main_bg_se_copy_rect(Rect se_rect, BG_POINT dest_pos)
Copies a rect in the main background from se_rect to the position (x, y).
void main_bg_se_copy_expand_3x3_rect(Rect se_rect_dest, BG_POINT se_rect_src_3x3_top_left)
Copies a 3x3 rect and expands it to fit a passed rect. Special case of the 9-patch.
void tte_erase_rect_wrapper(Rect rect)
A wrapper for tte_erase_rect that would use the rect struct.
void main_bg_se_copy_expand_9_patch(Rect se_dest_rect, const NinePatchRect *src_9_ptch)
Copies a 9-patch and expands it to fit a passed rect.
void main_bg_se_copy_expand_tile(Rect se_rect_dest, BG_POINT se_tile_src)
Copies a tile in the main background at se_tile_src to fill se_rect_dest.
void rng_shuffle_seed(void)
Sets a new randomized seed for the RNG using a source of entropy.
Definition random.c:27
void rng_set_seed(u32 seed)
Set the rng seed to the chosen value, and reset the step counter to 0. The seed will be capped at MAX...
Definition random.c:33
static Button * change_deck_get_button_from_sel(const Selection *sel)
Gets the Button corresponding to the current Selection in choose_deck_selection_grid
Definition run_setup.c:727
static int back_row_get_size(void)
Retuns the width of the Back button's row.
Definition run_setup.c:1262
void game_run_setup_change_background(void)
Change to the Run Setup menu background.
Definition run_setup.c:568
static void keyboard_button_on_pressed(void)
Keyboard key Button callback.
Definition run_setup.c:955
static void delete_seed_char(void)
Deletes the last char in the seed string base-36 representation.
Definition run_setup.c:917
static void seed_on_pressed(void)
Seed Button Callback. Opens the seed input keyboard.
Definition run_setup.c:1163
static void seed_keyboard_substate_update(void)
Update the Choose Seed substate by handling user inputs though the corresponding choose_seed_selectio...
Definition run_setup.c:864
static void update_seed_text(void)
Prints the string representing the chosen seed in base-36.
Definition run_setup.c:797
static void back_on_pressed(void)
Back Button Callback. Goes back to the Main Menu.
Definition run_setup.c:1189
static enum RunSetupKeyboardButtons get_keyboard_index_from_sel(const Selection *sel)
Get the keyboard key index from a SelectionGrid's Selection. The returned value is valid only if the ...
Definition run_setup.c:947
static void toggle_seed_enabled(bool enable)
Toggle whether or not we will use the seed chosen by the user. Changes the looks of the Seed button t...
Definition run_setup.c:1123
static void play_on_pressed(void)
Play Button Callback. Applies the chosen seed if enabled and starts a new run.
Definition run_setup.c:1172
static Button * choose_seed_get_button_from_sel(const Selection *sel)
Get the Button corresponding to a Selection within choose_seed_selection_grid
Definition run_setup.c:1001
void game_run_setup_on_exit(void)
Run Setup menu cleanup.
Definition run_setup.c:628
static void tab_set_highlight(enum RunSetupTab tab_sel)
Highlights the tab_sel Tab at the top of the screen, and removes highlight from all the others.
Definition run_setup.c:1207
static void change_deck_on_pressed(void)
Button Callback used for cycling through the Decks.
Definition run_setup.c:1197
static int choose_seed_get_bottom_row_size(void)
Returns the width of the Deck/Play buttons' row.
Definition run_setup.c:894
static int choose_seed_get_keyboard_short_row_size(void)
Returns the width of the bottom keyboard row, the shortest one.
Definition run_setup.c:884
static void choose_deck_substate_update(void)
Update the deck changing substate by handling user input though its corresponding SelectionGrid.
Definition run_setup.c:706
static bool choose_seed_row_on_selection_changed(SelectionGrid *selection_grid, int row_idx, const Selection *prev_selection, const Selection *new_selection)
Handle directional imputs in choose_seed_selection_grid
Definition run_setup.c:1046
static void choose_seed_row_on_key_transit(SelectionGrid *selection_grid, Selection *selection)
Handle button imputs in choose_seed_selection_grid
Definition run_setup.c:1028
static void seed_keyboard_substate_init(void)
Initialize the Choose Seed substate.
Definition run_setup.c:812
static void seed_play_row_on_key_transit(SelectionGrid *selection_grid, Selection *selection)
Handle button inputs for choose_deck_selection_grid
Definition run_setup.c:786
void game_run_setup_on_update(void)
Run Setup menu state update.
Definition run_setup.c:623
static int seed_play_get_row_size(void)
Returns the width of the Seed checkbox/Seed/Play buttons' row.
Definition run_setup.c:775
void game_run_setup_on_init(void)
Run Setup menu state initialization.
Definition run_setup.c:576
static void reroll_seed_str(void)
Deletes the last char in the seed string base-36 representation.
Definition run_setup.c:902
static void run_setup_tabs_update(void)
Handle user input in regards to the Tabs. Tabs are cycled through using the L/R buttons.
Definition run_setup.c:1218
static void resume_substate_init(void)
Initialize the "Resume Previous Run" substate.
Definition run_setup.c:1106
static int change_deck_get_row_size(void)
Returns the width of the Change Deck Button's row.
Definition run_setup.c:716
static void deck_on_pressed(void)
Deck Button Callback.
Definition run_setup.c:1093
static void use_seed_on_pressed(void)
Seed checkbox Button Callback. Toggles custom seed usage.
Definition run_setup.c:1155
static void choose_deck_substate_init(void)
Initializes the Deck changing substate.
Definition run_setup.c:650
static void type_seed_char(enum RunSetupKeyboardButtons key)
Add a new char at the end of the seed string.
Definition run_setup.c:931
static int choose_seed_get_keyboard_row_size(void)
Returns the width of the 3 top keyboard rows.
Definition run_setup.c:874
static bool choose_deck_row_on_selection_changed(SelectionGrid *selection_grid, int row_idx, const Selection *prev_selection, const Selection *new_selection)
Handle directional input in choose_deck_selection_grid
Definition run_setup.c:754
Setup Run menu state functions.
Utils functions to save/load data structures from/to the SRAM.
An implementation for a selection grid that handles directional selection.
void selection_grid_process_input(SelectionGrid *selection_grid)
Processes user input for the selection grid.
Sprite system for Gbalatro.
void sprite_object_unhide(SpriteObject *sprite_object)
Unhides the SpriteObject by manipulating ATTR0_HIDE in OAM. The sprite's ATTR0_MODE is maintained fro...
Definition sprite.c:220
INLINE void sprite_object_position(SpriteObject *sprite_object, int x, int y)
Set sprite_object position. Inlined for efficiency.
Definition sprite.h:417
void sprite_object_hide(SpriteObject *sprite_object)
Hides the SpriteObject by manipulating ATTR0_HIDE in OAM.
Definition sprite.c:213
State Machine.
void state_machine_remove(StateMachine *state_machine)
Remove a statemachine's update function.
void state_machine_register(StateMachine *state_machine)
Register a statemachine to run it's update function once per frame.
void noop(void)
no operation
void state_machine_change_state(StateMachine *state_machine, int new_state)
Calls the current state's on_exit, the new state's on_init, and sets the active update fn.
A button representation.
Definition button.h:31
u8 button_pal_idx
Palette index of the color of the button itself, used for the border when not highlighted.
Definition button.h:43
Structure to represent arbitrary-sized 9-patches.
u32 seed
Definition random.h:43
The core selection grid struct, represents the grid itself and its state.
A sprite object is a sprite that is focusable and movable in animation.
Definition sprite.h:61
State machine callbacks.
State machine instance.
StateInfo * state_infos
Array of StateCallbacks , one entry per state.
Utilities relating around number string representation and protected arithmatic helper functions.
uint32_t base36_to_u32(const char b36_str[])
Convert a base-36 string representation to a 32-bit unsigned integer. Since we are dealing with base-...
Definition util.c:260
void u32_to_base36(uint32_t n, char b36_str[])
Convert a 32-bit unsigned integer to its base-36 string representation. This will perform 6 divisions...
Definition util.c:272