diff --git a/.gitignore b/.gitignore index 3a44d42..9a99661 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *.o +*.so *.dll *.pdb *.lib *.exp -*.manifest \ No newline at end of file +*.manifest diff --git a/disc.cpp b/disc.cpp index fb24f71..4929f55 100644 --- a/disc.cpp +++ b/disc.cpp @@ -20,8 +20,14 @@ static bool g_eject_state; static int g_current_disc; +static unsigned g_initial_disc; +static std::string g_initial_disc_path; + static std::vector CDInterfaces; +static std::vector disk_image_paths; +static std::vector disk_image_labels; + // // Remember to rebuild region database in db.cpp if changing the order of // entries in this table(and be careful about game id collisions, @@ -152,11 +158,6 @@ static bool disk_get_eject_state(void) return g_eject_state; } -static unsigned disk_get_image_index(void) -{ - return g_current_disc; -} - static bool disk_set_image_index(unsigned index) { // only listen if the tray is open @@ -229,6 +230,9 @@ static bool disk_replace_image_index(unsigned index, const struct retro_game_inf if (index < CD_SelectedDisc) CD_SelectedDisc--; + disk_image_paths.erase(disk_image_paths.begin() + index); + disk_image_labels.erase(disk_image_labels.begin() + index); + // Poke into psx.cpp CalcDiscSCEx(); return true; @@ -248,6 +252,11 @@ static bool disk_replace_image_index(unsigned index, const struct retro_game_inf extract_basename(retro_cd_base_name, info->path, sizeof(retro_cd_base_name)); /* Ugly, but needed to get proper disk swapping effect. */ update_md5_checksum(iface); + + /* Update disk path/label vectors */ + disk_image_paths[index] = info->path; + disk_image_labels[index] = retro_cd_base_name; + return true; #endif } @@ -257,14 +266,70 @@ static bool disk_add_image_index(void) log_cb(RETRO_LOG_INFO, "disk_add_image_index called.\n"); CDInterfaces.push_back(NULL); + disk_image_paths.push_back(""); + disk_image_labels.push_back(""); return true; } +static bool disk_set_initial_image(unsigned index, const char *path) +{ + if (string_is_empty(path)) + return false; + + g_initial_disc = index; + g_initial_disc_path = path; + + return true; +} + +static bool disk_get_image_path(unsigned index, char *path, size_t len) +{ + if (len < 1) + return false; + + if ((index < CDInterfaces.size()) && + (index < disk_image_paths.size())) + { + if (!string_is_empty(disk_image_paths[index].c_str())) + { + strlcpy(path, disk_image_paths[index].c_str(), len); + return true; + } + } + + return false; +} + +static bool disk_get_image_label(unsigned index, char *label, size_t len) +{ + if (len < 1) + return false; + + if ((index < CDInterfaces.size()) && + (index < disk_image_labels.size())) + { + if (!string_is_empty(disk_image_labels[index].c_str())) + { + strlcpy(label, disk_image_labels[index].c_str(), len); + return true; + } + } + + return false; +} //------------------------------------------------------------------------------ // Global Functions //------------------------------------------------------------------------------ +/* This has to be 'global', since we need to + * access the current disk index inside + * libretro.cpp */ +unsigned disk_get_image_index(void) +{ + return g_current_disc; +} + static struct retro_disk_control_callback disk_interface = { disk_set_eject_state, @@ -276,13 +341,69 @@ static struct retro_disk_control_callback disk_interface = disk_add_image_index, }; +static struct retro_disk_control_ext_callback disk_interface_ext = +{ + disk_set_eject_state, + disk_get_eject_state, + disk_get_image_index, + disk_set_image_index, + disk_get_num_images, + disk_replace_image_index, + disk_add_image_index, + disk_set_initial_image, + disk_get_image_path, + disk_get_image_label, +}; + +void extract_basename(char *buf, const char *path, size_t size) +{ + const char *base = strrchr(path, '/'); + if (!base) + base = strrchr(path, '\\'); + if (!base) + base = path; + + if (*base == '\\' || *base == '/') + base++; + + strncpy(buf, base, size - 1); + buf[size - 1] = '\0'; + + char *ext = strrchr(buf, '.'); + if (ext) + *ext = '\0'; +} + +void extract_directory(char *buf, const char *path, size_t size) +{ + strncpy(buf, path, size - 1); + buf[size - 1] = '\0'; + + char *base = strrchr(buf, '/'); + if (!base) + base = strrchr(buf, '\\'); + + if (base) + *base = '\0'; + else + buf[0] = '\0'; +} + void disc_init( retro_environment_t environ_cb ) { + unsigned dci_version = 0; + // start closed g_eject_state = false; + g_initial_disc = 0; + g_initial_disc_path.clear(); + // register vtable with environment - environ_cb( RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_interface ); + if (environ_cb(RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION, &dci_version) && (dci_version >= 1)) + environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE, &disk_interface_ext); + else + environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_interface); } static INLINE bool MDFN_isspace(const char c) { return c == ' ' || c == '\f' || c == '\r' || c == '\n' || c == '\t' || c == '\v'; } @@ -427,6 +548,9 @@ void disc_cleanup(void) } CDInterfaces.clear(); + disk_image_paths.clear(); + disk_image_labels.clear(); + g_current_disc = 0; } @@ -589,23 +713,53 @@ bool disc_load_content( MDFNGI* game_interface, const char* content_name, uint8* if ( !strcasecmp( content_ext, ".m3u" ) ) { // multiple discs - std::vector file_list; - ReadM3U(file_list, content_name); - for(unsigned i = 0; i < file_list.size(); i++) + ReadM3U(disk_image_paths, content_name); + for(unsigned i = 0; i < disk_image_paths.size(); i++) { + char image_label[4096]; bool success = true; - log_cb(RETRO_LOG_INFO, "Adding CD: \"%s\".\n", file_list[i].c_str()); - CDIF *image = CDIF_Open(file_list[i].c_str(), image_memcache); + image_label[0] = '\0'; + log_cb(RETRO_LOG_INFO, "Adding CD: \"%s\".\n", disk_image_paths[i].c_str()); + CDIF *image = CDIF_Open(disk_image_paths[i].c_str(), image_memcache); CDInterfaces.push_back(image); + extract_basename( + image_label, + disk_image_paths[i].c_str(), + sizeof(image_label)); + disk_image_labels.push_back(image_label); } } else { // single disc + char image_label[4096]; bool success = true; + + image_label[0] = '\0'; + + disk_image_paths.push_back(content_name); CDIF *image = CDIF_Open(content_name, image_memcache); CDInterfaces.push_back(image); + + extract_basename( + image_label, + content_name, + sizeof(image_label)); + disk_image_labels.push_back(image_label); } + + /* Attempt to set initial disk index */ + if ((g_initial_disc > 0) && + (g_initial_disc + < CDInterfaces.size())) + if (g_initial_disc + < disk_image_paths.size()) + if (string_is_equal( + disk_image_paths[ + g_initial_disc].c_str(), + g_initial_disc_path.c_str())) + g_current_disc = (int) + g_initial_disc; } } catch( std::exception &e ) diff --git a/disc.h b/disc.h index c1631a8..3676f0e 100644 --- a/disc.h +++ b/disc.h @@ -5,8 +5,13 @@ #include "mednafen/git.h" #include "mednafen/mednafen-types.h" +extern void extract_basename(char *buf, const char *path, size_t size); +extern void extract_directory(char *buf, const char *path, size_t size); + // These routines handle disc drive front-end. +extern unsigned disk_get_image_index(void); + void disc_init( retro_environment_t environ_cb ); void disc_cleanup(void); diff --git a/libretro.cpp b/libretro.cpp index f54ca33..66686a6 100644 --- a/libretro.cpp +++ b/libretro.cpp @@ -96,40 +96,6 @@ extern MDFNGI EmulatedSS; MDFN_COLD void CloseGame(void); void Emulate(EmulateSpecStruct* espec_arg); -static void extract_basename(char *buf, const char *path, size_t size) -{ - const char *base = strrchr(path, '/'); - if (!base) - base = strrchr(path, '\\'); - if (!base) - base = path; - - if (*base == '\\' || *base == '/') - base++; - - strncpy(buf, base, size - 1); - buf[size - 1] = '\0'; - - char *ext = strrchr(buf, '.'); - if (ext) - *ext = '\0'; -} - -static void extract_directory(char *buf, const char *path, size_t size) -{ - strncpy(buf, path, size - 1); - buf[size - 1] = '\0'; - - char *base = strrchr(buf, '/'); - if (!base) - base = strrchr(buf, '\\'); - - if (base) - *base = '\0'; - else - buf[0] = '\0'; -} - //forward decls static bool overscan; static double last_sound_rate; @@ -674,7 +640,7 @@ bool retro_load_game(const struct retro_game_info *info) boot = false; - disc_select(0); + disc_select(disk_get_image_index()); frame_count = 0; internal_frame_count = 0;