From 221b6d77c09ccf86981fa8702acc5e011674bad8 Mon Sep 17 00:00:00 2001 From: Rickey Date: Mon, 25 May 2026 11:11:33 -0700 Subject: [PATCH] Add option to enable a more readable deck, suggestion by @Turro75 (#495) (#511) * Options menu revamp * Implement readable card sprites * redraw characters to fix the original style * clang format * remove usage of UNDEFINED (-1) for unsigned values * typo * change save fix for something cleaner * remove dependency to game_variables.h from card.c * Make the palette look less silly ^^' * Address @ricfehr3's comments * clang format * quick rename * clang format --------- Co-authored-by: Geralt <84459734+MathisMartin31@users.noreply.github.com> Co-authored-by: MathisMartin31 Co-authored-by: Turro75 --- graphics/background_options_menu_gfx.png | Bin 2124 -> 2272 bytes graphics/deck_big_gfx.grit | 1 + graphics/deck_big_gfx.png | Bin 0 -> 3190 bytes include/card.h | 12 +- include/game_variables.h | 8 +- source/card.c | 37 ++++-- source/game.c | 4 - source/game/options_menu.c | 148 ++++++++++++++--------- source/main.c | 1 - source/save.c | 71 ++++++----- 10 files changed, 172 insertions(+), 110 deletions(-) create mode 100644 graphics/deck_big_gfx.grit create mode 100644 graphics/deck_big_gfx.png diff --git a/graphics/background_options_menu_gfx.png b/graphics/background_options_menu_gfx.png index d36c827ebb59f3cab204c6282813c010876a303a..3f7f840e502f78b60d5aedfc18d1833b31a53b2b 100644 GIT binary patch delta 1202 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 Hc-p@JWhGMs literal 0 HcmV?d00001 diff --git a/include/card.h b/include/card.h index d716f48..8cf7aad 100644 --- a/include/card.h +++ b/include/card.h @@ -40,6 +40,10 @@ #define IMPOSSIBLY_HIGH_CARD_VALUE 100 +// Card sprites +#define DEFAULT_HIGH_CONTRAST false +#define DEFAULT_MORE_READABLE false + // Card types typedef struct Card { @@ -54,9 +58,11 @@ typedef struct CardObject bool selected; } CardObject; -// Card functions -void card_init(); -void toggle_high_contrast_cards(bool enable); +// Card sprites accessibility functions +void set_cards_high_contrast(bool enable); +void set_cards_more_readable(bool enable); +bool get_cards_high_contrast(void); +bool get_cards_more_readable(void); // Card methods Card* card_new(u8 suit, u8 rank); diff --git a/include/game_variables.h b/include/game_variables.h index cd1c92b..21d2f31 100644 --- a/include/game_variables.h +++ b/include/game_variables.h @@ -19,10 +19,9 @@ #define VOLUME_OPTION_MAX 5 #define VOLUME_OPTION_INCREMENT 20 -#define DEFAULT_GAME_SPEED 1 -#define DEFAULT_HIGH_CONTRAST false -#define DEFAULT_MUSIC_VOLUME VOLUME_OPTION_MAX -#define DEFAULT_SOUND_VOLUME VOLUME_OPTION_MAX +#define DEFAULT_GAME_SPEED 1 +#define DEFAULT_MUSIC_VOLUME VOLUME_OPTION_MAX +#define DEFAULT_SOUND_VOLUME VOLUME_OPTION_MAX #define MAX_HANDS 4 #define MAX_DISCARDS 4 @@ -66,7 +65,6 @@ typedef struct // BY DEFAULT IS SET TO 1, but if changed to 2 or more, should speed up all (or most) of the // game aspects that should be sped up by speed, as in the original game. u8 game_speed; - bool high_contrast; u8 music_volume; u8 sound_volume; } GameVariables; diff --git a/source/card.c b/source/card.c index 528146b..4500353 100644 --- a/source/card.c +++ b/source/card.c @@ -1,8 +1,6 @@ #include "card.h" -#include "deck_gfx.h" #include "graphic_utils.h" -#include "high_contrast_deck_pal_gfx.h" #include #include @@ -11,6 +9,11 @@ #include "pool.h" #include "soundbank.h" +// Card Sprites and Palettes +#include "deck_big_gfx.h" +#include "deck_gfx.h" +#include "high_contrast_deck_pal_gfx.h" + // Card sprites lookup table. First index is the suit, second index is the rank. The value is the // tile index. const static u16 _card_sprite_lut[NUM_SUITS][NUM_RANKS] = { @@ -20,14 +23,13 @@ const static u16 _card_sprite_lut[NUM_SUITS][NUM_RANKS] = { {624, 640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816} }; -void card_init() -{ - toggle_high_contrast_cards(false); -} +bool high_contrast = DEFAULT_HIGH_CONTRAST; +bool more_readable = DEFAULT_MORE_READABLE; -void toggle_high_contrast_cards(bool enable) +void set_cards_high_contrast(bool enable) { - if (enable) + high_contrast = enable; + if (high_contrast) { GRIT_CPY(&pal_obj_mem[CARD_PB], high_contrast_deck_pal_gfxPal); } @@ -37,6 +39,21 @@ void toggle_high_contrast_cards(bool enable) } } +void set_cards_more_readable(bool enable) +{ + more_readable = enable; +} + +bool get_cards_high_contrast(void) +{ + return high_contrast; +} + +bool get_cards_more_readable(void) +{ + return more_readable; +} + // Card methods Card* card_new(u8 suit, u8 rank) { @@ -103,10 +120,10 @@ void card_object_update(CardObject* card_object) void card_object_set_sprite(CardObject* card_object, int layer) { int tile_index = CARD_TID + (layer * CARD_SPRITE_OFFSET); + const unsigned int* card_tiles = more_readable ? deck_big_gfxTiles : deck_gfxTiles; memcpy32( &tile_mem[TILE_MEM_OBJ_CHARBLOCK0_IDX][tile_index], - &deck_gfxTiles - [_card_sprite_lut[card_object->card->suit][card_object->card->rank] * TILE_SIZE], + &card_tiles[_card_sprite_lut[card_object->card->suit][card_object->card->rank] * TILE_SIZE], TILE_SIZE * CARD_SPRITE_OFFSET ); Sprite* sprite = sprite_new( diff --git a/source/game.c b/source/game.c index e3ab495..a93da96 100644 --- a/source/game.c +++ b/source/game.c @@ -289,7 +289,6 @@ GameVariables g_game_vars = { .round_end_blind_token = NULL, .game_speed = DEFAULT_GAME_SPEED, - .high_contrast = DEFAULT_HIGH_CONTRAST, .music_volume = DEFAULT_MUSIC_VOLUME, .sound_volume = DEFAULT_SOUND_VOLUME, }; @@ -2599,9 +2598,6 @@ void game_start(void) g_game_vars.hands = MAX_HANDS; g_game_vars.discards = MAX_DISCARDS; - // Activate high contrast palette for cards if loaded settings tell us to - toggle_high_contrast_cards(g_game_vars.high_contrast); - // Fill the deck with all the cards. Later on this can be replaced with a more dynamic system // that allows for different decks and card types. for (int suit = 0; suit < NUM_SUITS; suit++) diff --git a/source/game/options_menu.c b/source/game/options_menu.c index 04719ad..ee08e6a 100644 --- a/source/game/options_menu.c +++ b/source/game/options_menu.c @@ -4,6 +4,7 @@ #include "audio_utils.h" #include "background_options_menu_gfx.h" #include "button.h" +#include "card.h" #include "game.h" #include "game/common_ui.h" #include "game_variables.h" @@ -39,23 +40,26 @@ enum OptionSpeedButtons #define MENU_BUTTON_MAIN_COLOR_PAL_IDX 1 #define SAVE_BUTTON_MAIN_COLOR_PAL_IDX 3 #define BACK_BUTTON_MAIN_COLOR_PAL_IDX 4 -#define SPEED_DOWN_BUTTON_OUTLINE_COLOR_PAL_IDX 5 -#define SPEED_BUTTON_OUTLINE_COLOR_PAL_IDX 6 -#define SPEED_UP_BUTTON_OUTLINE_COLOR_PAL_IDX 7 -#define CONTRAST_BUTTON_OUTLINE_COLOR_PAL_IDX 8 -#define MUSIC_BUTTON_OUTLINE_COLOR_PAL_IDX 9 -#define SOUND_BUTTON_OUTLINE_COLOR_PAL_IDX 10 -#define SAVE_BUTTON_OUTLINE_COLOR_PAL_IDX 11 -#define BACK_BUTTON_OUTLINE_COLOR_PAL_IDX 12 +#define SPEED_DOWN_BUTTON_OUTLINE_COLOR_PAL_IDX 16 +#define SPEED_BUTTON_OUTLINE_COLOR_PAL_IDX 17 +#define SPEED_UP_BUTTON_OUTLINE_COLOR_PAL_IDX 18 +#define CONTRAST_BUTTON_OUTLINE_COLOR_PAL_IDX 19 +#define READABLE_BUTTON_OUTLINE_COLOR_PAL_IDX 20 +#define MUSIC_BUTTON_OUTLINE_COLOR_PAL_IDX 21 +#define SOUND_BUTTON_OUTLINE_COLOR_PAL_IDX 22 +#define SAVE_BUTTON_OUTLINE_COLOR_PAL_IDX 23 +#define BACK_BUTTON_OUTLINE_COLOR_PAL_IDX 24 // Define selection grid for the menu buttons static void game_speed_down_on_pressed(void); static void game_speed_up_on_pressed(void); static void high_contrast_on_pressed(void); +static void more_readable_on_pressed(void); static void save_on_pressed(void); static void back_on_pressed(void); static int options_menu_return_upper_rows_size(void); +static int options_menu_return_card_sprites_row_size(void); static int options_menu_return_bottom_row_size(void); static void options_menu_row_on_key_transit(SelectionGrid* selection_grid, Selection* selection); static bool game_speed_row_on_selection_changed( @@ -95,7 +99,7 @@ static SelectionGridRow options_menu_selection_rows[] = { }, { HIGH_CONTRAST_ROW_IDX, - options_menu_return_upper_rows_size, + options_menu_return_card_sprites_row_size, regular_button_row_on_selection_changed, options_menu_row_on_key_transit, {.wrap = false} @@ -125,7 +129,10 @@ static SelectionGridRow options_menu_selection_rows[] = { static Button options_menu_buttons[NB_OPTIONS_ROWS][2] = { {{SPEED_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, NULL, NULL}}, - {{CONTRAST_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, high_contrast_on_pressed, NULL}}, + { + {CONTRAST_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, high_contrast_on_pressed, NULL}, + {READABLE_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, more_readable_on_pressed, NULL} + }, {{MUSIC_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, NULL, NULL}}, {{SOUND_BUTTON_OUTLINE_COLOR_PAL_IDX, MENU_BUTTON_MAIN_COLOR_PAL_IDX, NULL, NULL}}, { @@ -164,9 +171,12 @@ static const Rect OPTIONS_SPEED_VALUES[GAME_SPEED_MAX] = { { 3, 20, 4, 21 { 4, 22, 5, 23} }; static const BG_POINT OPTIONS_SPEED_VALUE_DEST_POS = {14, 3}; -static const Rect OPTIONS_CONTRAST_VALUE_YES_SRC_RECT = { 1, 24, 4, 25}; -static const Rect OPTIONS_CONTRAST_VALUE_NO_SRC_RECT = { 6, 24, 9, 25}; -static const BG_POINT OPTIONS_CONTRAST_VALUE_DEST_POS = {13, 7}; +static const Rect OPTIONS_CONTRAST_CHECK_NO_SRC_RECT = { 0, 24, 1, 25}; +static const Rect OPTIONS_CONTRAST_CHECK_YES_SRC_RECT = { 2, 24, 3, 25}; +static const BG_POINT OPTIONS_CONTRAST_CHECK_DEST_POS = {14, 7}; +static const Rect OPTIONS_READABLE_CHECK_NO_SRC_RECT = { 4, 24, 5, 25}; +static const Rect OPTIONS_READABLE_CHECK_YES_SRC_RECT = { 6, 24, 7, 25}; +static const BG_POINT OPTIONS_READABLE_CHECK_DEST_POS = {21, 7}; static const Rect OPTIONS_MUSIC_SLIDER_FULL_SRC = { 9, 20, 9, 20}; static const Rect OPTIONS_MUSIC_SLIDER_MID_SRC = {10, 20, 10, 20}; @@ -184,13 +194,13 @@ static const u8 OPTIONS_SOUND_SLIDER_SEGMENT_LENGTH = (OPTIONS_SOUND_ / VOLUME_OPTION_MAX; // Values in pixels -static const BG_POINT OPTIONS_GAME_SPEED_TEXT_POS = { 82, 16}; -static const BG_POINT OPTIONS_HIGH_CONTRAST_TEXT_POS = { 40, 48}; -static const BG_POINT OPTIONS_MUSIC_VOLUME_TEXT_POS = { 56, 80}; -static const BG_POINT OPTIONS_MUSIC_VALUE_TEXT_POS = {160, 80}; -static const BG_POINT OPTIONS_SOUND_VOLUME_TEXT_POS = { 56, 104}; -static const BG_POINT OPTIONS_SOUND_VALUE_TEXT_POS = {160, 104}; -static const BG_POINT OPTIONS_BACK_SAVE_TEXT_POS = { 64, 136}; +static const BG_POINT OPTIONS_GAME_SPEED_TEXT_POS = { 82, 16}; +static const BG_POINT OPTIONS_CARD_SPRITES_TEXT_POS = { 72, 48}; +static const BG_POINT OPTIONS_MUSIC_VOLUME_TEXT_POS = { 56, 80}; +static const BG_POINT OPTIONS_MUSIC_VALUE_TEXT_POS = {160, 80}; +static const BG_POINT OPTIONS_SOUND_VOLUME_TEXT_POS = { 56, 104}; +static const BG_POINT OPTIONS_SOUND_VALUE_TEXT_POS = {160, 104}; +static const BG_POINT OPTIONS_BACK_SAVE_TEXT_POS = { 64, 136}; // clang-format on #define GAME_SPEED_ARROW_HIGHLIGHT_DURATION 10 @@ -212,8 +222,21 @@ static void disable_all_outlines_except_self(Selection sel_btn) for (int j = 0; j < NB_OPTIONS_ROWS; j++) { - int nb_buttons_in_row = (j == SAVE_BACK_ROW_IDX) ? options_menu_return_bottom_row_size() - : options_menu_return_upper_rows_size(); + int nb_buttons_in_row; + + switch (j) + { + case HIGH_CONTRAST_ROW_IDX: + nb_buttons_in_row = options_menu_return_card_sprites_row_size(); + break; + case SAVE_BACK_ROW_IDX: + nb_buttons_in_row = options_menu_return_bottom_row_size(); + break; + default: + nb_buttons_in_row = options_menu_return_upper_rows_size(); + break; + } + for (int i = 0; i < nb_buttons_in_row; i++) { button_set_highlight(&options_menu_buttons[j][i], i == sel_btn.x && j == sel_btn.y); @@ -224,29 +247,16 @@ static void disable_all_outlines_except_self(Selection sel_btn) static void update_game_speed_button_graphics() { // check if need to disable game speed arrows - if (g_game_vars.game_speed == GAME_SPEED_MIN) - { - main_bg_se_copy_rect( - OPTIONS_SPEED_DOWN_DISABLED_BTN_SRC_RECT, - OPTIONS_SPEED_DOWN_BTN_DEST_POS - ); - } - else - { - main_bg_se_copy_rect( - OPTIONS_SPEED_DOWN_ACTIVE_BTN_SRC_RECT, - OPTIONS_SPEED_DOWN_BTN_DEST_POS - ); - } - if (g_game_vars.game_speed == GAME_SPEED_MAX) - { - main_bg_se_copy_rect(OPTIONS_SPEED_UP_DISABLED_BTN_SRC_RECT, OPTIONS_SPEED_UP_BTN_DEST_POS); - } - else - { - main_bg_se_copy_rect(OPTIONS_SPEED_UP_ACTIVE_BTN_SRC_RECT, OPTIONS_SPEED_UP_BTN_DEST_POS); - } + Rect speed_down_btn_tiles = (g_game_vars.game_speed == GAME_SPEED_MIN) + ? OPTIONS_SPEED_DOWN_DISABLED_BTN_SRC_RECT + : OPTIONS_SPEED_DOWN_ACTIVE_BTN_SRC_RECT; + main_bg_se_copy_rect(speed_down_btn_tiles, OPTIONS_SPEED_DOWN_BTN_DEST_POS); + + Rect speed_up_btn_tiles = (g_game_vars.game_speed == GAME_SPEED_MAX) + ? OPTIONS_SPEED_UP_DISABLED_BTN_SRC_RECT + : OPTIONS_SPEED_UP_ACTIVE_BTN_SRC_RECT; + main_bg_se_copy_rect(speed_up_btn_tiles, OPTIONS_SPEED_UP_BTN_DEST_POS); main_bg_se_copy_rect( OPTIONS_SPEED_VALUES[g_game_vars.game_speed - 1], @@ -254,16 +264,18 @@ static void update_game_speed_button_graphics() ); } -static void update_high_contrast_button_graphics() +static void update_high_contrast_button_graphics(void) { - if (g_game_vars.high_contrast) - { - main_bg_se_copy_rect(OPTIONS_CONTRAST_VALUE_YES_SRC_RECT, OPTIONS_CONTRAST_VALUE_DEST_POS); - } - else - { - main_bg_se_copy_rect(OPTIONS_CONTRAST_VALUE_NO_SRC_RECT, OPTIONS_CONTRAST_VALUE_DEST_POS); - } + Rect contrast_btn_tiles = (get_cards_high_contrast()) ? OPTIONS_CONTRAST_CHECK_YES_SRC_RECT + : OPTIONS_CONTRAST_CHECK_NO_SRC_RECT; + main_bg_se_copy_rect(contrast_btn_tiles, OPTIONS_CONTRAST_CHECK_DEST_POS); +} + +static void update_more_readable_button_graphics(void) +{ + Rect readable_btn_tiles = (get_cards_more_readable()) ? OPTIONS_READABLE_CHECK_YES_SRC_RECT + : OPTIONS_READABLE_CHECK_NO_SRC_RECT; + main_bg_se_copy_rect(readable_btn_tiles, OPTIONS_READABLE_CHECK_DEST_POS); } static void update_volume_slider_graphics(enum OptionButtonRows sel_row) @@ -360,9 +372,9 @@ void game_options_menu_change_background(void) TTE_WHITE_PB ); tte_printf( - "#{P:%d,%d; cx:0x%X000}High Contrast Cards", - OPTIONS_HIGH_CONTRAST_TEXT_POS.x, - OPTIONS_HIGH_CONTRAST_TEXT_POS.y, + "#{P:%d,%d; cx:0x%X000}Card Sprites", + OPTIONS_CARD_SPRITES_TEXT_POS.x, + OPTIONS_CARD_SPRITES_TEXT_POS.y, TTE_WHITE_PB ); tte_printf( @@ -396,6 +408,7 @@ void game_options_menu_on_init(void) // Do an update on the first frame update_game_speed_button_graphics(); update_high_contrast_button_graphics(); + update_more_readable_button_graphics(); update_volume_slider_graphics(MUSIC_VOLUME_ROW_IDX); update_volume_slider_graphics(SOUND_VOLUME_ROW_IDX); } @@ -442,10 +455,19 @@ static void game_speed_up_on_pressed(void) */ static void high_contrast_on_pressed(void) { - g_game_vars.high_contrast = (g_game_vars.high_contrast == 1) ? false : true; + set_cards_high_contrast(!get_cards_high_contrast()); update_high_contrast_button_graphics(); } +/** + * @brief Handles input for the more readable card toggle button and nothing more. + */ +static void more_readable_on_pressed(void) +{ + set_cards_more_readable(!get_cards_more_readable()); + update_more_readable_button_graphics(); +} + /** * @brief Handles input for the Save button. */ @@ -465,7 +487,7 @@ static void back_on_pressed(void) } /** - * @brief Gives the width of upper options menu rows in selection grid. + * @brief Gives the width of normal options rows in selection grid. * * @returns 1 */ @@ -474,6 +496,16 @@ static int options_menu_return_upper_rows_size(void) return 1; } +/** + * @brief Gives the width of Card Sprites options row in selection grid. + * + * @returns 2 + */ +static int options_menu_return_card_sprites_row_size(void) +{ + return 2; +} + /** * @brief Gives the width of the Save and Back buttons' row. * diff --git a/source/main.c b/source/main.c index ce53736..e95c477 100644 --- a/source/main.c +++ b/source/main.c @@ -96,7 +96,6 @@ void init() load_options(); affine_background_init(); sprite_init(); - card_init(); blind_init(); joker_init(); game_init(); diff --git a/source/save.c b/source/save.c index 6fa9510..4cece11 100644 --- a/source/save.c +++ b/source/save.c @@ -5,6 +5,7 @@ #include "audio_utils.h" #include "bitset.h" +#include "card.h" #include "game.h" #include "joker.h" #include "list.h" @@ -55,6 +56,16 @@ typedef struct SaveHeader u32 valid_sections; } SaveHeader; +/** + * @brief Default value for the SaveHeader struct. + */ +static const SaveHeader SaveHeader_default = { + .magic = CHECK_MAGIC, + .dirty = false, + .githash = "fffffff", + .valid_sections = SAVE_SECTION_FLAG_NONE +}; + // clang-format off /** * @brief SaveOptions will only contain options data set in the Options Menu @@ -65,8 +76,8 @@ typedef struct SaveHeader * 1 | 'T' | 'I' | 'O' | 'N' | - | Spells "- OPTIONS DATA -" * 2 | 'S' | ' ' | 'D' | 'A' | - | - * 3 | 'T' | 'A' | ' ' | '-' | - | - - * 4 | SPEED | CNTRST | MUSIC | SOUND | OPTN_VALUES | All 4 option values, packed in a single word. - * 5 | UNDEF | UNDEF | UNDEF | UNDEF | PADDING | Padding, so that the next section starts at the beginning of the + * 4 | SPEED | CNTRST | READBL | MUSIC | OPTN_VALUES | All 5 option values, followed by some padding, + * 5 | SOUND | UNDEF | UNDEF | UNDEF | - | so that the next section starts at the beginning of the * 6 | UNDEF | UNDEF | UNDEF | UNDEF | - | next 4-word row in a hex viewer * 7 | UNDEF | UNDEF | UNDEF | UNDEF | - | - */ @@ -75,12 +86,33 @@ typedef struct SaveOptions { char tag_options[SAVE_LABEL_SIZE]; u8 game_speed; - bool high_contrast; + bool cards_high_contrast; + bool cards_more_readable; u8 music_volume; u8 sound_volume; - u32 padding[3]; + s8 padding[11]; } SaveOptions; +/** + * @brief Default value for the SaveOptions struct, with tags already set. + */ +// clang-format off +static const SaveOptions SaveOptions_default = { + .tag_options = "- OPTIONS DATA -", + .game_speed = GAME_SPEED_MIN, + .cards_high_contrast = DEFAULT_HIGH_CONTRAST, + .cards_more_readable = DEFAULT_MORE_READABLE, + .music_volume = VOLUME_OPTION_MAX, + .sound_volume = VOLUME_OPTION_MAX, + .padding = { + UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED, UNDEFINED, + UNDEFINED, UNDEFINED + } +}; +// clang-format on + /** * @brief JokerObjectSaveData will hold the minimal amount of data necessary to reconstruct a Joker. * The `id` is a u8 in the base Joker struct, but I made it a u32 here to keep @@ -131,7 +163,7 @@ typedef struct SaveGame int round; int ante; int money; - u32 padding[2]; + s32 padding[2]; char tag_jokers[SAVE_LABEL_SIZE]; JokerObjectSaveData jokers_data[MAX_JOKERS_HELD_SIZE]; @@ -139,28 +171,6 @@ typedef struct SaveGame char tag_end[4]; } SaveGame; -/** - * @brief Default value for the SaveHeader struct. - */ -static const SaveHeader SaveHeader_default = { - .magic = CHECK_MAGIC, - .dirty = false, - .githash = "fffffff", - .valid_sections = SAVE_SECTION_FLAG_NONE -}; - -/** - * @brief Default value for the SaveOptions struct, with tags already set. - */ -static const SaveOptions SaveOptions_default = { - .tag_options = "- OPTIONS DATA -", - .game_speed = GAME_SPEED_MIN, - .high_contrast = DEFAULT_HIGH_CONTRAST, - .music_volume = VOLUME_OPTION_MAX, - .sound_volume = VOLUME_OPTION_MAX, - .padding = {UNDEFINED, UNDEFINED, UNDEFINED}, -}; - /** * @brief Default value for the SaveGame struct, with tags already set. */ @@ -293,7 +303,8 @@ void save_options(void) SaveOptions options = SaveOptions_default; options.game_speed = g_game_vars.game_speed; - options.high_contrast = g_game_vars.high_contrast; + options.cards_high_contrast = get_cards_high_contrast(); + options.cards_more_readable = get_cards_more_readable(); options.music_volume = g_game_vars.music_volume; options.sound_volume = g_game_vars.sound_volume; @@ -312,10 +323,12 @@ void load_options(void) read_sram(OPTIONS_ADDRESS, (u8*)&options, sizeof(options)); g_game_vars.game_speed = options.game_speed; - g_game_vars.high_contrast = options.high_contrast; g_game_vars.music_volume = options.music_volume; g_game_vars.sound_volume = options.sound_volume; + set_cards_high_contrast(options.cards_high_contrast); + set_cards_more_readable(options.cards_more_readable); + mmSetModuleVolume(MM_MODULE_FULL_VOLUME * g_game_vars.music_volume / VOLUME_OPTION_MAX); }