diff --git a/core.h b/core.h
index 29fc95767d..c2c090b72e 100644
--- a/core.h
+++ b/core.h
@@ -67,8 +67,8 @@ typedef struct rarch_system_info
 
    bool supports_vfs;
 
-   struct retro_disk_control_callback  disk_control_cb;
-   struct retro_location_callback      location_cb;
+   struct retro_disk_control_ext_callback  disk_control_cb;
+   struct retro_location_callback          location_cb;
 
    struct
    {
diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h
index 2b7fc95a76..4ddb6e89ea 100644
--- a/libretro-common/include/libretro.h
+++ b/libretro-common/include/libretro.h
@@ -1117,7 +1117,7 @@ enum retro_mod
                                             * This may be still be done regardless of the core options
                                             * interface version.
                                             *
-                                            * If version is 1 however, core options may instead be set by
+                                            * If version is >= 1 however, core options may instead be set by
                                             * passing an array of retro_core_option_definition structs to
                                             * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
                                             * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
@@ -1132,8 +1132,8 @@ enum retro_mod
                                             * GET_VARIABLE.
                                             * This allows the frontend to present these variables to
                                             * a user dynamically.
-                                            * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
-                                            * returns an API version of 1.
+                                            * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
+                                            * returns an API version of >= 1.
                                             * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
                                             * This should be called the first time as early as
                                             * possible (ideally in retro_set_environment).
@@ -1169,8 +1169,6 @@ enum retro_mod
                                             * i.e. it should be feasible to cycle through options
                                             * without a keyboard.
                                             *
-                                            * First entry should be treated as a default.
-                                            *
                                             * Example entry:
                                             * {
                                             *     "foo_option",
@@ -1196,8 +1194,8 @@ enum retro_mod
                                             * GET_VARIABLE.
                                             * This allows the frontend to present these variables to
                                             * a user dynamically.
-                                            * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
-                                            * returns an API version of 1.
+                                            * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
+                                            * returns an API version of >= 1.
                                             * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
                                             * This should be called the first time as early as
                                             * possible (ideally in retro_set_environment).
@@ -1257,7 +1255,38 @@ enum retro_mod
                                             *
                                             * 'data' points to an unsigned variable
                                             */
-											
+
+#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57
+                                           /* unsigned * --
+                                            * Unsigned value is the API version number of the disk control
+                                            * interface supported by the frontend. If callback return false,
+                                            * API version is assumed to be 0.
+                                            *
+                                            * In legacy code, the disk control interface is defined by passing
+                                            * a struct of type retro_disk_control_callback to
+                                            * RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
+                                            * This may be still be done regardless of the disk control
+                                            * interface version.
+                                            *
+                                            * If version is >= 1 however, the disk control interface may
+                                            * instead be defined by passing a struct of type
+                                            * retro_disk_control_ext_callback to
+                                            * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
+                                            * This allows the core to provide additional information about
+                                            * disk images to the frontend and/or enables extra
+                                            * disk control functionality by the frontend.
+                                            */
+
+#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58
+                                           /* const struct retro_disk_control_ext_callback * --
+                                            * Sets an interface which frontend can use to eject and insert
+                                            * disk images, and also obtain information about individual
+                                            * disk image files registered by the core.
+                                            * This is used for games which consist of multiple images and
+                                            * must be manually swapped out by the user (e.g. PSX, floppy disk
+                                            * based systems).
+                                            */
+
 /* VFS functionality */
 
 /* File paths:
@@ -2307,7 +2336,8 @@ struct retro_keyboard_callback
    retro_keyboard_event_t callback;
 };
 
-/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
+/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE &
+ * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
  * Should be set for implementations which can swap out multiple disk
  * images in runtime.
  *
@@ -2365,6 +2395,53 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
  * with replace_image_index. */
 typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
 
+/* Sets initial image to insert in drive when calling
+ * core_load_game().
+ * Since we cannot pass the initial index when loading
+ * content (this would require a major API change), this
+ * is set by the frontend *before* calling the core's
+ * retro_load_game()/retro_load_game_special() implementation.
+ * A core should therefore cache the index/path values and handle
+ * them inside retro_load_game()/retro_load_game_special().
+ * - If 'index' is invalid (index >= get_num_images()), the
+ *   core should ignore the set value and instead use 0
+ * - 'path' is used purely for error checking - i.e. when
+ *   content is loaded, the core should verify that the
+ *   disk specified by 'index' has the specified file path.
+ *   This is to guard against auto selecting the wrong image
+ *   if (for example) the user should modify an existing M3U
+ *   playlist. We have to let the core handle this because
+ *   set_initial_image() must be called before loading content,
+ *   i.e. the frontend cannot access image paths in advance
+ *   and thus cannot perform the error check itself.
+ *   If set path and content path do not match, the core should
+ *   ignore the set 'index' value and instead use 0
+ * Returns 'false' if index or 'path' are invalid, or core
+ * does not support this functionality
+ */
+typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path);
+
+/* Fetches the path of the specified disk image file.
+ * Returns 'false' if index is invalid (index >= get_num_images())
+ * or path is otherwise unavailable.
+ */
+typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len);
+
+/* Fetches a core-provided 'label' for the specified disk
+ * image file. In the simplest case this may be a file name
+ * (without extension), but for cores with more complex
+ * content requirements information may be provided to
+ * facilitate user disk swapping - for example, a core
+ * running floppy-disk-based content may uniquely label
+ * save disks, data disks, level disks, etc. with names
+ * corresponding to in-game disk change prompts (so the
+ * frontend can provide better user guidance than a 'dumb'
+ * disk index value).
+ * Returns 'false' if index is invalid (index >= get_num_images())
+ * or label is otherwise unavailable.
+ */
+typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len);
+
 struct retro_disk_control_callback
 {
    retro_set_eject_state_t set_eject_state;
@@ -2378,6 +2455,27 @@ struct retro_disk_control_callback
    retro_add_image_index_t add_image_index;
 };
 
+struct retro_disk_control_ext_callback
+{
+   retro_set_eject_state_t set_eject_state;
+   retro_get_eject_state_t get_eject_state;
+
+   retro_get_image_index_t get_image_index;
+   retro_set_image_index_t set_image_index;
+   retro_get_num_images_t  get_num_images;
+
+   retro_replace_image_index_t replace_image_index;
+   retro_add_image_index_t add_image_index;
+
+   /* NOTE: Frontend will only attempt to record/restore
+    * last used disk index if both set_initial_image()
+    * and get_image_path() are implemented */
+   retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */
+
+   retro_get_image_path_t get_image_path;       /* Optional - may be NULL */
+   retro_get_image_label_t get_image_label;     /* Optional - may be NULL */
+};
+
 enum retro_pixel_format
 {
    /* 0RGB1555, native endian.
@@ -2522,8 +2620,20 @@ struct retro_core_option_display
 };
 
 /* Maximum number of values permitted for a core option
- * NOTE: This may be increased on a core-by-core basis
- * if required (doing so has no effect on the frontend) */
+ * > Note: We have to set a maximum value due the limitations
+ *   of the C language - i.e. it is not possible to create an
+ *   array of structs each containing a variable sized array,
+ *   so the retro_core_option_definition values array must
+ *   have a fixed size. The size limit of 128 is a balancing
+ *   act - it needs to be large enough to support all 'sane'
+ *   core options, but setting it too large may impact low memory
+ *   platforms. In practise, if a core option has more than
+ *   128 values then the implementation is likely flawed.
+ *   To quote the above API reference:
+ *      "The number of possible options should be very limited
+ *       i.e. it should be feasible to cycle through options
+ *       without a keyboard."
+ */
 #define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
 
 struct retro_core_option_value
diff --git a/menu/cbs/menu_cbs_get_value.c b/menu/cbs/menu_cbs_get_value.c
index 139f8316f9..fea114f782 100644
--- a/menu/cbs/menu_cbs_get_value.c
+++ b/menu/cbs/menu_cbs_get_value.c
@@ -762,9 +762,9 @@ static void menu_action_setting_disp_set_label_menu_disk_index(
       const char *path,
       char *s2, size_t len2)
 {
-   unsigned images = 0, current                = 0;
-   struct retro_disk_control_callback *control = NULL;
-   rarch_system_info_t *system                 = runloop_get_system_info();
+   unsigned images = 0, current                    = 0;
+   struct retro_disk_control_ext_callback *control = NULL;
+   rarch_system_info_t *system                     = runloop_get_system_info();
 
    if (!system)
       return;
diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c
index 2486a83280..a00f1049c9 100644
--- a/menu/cbs/menu_cbs_ok.c
+++ b/menu/cbs/menu_cbs_ok.c
@@ -6115,8 +6115,8 @@ static int action_ok_disk_cycle_tray_status(const char *path,
    /* Get disk eject state *before* toggling drive status */
    if (sys_info)
    {
-      const struct retro_disk_control_callback *control =
-            (const struct retro_disk_control_callback*)
+      const struct retro_disk_control_ext_callback *control =
+            (const struct retro_disk_control_ext_callback*)
                   &sys_info->disk_control_cb;
 
       if (control)
diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c
index 940ea71a65..c914248e23 100644
--- a/menu/menu_displaylist.c
+++ b/menu/menu_displaylist.c
@@ -3242,17 +3242,17 @@ static unsigned menu_displaylist_parse_content_information(
 static unsigned menu_displaylist_parse_disk_options(
       file_list_t *list)
 {
-   unsigned count                                    = 0;
-   rarch_system_info_t *sys_info                     =
+   unsigned count                                        = 0;
+   rarch_system_info_t *sys_info                         =
          runloop_get_system_info();
-   const struct retro_disk_control_callback *control = NULL;
+   const struct retro_disk_control_ext_callback *control = NULL;
    bool disk_ejected;
 
    /* Sanity Check */
    if (!sys_info)
       return count;
 
-   control = (const struct retro_disk_control_callback*)
+   control = (const struct retro_disk_control_ext_callback*)
          &sys_info->disk_control_cb;
 
    if (!control ||
@@ -5356,8 +5356,8 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
 
             if (sys_info)
             {
-               const struct retro_disk_control_callback *control =
-                     (const struct retro_disk_control_callback*)
+               const struct retro_disk_control_ext_callback *control =
+                     (const struct retro_disk_control_ext_callback*)
                            &sys_info->disk_control_cb;
 
                /* Check that the required disk control interface
@@ -5368,21 +5368,56 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct
                {
                   unsigned num_images    = control->get_num_images();
                   unsigned current_image = control->get_image_index();
+                  unsigned num_digits    = 0;
                   unsigned i;
 
+                  /* If core supports labels, index value string
+                   * should be padded to maximum width (otherwise
+                   * labels will be misaligned/ugly) */
+                  if (control->get_image_label)
+                  {
+                     unsigned digit_counter = num_images;
+                     do
+                     {
+                        num_digits++;
+                        digit_counter = digit_counter / 10;
+                     }
+                     while (digit_counter > 0);
+                  }
+
                   /* Loop through disk images */
                   for (i = 0; i < num_images; i++)
                   {
-                     char current_image_str[256];
+                     char current_image_str[PATH_MAX_LENGTH];
+                     char image_label[PATH_MAX_LENGTH];
 
                      current_image_str[0] = '\0';
+                     image_label[0]       = '\0';
+
+                     /* Get image label, if supported by core */
+                     if (control->get_image_label)
+                        if (!control->get_image_label(i, image_label, sizeof(image_label)))
+                           image_label[0] = '\0';
 
                      /* Get string representation of disk index
                       * > Note that displayed index starts at '1',
                       *   not '0' */
-                     snprintf(
-                           current_image_str, sizeof(current_image_str),
-                           "%u", i + 1);
+                     if (!string_is_empty(image_label))
+                     {
+                        /* Note: 2-space gap is intentional
+                         * (for clarity) */
+                        int n = snprintf(
+                              current_image_str, sizeof(current_image_str),
+                              "%0*u:  %s", num_digits, i + 1, image_label);
+
+                        /* Suppress GCC warnings... */
+                        if ((n < 0) || (n >= PATH_MAX_LENGTH))
+                           n = 0;
+                     }
+                     else
+                        snprintf(
+                              current_image_str, sizeof(current_image_str),
+                              "%0*u", num_digits, i + 1);
 
                      /* Add menu entry */
                      if (menu_entries_append_enum(list,
diff --git a/retroarch.c b/retroarch.c
index b89de3520f..bc98ec6d2c 100644
--- a/retroarch.c
+++ b/retroarch.c
@@ -5231,14 +5231,14 @@ finish:
 static void command_event_disk_control_set_eject(bool new_state, bool print_log)
 {
    char msg[128];
-   bool error                                        = false;
-   const struct retro_disk_control_callback *control = NULL;
-   rarch_system_info_t *info                         = &runloop_system;
+   bool error                                            = false;
+   const struct retro_disk_control_ext_callback *control = NULL;
+   rarch_system_info_t *info                             = &runloop_system;
 
    msg[0] = '\0';
 
    if (info)
-      control = (const struct retro_disk_control_callback*)&info->disk_control_cb;
+      control = (const struct retro_disk_control_ext_callback*)&info->disk_control_cb;
 
    if (!control || !control->get_num_images)
       return;
@@ -5285,14 +5285,14 @@ static void command_event_disk_control_set_index(unsigned idx, bool print_log)
 {
    unsigned num_disks;
    char msg[128];
-   bool error                                        = false;
-   const struct retro_disk_control_callback *control = NULL;
-   rarch_system_info_t *info                         = &runloop_system;
+   bool error                                            = false;
+   const struct retro_disk_control_ext_callback *control = NULL;
+   rarch_system_info_t *info                             = &runloop_system;
 
    msg[0] = '\0';
 
    if (info)
-      control = (const struct retro_disk_control_callback*)&info->disk_control_cb;
+      control = (const struct retro_disk_control_ext_callback*)&info->disk_control_cb;
 
    if (!control || !control->get_num_images)
       return;
@@ -5349,10 +5349,10 @@ static bool command_event_disk_control_append_image(const char *path)
 {
    unsigned new_idx;
    char msg[128];
-   struct retro_game_info info                        = {0};
-   const struct retro_disk_control_callback *control  = NULL;
-   rarch_system_info_t *sysinfo                       = &runloop_system;
-   const char *disk_filename                          = NULL;
+   struct retro_game_info info                           = {0};
+   const struct retro_disk_control_ext_callback *control = NULL;
+   rarch_system_info_t *sysinfo                          = &runloop_system;
+   const char *disk_filename                             = NULL;
 
    msg[0] = '\0';
 
@@ -5365,7 +5365,7 @@ static bool command_event_disk_control_append_image(const char *path)
       return false;
 
    if (sysinfo)
-      control = (const struct retro_disk_control_callback*)
+      control = (const struct retro_disk_control_ext_callback*)
          &sysinfo->disk_control_cb;
 
    if (!control)
@@ -5419,7 +5419,7 @@ static bool command_event_disk_control_append_image(const char *path)
  * Perform disk cycle to previous index action (Core Disk Options).
  **/
 static void command_event_check_disk_prev(
-      const struct retro_disk_control_callback *control, bool print_log)
+      const struct retro_disk_control_ext_callback *control, bool print_log)
 {
    unsigned num_disks    = 0;
    unsigned current      = 0;
@@ -5453,7 +5453,7 @@ static void command_event_check_disk_prev(
  * Perform disk cycle to next index action (Core Disk Options).
  **/
 static void command_event_check_disk_next(
-      const struct retro_disk_control_callback *control, bool print_log)
+      const struct retro_disk_control_ext_callback *control, bool print_log)
 {
    unsigned num_disks        = 0;
    unsigned current          = 0;
@@ -7587,8 +7587,8 @@ TODO: Add a setting for these tweaks */
 
             if (info && info->disk_control_cb.get_num_images)
             {
-               const struct retro_disk_control_callback *control =
-                  (const struct retro_disk_control_callback*)
+               const struct retro_disk_control_ext_callback *control =
+                  (const struct retro_disk_control_ext_callback*)
                   &info->disk_control_cb;
 
                if (control)
@@ -7624,8 +7624,8 @@ TODO: Add a setting for these tweaks */
 
             if (info && info->disk_control_cb.get_num_images)
             {
-               const struct retro_disk_control_callback *control =
-                  (const struct retro_disk_control_callback*)
+               const struct retro_disk_control_ext_callback *control =
+                  (const struct retro_disk_control_ext_callback*)
                   &info->disk_control_cb;
                bool print_log                                    = true;
 
@@ -7654,8 +7654,8 @@ TODO: Add a setting for these tweaks */
 
             if (info && info->disk_control_cb.get_num_images)
             {
-               const struct retro_disk_control_callback *control =
-                  (const struct retro_disk_control_callback*)
+               const struct retro_disk_control_ext_callback *control =
+                  (const struct retro_disk_control_ext_callback*)
                   &info->disk_control_cb;
                bool print_log                                    = true;
 
@@ -7687,8 +7687,8 @@ TODO: Add a setting for these tweaks */
 
             if (info && info->disk_control_cb.get_num_images)
             {
-               const struct retro_disk_control_callback *control =
-                  (const struct retro_disk_control_callback*)
+               const struct retro_disk_control_ext_callback *control =
+                  (const struct retro_disk_control_ext_callback*)
                   &info->disk_control_cb;
 
                if (!control)
@@ -9803,13 +9803,42 @@ static bool rarch_environment_cb(unsigned cmd, void *data)
          break;
       }
 
+      case RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION:
+         /* Current API version is 1 */
+         *(unsigned *)data = 1;
+         break;
+
       case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE:
-         RARCH_LOG("[Environ]: SET_DISK_CONTROL_INTERFACE.\n");
+         {
+            const struct retro_disk_control_callback *control_cb =
+                  (const struct retro_disk_control_callback*)data;
+
+            if (control_cb && system)
+            {
+               RARCH_LOG("[Environ]: SET_DISK_CONTROL_INTERFACE.\n");
+
+               system->disk_control_cb.set_eject_state     = control_cb->set_eject_state;
+               system->disk_control_cb.get_eject_state     = control_cb->get_eject_state;
+               system->disk_control_cb.get_image_index     = control_cb->get_image_index;
+               system->disk_control_cb.set_image_index     = control_cb->set_image_index;
+               system->disk_control_cb.get_num_images      = control_cb->get_num_images;
+               system->disk_control_cb.replace_image_index = control_cb->replace_image_index;
+               system->disk_control_cb.add_image_index     = control_cb->add_image_index;
+
+               system->disk_control_cb.set_initial_image   = NULL;
+               system->disk_control_cb.get_image_path      = NULL;
+               system->disk_control_cb.get_image_label     = NULL;
+            }
+         }
+         break;
+
+      case RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE:
+         RARCH_LOG("[Environ]: SET_DISK_CONTROL_EXT_INTERFACE.\n");
          if (system)
             system->disk_control_cb =
-               *(const struct retro_disk_control_callback*)data;
+               *(const struct retro_disk_control_ext_callback*)data;
          break;
-      
+
       case RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER:
       {
          unsigned *cb = (unsigned*)data;