Skip to content

Commit

Permalink
Merge pull request #10019 from jdgleaver/extended-disk-control
Browse files Browse the repository at this point in the history
Add disk control interface API extension
  • Loading branch information
inactive123 committed Jan 17, 2020
2 parents dbe0705 + a2e1d62 commit 38b486e
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 54 deletions.
4 changes: 2 additions & 2 deletions core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
132 changes: 121 additions & 11 deletions libretro-common/include/libretro.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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).
Expand Down Expand Up @@ -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",
Expand All @@ -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).
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions menu/cbs/menu_cbs_get_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions menu/cbs/menu_cbs_ok.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
55 changes: 45 additions & 10 deletions menu/menu_displaylist.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down

0 comments on commit 38b486e

Please sign in to comment.