From bf1212b873d3941f094f2319d208b5ee046e71af Mon Sep 17 00:00:00 2001 From: Alex Troesch Date: Thu, 14 Nov 2024 04:03:53 -0800 Subject: [PATCH] Implement setting to force flash size Adds libretro setting to toggle between automatic detection and fixed sizes for the cartidge flash. Allows for selection of "auto", "64kb", and "128kb" options. This allows for compatibility with roms which need a specific amount of memory but do not appear in the list of known overrides. --- gba_memory.c | 63 +++++++++++++++++--------------- gba_memory.h | 3 +- libretro/libretro.c | 15 +++++++- libretro/libretro_core_options.h | 12 ++++++ 4 files changed, 61 insertions(+), 32 deletions(-) diff --git a/gba_memory.c b/gba_memory.c index 7badef57..731d232a 100644 --- a/gba_memory.c +++ b/gba_memory.c @@ -2540,37 +2540,40 @@ static s32 load_gamepak_raw(const char *name) } u32 load_gamepak(const struct retro_game_info* info, const char *name, - int force_rtc, int force_rumble, int force_serial) + int force_rtc, int force_rumble, int force_serial, + int force_flash_size) { - gamepak_info_t gpinfo; - - if (load_gamepak_raw(name)) - return -1; - - // Buffer 0 always has the first 1MB chunk of the ROM - memset(&gpinfo, 0, sizeof(gpinfo)); - memcpy(gpinfo.gamepak_title, &gamepak_buffers[0][0xA0], 12); - memcpy(gpinfo.gamepak_code, &gamepak_buffers[0][0xAC], 4); - memcpy(gpinfo.gamepak_maker, &gamepak_buffers[0][0xB0], 2); - - idle_loop_target_pc = 0xFFFFFFFF; - translation_gate_targets = 0; - flash_device_id = FLASH_DEVICE_MACRONIX_64KB; - flash_bank_cnt = FLASH_SIZE_64KB; - rtc_enabled = false; - rumble_enabled = false; - backup_type_reset = BACKUP_UNKN; - serial_mode = force_serial; - - load_game_config_over(&gpinfo); - - // Forced RTC / Rumble modes, override the autodetect logic. - if (force_rtc != FEAT_AUTODETECT) - rtc_enabled = (force_rtc == FEAT_ENABLE); - if (force_rumble != FEAT_AUTODETECT) - rumble_enabled = (force_rumble == FEAT_ENABLE); - - return 0; + gamepak_info_t gpinfo; + + if (load_gamepak_raw(name)) + return -1; + + // Buffer 0 always has the first 1MB chunk of the ROM + memset(&gpinfo, 0, sizeof(gpinfo)); + memcpy(gpinfo.gamepak_title, &gamepak_buffers[0][0xA0], 12); + memcpy(gpinfo.gamepak_code, &gamepak_buffers[0][0xAC], 4); + memcpy(gpinfo.gamepak_maker, &gamepak_buffers[0][0xB0], 2); + + idle_loop_target_pc = 0xFFFFFFFF; + translation_gate_targets = 0; + flash_device_id = FLASH_DEVICE_MACRONIX_64KB; + flash_bank_cnt = FLASH_SIZE_64KB; + rtc_enabled = false; + rumble_enabled = false; + backup_type_reset = BACKUP_UNKN; + serial_mode = force_serial; + + load_game_config_over(&gpinfo); + + // Forced RTC / Rumble / Flash modes, override the autodetect logic. + if (force_rtc != FEAT_AUTODETECT) + rtc_enabled = (force_rtc == FEAT_ENABLE); + if (force_rumble != FEAT_AUTODETECT) + rumble_enabled = (force_rumble == FEAT_ENABLE); + if (force_flash_size != FEAT_AUTODETECT) + flash_bank_cnt = force_flash_size; + + return 0; } s32 load_bios(char *name) diff --git a/gba_memory.h b/gba_memory.h index c97e77f0..6cd3838d 100644 --- a/gba_memory.h +++ b/gba_memory.h @@ -246,7 +246,8 @@ extern char gamepak_filename[512]; cpu_alert_type dma_transfer(unsigned dma_chan, int *cycles); u8 *memory_region(u32 address, u32 *memory_limit); u32 load_gamepak(const struct retro_game_info* info, const char *name, - int force_rtc, int force_rumble, int force_serial); + int force_rtc, int force_rumble, int force_serial, + int force_flash_size); s32 load_bios(char *name); void init_memory(void); void init_gamepak_buffer(void); diff --git a/libretro/libretro.c b/libretro/libretro.c index 6afa60dd..ad958434 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -94,6 +94,7 @@ int sprite_limit = 1; static int rtc_mode = FEAT_AUTODETECT; static int rumble_mode = FEAT_AUTODETECT; +static int flash_size_setting = FEAT_AUTODETECT; static int serial_setting = SERIAL_MODE_AUTO; u32 idle_loop_target_pc = 0xFFFFFFFF; @@ -905,6 +906,18 @@ static void check_variables(bool started_from_load) else rumble_mode = FEAT_AUTODETECT; } + + var.key = "gpsp_flash_size"; + var.value = 0; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "64kb")) + flash_size_setting = FLASH_SIZE_64KB; + else if (!strcmp(var.value, "128kb")) + flash_size_setting = FLASH_SIZE_128KB; + else + flash_size_setting = FEAT_AUTODETECT; + } } var.key = "gpsp_sprlim"; @@ -1108,7 +1121,7 @@ bool retro_load_game(const struct retro_game_info* info) } memset(gamepak_backup, 0xff, sizeof(gamepak_backup)); - if (load_gamepak(info, info->path, rtc_mode, rumble_mode, serial_setting) != 0) + if (load_gamepak(info, info->path, rtc_mode, rumble_mode, serial_setting, flash_size_setting) != 0) { error_msg("Could not load the game file."); return false; diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h index 098db767..ffe68cf3 100644 --- a/libretro/libretro_core_options.h +++ b/libretro/libretro_core_options.h @@ -136,6 +136,18 @@ struct retro_core_option_definition option_defs_us[] = { }, "auto" }, + { + "gpsp_flash_size", + "Save flash size", + "Sets the size of the flash memory for the emulated cartridge. Autodetect uses a ROM database that works with most commercial titles. You might want to force a particular size when using homebrew or ROM hacks that support or require it.", + { + { "auto", NULL }, + { "64kb", NULL }, + { "128kb", NULL }, + { NULL, NULL }, + }, + "auto" + }, { "gpsp_frameskip", "Frameskip",