diff --git a/dynamic.c b/dynamic.c index 458eee3fad..adb5291174 100644 --- a/dynamic.c +++ b/dynamic.c @@ -185,7 +185,7 @@ void libretro_free_system_info(struct retro_system_info *info) memset(info, 0, sizeof(*info)); } -const struct retro_game_special_info *libretro_find_subsystem_info(const struct retro_game_special_info *info, unsigned num_info, +const struct retro_subsystem_info *libretro_find_subsystem_info(const struct retro_subsystem_info *info, unsigned num_info, const char *ident) { unsigned i; @@ -930,11 +930,11 @@ bool rarch_environment_cb(unsigned cmd, void *data) return driver_update_system_av_info((const struct retro_system_av_info*)data); } - case RETRO_ENVIRONMENT_SET_SPECIAL_GAME_TYPES: + case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO: { - RARCH_LOG("Environ SET_SPECIAL_GAME_TYPES.\n"); + RARCH_LOG("Environ SET_SUBSYSTEM_INFO.\n"); unsigned i, j; - const struct retro_game_special_info *info = (const struct retro_game_special_info*)data; + const struct retro_subsystem_info *info = (const struct retro_subsystem_info*)data; for (i = 0; info[i].ident; i++) { RARCH_LOG("Special game type: %s\n", info[i].desc); @@ -949,11 +949,12 @@ bool rarch_environment_cb(unsigned cmd, void *data) } free(g_extern.system.special); - g_extern.system.special = (struct retro_game_special_info*)calloc(i, sizeof(*g_extern.system.special)); + g_extern.system.special = (struct retro_subsystem_info*)calloc(i, sizeof(*g_extern.system.special)); if (!g_extern.system.special) return false; memcpy(g_extern.system.special, info, i * sizeof(*g_extern.system.special)); + g_extern.system.num_special = i; break; } diff --git a/dynamic.h b/dynamic.h index cc83cd06f4..9f5996c110 100644 --- a/dynamic.h +++ b/dynamic.h @@ -64,7 +64,7 @@ void libretro_free_system_info(struct retro_system_info *info); // Transforms a library id to a name suitable as a pathname. void libretro_get_current_core_pathname(char *name, size_t size); -const struct retro_game_special_info *libretro_find_subsystem_info(const struct retro_game_special_info *info, unsigned num_info, const char *ident); +const struct retro_subsystem_info *libretro_find_subsystem_info(const struct retro_subsystem_info *info, unsigned num_info, const char *ident); extern void (*pretro_init)(void); extern void (*pretro_deinit)(void); diff --git a/file.c b/file.c index 929eb99cb3..ea57169821 100644 --- a/file.c +++ b/file.c @@ -321,7 +321,7 @@ void save_ram_file(const char *path, int type) } } -static bool load_roms(const struct retro_game_special_info *special, const struct string_list *roms) +static bool load_roms(const struct retro_subsystem_info *special, const struct string_list *roms) { unsigned i; bool ret = true; @@ -388,7 +388,7 @@ bool init_rom_file(void) if (!g_extern.temporary_roms) return false; - const struct retro_game_special_info *special = NULL; + const struct retro_subsystem_info *special = NULL; if (*g_extern.subsystem) { diff --git a/general.h b/general.h index 87e592bb51..00068a77c8 100644 --- a/general.h +++ b/general.h @@ -443,7 +443,7 @@ struct global core_option_manager_t *core_options; - struct retro_game_special_info *special; + struct retro_subsystem_info *special; unsigned num_special; } system; diff --git a/libretro-test/libretro-test.c b/libretro-test/libretro-test.c index 7157e63234..12e5d1b636 100644 --- a/libretro-test/libretro-test.c +++ b/libretro-test/libretro-test.c @@ -115,6 +115,21 @@ void retro_set_environment(retro_environment_t cb) if (!cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging)) logging.log = fallback_log; + + static const struct retro_subsystem_memory_info mem1[] = {{ "ram1", 0x400 }, { "ram2", 0x401 }}; + static const struct retro_subsystem_memory_info mem2[] = {{ "ram3", 0x402 }, { "ram4", 0x403 }}; + + static const struct retro_subsystem_rom_info roms[] = { + { "Test Rom #1", "bin", false, false, true, mem1, 2, }, + { "Test Rom #2", "bin", false, false, true, mem2, 2, }, + }; + + static const struct retro_subsystem_info types[] = { + { "Foo", "foo", roms, 2, 0x200, }, + { NULL }, + }; + + cb(RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO, (void*)types); } void retro_set_audio_sample(retro_audio_sample_t cb) @@ -370,10 +385,11 @@ unsigned retro_get_region(void) bool retro_load_game_special(unsigned type, const struct retro_game_info *info, size_t num) { - (void)type; - (void)info; - (void)num; - return false; + if (type != 0x200) + return false; + if (num != 2) + return false; + return retro_load_game(NULL); } size_t retro_serialize_size(void) diff --git a/libretro.h b/libretro.h index eddbda81ac..4ef9d93a5c 100755 --- a/libretro.h +++ b/libretro.h @@ -600,8 +600,8 @@ enum retro_mod // // If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK **MUST** be called from within retro_set_environment(). // -#define RETRO_ENVIRONMENT_SET_SPECIAL_GAME_TYPES 34 - // const struct retro_game_special_info * -- +#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 + // const struct retro_subsystem_info * -- // This environment call introduces the concept of libretro "subsystems". // A subsystem is a variant of a libretro core which supports different kinds of games. // The purpose of this is to support e.g. emulators which might have special needs, e.g. Super Nintendos Super GameBoy, Sufami Turbo. @@ -613,41 +613,41 @@ enum retro_mod // // If a core wants to use this functionality, SET_SPECIAL_GAME_TYPES **MUST** be called from within retro_set_environment(). -struct retro_game_special_memory_info +struct retro_subsystem_memory_info { const char *extension; // The extension associated with a memory type, e.g. "psram". unsigned type; // The memory type for retro_get_memory(). This should be at least 0x100 to avoid conflict with standardized libretro memory types. }; -struct retro_game_special_rom_info +struct retro_subsystem_rom_info { - const char *desc; // Describes what the ROM is (SGB bios, GB rom, etc). - const char *valid_extensions; // Same definition as retro_get_system_info(). - bool need_fullpath; // Same definition as retro_get_system_info(). - bool block_extract; // Same definition as retro_get_system_info(). - bool required; // This is set if the ROM is required to load a game. If this is set to false, a zeroed-out retro_game_info can be passed. + const char *desc; // Describes what the ROM is (SGB bios, GB rom, etc). + const char *valid_extensions; // Same definition as retro_get_system_info(). + bool need_fullpath; // Same definition as retro_get_system_info(). + bool block_extract; // Same definition as retro_get_system_info(). + bool required; // This is set if the ROM is required to load a game. If this is set to false, a zeroed-out retro_game_info can be passed. - // ROMs can have multiple associated persistent memory types (retro_get_memory()). - const struct retro_game_special_memory_info *memory; - unsigned num_memory; + // ROMs can have multiple associated persistent memory types (retro_get_memory()). + const struct retro_subsystem_memory_info *memory; + unsigned num_memory; }; -struct retro_game_special_info +struct retro_subsystem_info { - const char *desc; // Human-readable string of the subsystem type, e.g. "Super GameBoy" - // A computer friendly short string identifier for the subsystem type. - // This name must be [a-z]. - // E.g. if desc is "Super GameBoy", this can be "sgb". - // This identifier can be used for command-line interfaces, etc. - const char *ident; + const char *desc; // Human-readable string of the subsystem type, e.g. "Super GameBoy" + // A computer friendly short string identifier for the subsystem type. + // This name must be [a-z]. + // E.g. if desc is "Super GameBoy", this can be "sgb". + // This identifier can be used for command-line interfaces, etc. + const char *ident; - // Infos for each ROM. The first entry is assumed to be the "most significant" ROM for frontend purposes. - // E.g. with Super GameBoy, the first ROM should be the GameBoy ROM, as it is the most "significant" ROM to a user. - // If a frontend creates new file paths based on the ROM used (e.g. savestates), it should use the path for the first ROM to do so. - const struct retro_game_special_rom_info *roms; + // Infos for each ROM. The first entry is assumed to be the "most significant" ROM for frontend purposes. + // E.g. with Super GameBoy, the first ROM should be the GameBoy ROM, as it is the most "significant" ROM to a user. + // If a frontend creates new file paths based on the ROM used (e.g. savestates), it should use the path for the first ROM to do so. + const struct retro_subsystem_rom_info *roms; - unsigned num_roms; // Number of ROMs associated with a subsystem. - unsigned id; // The type passed to retro_load_game_special(). + unsigned num_roms; // Number of ROMs associated with a subsystem. + unsigned id; // The type passed to retro_load_game_special(). }; typedef void (*retro_proc_address_t)(void); diff --git a/retroarch.c b/retroarch.c index 72d5acd6f0..34d195c615 100644 --- a/retroarch.c +++ b/retroarch.c @@ -902,6 +902,7 @@ static void parse_input(int argc, char *argv[]) g_extern.has_set_save_path = false; g_extern.has_set_state_path = false; g_extern.has_set_libretro = false; + *g_extern.subsystem = '\0'; if (argc < 2) { @@ -1782,10 +1783,11 @@ static void fill_pathnames(void) if (*g_extern.subsystem) { unsigned i; - const struct retro_game_special_info *info = libretro_find_subsystem_info(g_extern.system.special, g_extern.system.num_special, g_extern.subsystem); + const struct retro_subsystem_info *info = libretro_find_subsystem_info(g_extern.system.special, g_extern.system.num_special, g_extern.subsystem); // We'll handle this error gracefully later. - unsigned num_roms = info ? info->num_roms : 0; + unsigned num_roms = min(info ? info->num_roms : 0, g_extern.subsystem_fullpaths ? g_extern.subsystem_fullpaths->size : 0); + bool use_sram_dir = path_is_directory(g_extern.savefile_name); for (i = 0; i < num_roms; i++) @@ -1793,7 +1795,7 @@ static void fill_pathnames(void) unsigned j; for (j = 0; j < info->roms[i].num_memory; j++) { - const struct retro_game_special_memory_info *mem = &info->roms[i].memory[j]; + const struct retro_subsystem_memory_info *mem = &info->roms[i].memory[j]; union string_list_elem_attr attr; char path[PATH_MAX];