25#define HEADER_ADDRESS 0x0
26#define OPTIONS_ADDRESS 0x10
27#define GAME_ADDRESS 0x30
29#define SAVE_SECTION_FLAG_NONE 0
30#define SAVE_SECTION_FLAG_OPTIONS (1 << 0)
31#define SAVE_SECTION_FLAG_GAME (1 << 1)
33#define CHECK_MAGIC 0x4C414247
34#define CHECK_HASH_SIZE 7
35#define GIT_HASH_START 17
37#define SAVE_LABEL_SIZE 16
56 char githash[CHECK_HASH_SIZE];
67 .valid_sections = SAVE_SECTION_FLAG_NONE
88 char tag_options[SAVE_LABEL_SIZE];
90 bool cards_high_contrast;
91 bool cards_more_readable;
102 .tag_options =
"- OPTIONS DATA -",
103 .game_speed = GAME_SPEED_MIN,
104 .cards_high_contrast = DEFAULT_HIGH_CONTRAST,
105 .cards_more_readable = DEFAULT_MORE_READABLE,
106 .music_volume = VOLUME_OPTION_MAX,
107 .sound_volume = VOLUME_OPTION_MAX,
109 UNDEFINED, UNDEFINED, UNDEFINED,
110 UNDEFINED, UNDEFINED, UNDEFINED,
111 UNDEFINED, UNDEFINED, UNDEFINED,
125 u32 persistent_state;
161 char tag_internal[SAVE_LABEL_SIZE];
169 char tag_jokers[SAVE_LABEL_SIZE];
179 .tag_internal =
"-INTERNAL DATA -",
181 .rng_info = {0, {0}},
185 .padding = {UNDEFINED, UNDEFINED},
187 .tag_jokers =
"- OWNED JOKERS -",
200static inline void write_sram(u32 sram_base,
const u8* bytes, u32 size)
202 if (sram_base + size > SRAM_SIZE)
205 for (u32 i = 0; i < size; i++)
207 sram_mem[sram_base + i] = bytes[i];
216static inline void read_sram(u32 sram_base, u8* bytes, u32 size)
218 if (sram_base + size > SRAM_SIZE)
221 for (u32 i = 0; i < size; i++)
223 bytes[i] = sram_mem[sram_base + i];
236 for (u32 i = 0; i < CHECK_HASH_SIZE; i++)
238 if (gbalatro_version[GIT_HASH_START + i] != prefix[i])
256 return strlen(gbalatro_version) > GIT_HASH_START + CHECK_HASH_SIZE;
267 read_sram(HEADER_ADDRESS, (u8*)header,
sizeof(*header));
268 return (header->magic == CHECK_MAGIC) && header->dirty ==
is_version_dirty() &&
294 header.valid_sections |= section_flag;
297 memcpy(&(header.githash), gbalatro_version + GIT_HASH_START, CHECK_HASH_SIZE);
299 write_sram(HEADER_ADDRESS, (
const u8*)&header,
sizeof(header));
306 options.game_speed = g_game_vars.game_speed;
307 options.cards_high_contrast = get_cards_high_contrast();
308 options.cards_more_readable = get_cards_more_readable();
309 options.music_volume = g_game_vars.music_volume;
310 options.sound_volume = g_game_vars.sound_volume;
312 write_sram(OPTIONS_ADDRESS, (
const u8*)&options,
sizeof(options));
323 if (
get_save_header(&header) && (header.valid_sections & SAVE_SECTION_FLAG_OPTIONS))
324 read_sram(OPTIONS_ADDRESS, (u8*)&options,
sizeof(options));
326 g_game_vars.game_speed = options.game_speed;
327 g_game_vars.music_volume = options.music_volume;
328 g_game_vars.sound_volume = options.sound_volume;
331 set_cards_high_contrast(options.cards_high_contrast);
332 set_cards_more_readable(options.cards_more_readable);
338 return get_save_header(&header) && (header.valid_sections & SAVE_SECTION_FLAG_GAME);
347 game.timer = g_game_vars.timer;
348 game.rng_info = g_game_vars.rng_info;
349 game.round = g_game_vars.round;
350 game.ante = g_game_vars.ante;
351 game.money = g_game_vars.money;
355 List* jokers_list = get_jokers_list();
359 for (; i < nb_jokers; i++)
363 (u32)joker_object->joker->id,
364 joker_object->joker->persistent_state
366 game.jokers_data[i] = data;
368 for (; i < MAX_JOKERS_HELD_SIZE; i++)
371 game.jokers_data[i] = data;
374 write_sram(GAME_ADDRESS, (
const u8*)&game,
sizeof(game));
382 if (!
get_save_header(&header) || !(header.valid_sections & SAVE_SECTION_FLAG_GAME))
386 read_sram(GAME_ADDRESS, (u8*)&game,
sizeof(game));
388 g_game_vars.timer = game.timer;
390 g_game_vars.round = game.round;
391 g_game_vars.ante = game.ante;
392 g_game_vars.money = game.money;
Utilities for using maxmod to play sound effects.
int volume_module_step_to_val(unsigned char step)
Get MaxMod module audio value from VOLUME_OPTION value.
A bitset for operating on flags.
Game global game variables struct definition.
Functions relative to the handling of Jokers.
void * list_get_at_idx(List *list, unsigned int idx)
int list_get_len(const List *list)
void rng_restore(RngInfo info)
Restore RNG info struct in the GameVariables. Sets the seed and restores the state for each independe...
bool is_game_data_valid(void)
Checks whether the SaveGame section is present and valid.
static const SaveOptions SaveOptions_default
Default value for the SaveOptions struct, with tags already set.
static bool is_version_dirty(void)
Determines if the current build is considered "dirty" aka has uncommitted changes....
static bool check_hash(const char *prefix)
Checks the 7 chars of gbalatro_version after the "GBALATRO_VERSION" prefix representing the git hash ...
static void read_sram(u32 sram_base, u8 *bytes, u32 size)
Read raw binary data from SRAM.
void save_game(void)
Save current run data to SRAM.
static bool get_save_header(SaveHeader *header)
Reads whether the save data exists and is valid.
void load_game(void)
Load previous run data from SRAM.
void load_options(void)
Load options values from SRAM.
static const SaveGame SaveGame_default
Default value for the SaveGame struct, with tags already set.
static const SaveHeader SaveHeader_default
Default value for the SaveHeader struct.
static void write_sram(u32 sram_base, const u8 *bytes, u32 size)
Write raw binary data to SRAM.
static void set_save_header(u32 section_flag)
Writes a magic number and ROM version info to SRAM to signal that the save data exists and allow the ...
void save_options(void)
Save options values to SRAM.
Utils functions to save/load data structures from/to the SRAM.
JokerObjectSaveData will hold the minimal amount of data necessary to reconstruct a Joker....
Information to track and restore RNG state.
SaveGame will contain the data about the current run to be saved to SRAM. GameVariables was used for ...
SaveOptions will only contain options data set in the Options Menu.
Utilities relating around number string representation and protected arithmatic helper functions.
Game ROM version global var declaration.