mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
Add preliminary disk swapping interface.
Works with Mednafen's disk swapping model.
This commit is contained in:
parent
bd4d97337c
commit
e3dfba2c34
@ -515,6 +515,8 @@ static const bool input_autodetect_enable = true;
|
||||
#define RETRO_LBL_VOLUME_UP "Volume Up"
|
||||
#define RETRO_LBL_VOLUME_DOWN "Volume Down"
|
||||
#define RETRO_LBL_OVERLAY_NEXT "Next Overlay"
|
||||
#define RETRO_LBL_DISK_EJECT_TOGGLE "Disk Eject Toggle"
|
||||
#define RETRO_LBL_DISK_NEXT "Disk Swap Next"
|
||||
|
||||
// Player 1
|
||||
static const struct retro_keybind retro_keybinds_1[] = {
|
||||
@ -583,6 +585,8 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
{ true, RARCH_VOLUME_UP, RETRO_LBL_VOLUME_UP, RETROK_KP_PLUS, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_VOLUME_DOWN, RETRO_LBL_VOLUME_DOWN, RETROK_KP_MINUS,NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_OVERLAY_NEXT, RETRO_LBL_OVERLAY_NEXT, RETROK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_DISK_EJECT_TOGGLE, RETRO_LBL_DISK_EJECT_TOGGLE, RETROK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
{ true, RARCH_DISK_NEXT, RETRO_LBL_DISK_NEXT, RETROK_UNKNOWN, NO_BTN, AXIS_NONE },
|
||||
};
|
||||
|
||||
// Player 2-5
|
||||
|
2
driver.h
2
driver.h
@ -105,6 +105,8 @@ enum // RetroArch specific bind IDs.
|
||||
RARCH_VOLUME_UP,
|
||||
RARCH_VOLUME_DOWN,
|
||||
RARCH_OVERLAY_NEXT,
|
||||
RARCH_DISK_EJECT_TOGGLE,
|
||||
RARCH_DISK_NEXT,
|
||||
|
||||
#ifdef RARCH_CONSOLE
|
||||
RARCH_CHEAT_INPUT,
|
||||
|
@ -485,13 +485,17 @@ static bool environment_cb(unsigned cmd, void *data)
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK:
|
||||
{
|
||||
RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n");
|
||||
const struct retro_keyboard_callback *info = (const struct retro_keyboard_callback*)data;
|
||||
|
||||
g_extern.system.key_event = info->callback;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE:
|
||||
RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n");
|
||||
g_extern.system.disk_control = *(const struct retro_disk_control_callback*)data;
|
||||
break;
|
||||
|
||||
default:
|
||||
RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
|
||||
return false;
|
||||
@ -505,7 +509,6 @@ static void set_environment(void)
|
||||
pretro_set_environment(environment_cb);
|
||||
}
|
||||
|
||||
// Assume SNES as defaults.
|
||||
static void set_environment_defaults(void)
|
||||
{
|
||||
char *save;
|
||||
|
@ -380,6 +380,8 @@ struct global
|
||||
char valid_extensions[PATH_MAX];
|
||||
|
||||
retro_keyboard_event_t key_event;
|
||||
|
||||
struct retro_disk_control_callback disk_control;
|
||||
} system;
|
||||
|
||||
struct
|
||||
|
@ -549,6 +549,8 @@ static const struct str_to_bind_map str_to_bind[] = {
|
||||
{ "volume_up", RARCH_VOLUME_UP },
|
||||
{ "volume_down", RARCH_VOLUME_DOWN },
|
||||
{ "overlay_next", RARCH_OVERLAY_NEXT },
|
||||
{ "disk_eject_toggle", RARCH_DISK_EJECT_TOGGLE },
|
||||
{ "disk_next", RARCH_DISK_NEXT },
|
||||
};
|
||||
|
||||
unsigned input_str_to_bind(const char *str)
|
||||
|
37
libretro.h
37
libretro.h
@ -415,6 +415,12 @@ enum retro_mod
|
||||
#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12
|
||||
// const struct retro_keyboard_callback * --
|
||||
// Sets a callback function used to notify core about keyboard events.
|
||||
//
|
||||
#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13
|
||||
// const struct retro_disk_control_callback * --
|
||||
// Sets an interface which frontend can use to eject and insert disk images.
|
||||
// This is used for games which consist of multiple images and must be manually
|
||||
// swapped out by the user (e.g. PSX).
|
||||
|
||||
|
||||
// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.
|
||||
@ -429,6 +435,37 @@ struct retro_keyboard_callback
|
||||
retro_keyboard_event_t callback;
|
||||
};
|
||||
|
||||
// Callback for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
||||
// Should be set for implementations which can swap out multiple disk images in runtime.
|
||||
// If the implementation can do this automatically, it should strive to do so.
|
||||
// However, there are cases where the user must manually do so.
|
||||
//
|
||||
// Overview: To swap a disk image, eject the disk image with set_eject_state(true).
|
||||
// Set the disk index with set_image_index(index). Insert the disk again with set_eject_state(false).
|
||||
|
||||
// If ejected is true, "ejects" the virtual disk tray. When ejected, the disk image index can be set.
|
||||
typedef bool (*retro_set_eject_state_t)(bool ejected);
|
||||
// Gets current eject state. The initial state is not ejected.
|
||||
typedef bool (*retro_get_eject_state_t)(void);
|
||||
// Gets current disk index. First disk is index 0.
|
||||
// If return value is >= get_num_images(), no disk is currently inserted.
|
||||
typedef unsigned (*retro_get_image_index_t)(void);
|
||||
// Sets image index. Can only be called when disk is ejected.
|
||||
// The implementation supports setting "no disk" by using an index >= get_num_images().
|
||||
typedef bool (*retro_set_image_index_t)(unsigned index);
|
||||
// Gets total number of images which are available to use.
|
||||
typedef unsigned (*retro_get_num_images_t)(void);
|
||||
|
||||
struct retro_disk_control_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;
|
||||
};
|
||||
|
||||
enum retro_pixel_format
|
||||
{
|
||||
// 0RGB1555, native endian. 0 bit must be set to 0.
|
||||
|
72
retroarch.c
72
retroarch.c
@ -2390,6 +2390,77 @@ static void check_cheats(void)
|
||||
old_pressed_toggle = pressed_toggle;
|
||||
}
|
||||
|
||||
static void check_disk(void)
|
||||
{
|
||||
const struct retro_disk_control_callback *control = &g_extern.system.disk_control;
|
||||
if (!control->get_num_images)
|
||||
return;
|
||||
|
||||
static bool old_pressed_eject;
|
||||
static bool old_pressed_next;
|
||||
|
||||
bool pressed_eject = input_key_pressed_func(RARCH_DISK_EJECT_TOGGLE);
|
||||
bool pressed_next = input_key_pressed_func(RARCH_DISK_NEXT);
|
||||
bool error = false;
|
||||
char msg[256];
|
||||
*msg = '\0';
|
||||
|
||||
if (pressed_eject && !old_pressed_eject)
|
||||
{
|
||||
bool new_state = !control->get_eject_state();
|
||||
if (control->set_eject_state(new_state))
|
||||
snprintf(msg, sizeof(msg), "%s virtual disk tray.", new_state ? "Ejected" : "Closed");
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
snprintf(msg, sizeof(msg), "Failed to %s virtual disk tray.", new_state ? "eject" : "close");
|
||||
}
|
||||
}
|
||||
else if (pressed_next && !old_pressed_next)
|
||||
{
|
||||
unsigned num_disks = control->get_num_images();
|
||||
unsigned current = control->get_image_index();
|
||||
if (num_disks && num_disks != UINT_MAX)
|
||||
{
|
||||
// Use "no disk" state when index == num_disks.
|
||||
unsigned next_index = current >= num_disks ? 0 : ((current + 1) % (num_disks + 1));
|
||||
if (control->set_image_index(next_index))
|
||||
{
|
||||
if (next_index < num_disks)
|
||||
snprintf(msg, sizeof(msg), "Setting disk %u of %u in tray.", next_index + 1, num_disks);
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Removed disk from tray.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (next_index < num_disks)
|
||||
snprintf(msg, sizeof(msg), "Failed to set disk %u of %u.", next_index + 1, num_disks);
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Failed to remove disk from tray.");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "Got invalid disk index from libretro.");
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (*msg)
|
||||
{
|
||||
if (error)
|
||||
RARCH_ERR("%s\n", msg);
|
||||
else
|
||||
RARCH_LOG("%s\n", msg);
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 1, 180);
|
||||
}
|
||||
|
||||
old_pressed_eject = pressed_eject;
|
||||
old_pressed_next = pressed_next;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SCREENSHOTS) && !defined(_XBOX)
|
||||
static void check_screenshot(void)
|
||||
{
|
||||
@ -2562,6 +2633,7 @@ static void do_state_checks(void)
|
||||
|
||||
check_shader_dir();
|
||||
check_cheats();
|
||||
check_disk();
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
check_dsp_config();
|
||||
|
@ -380,6 +380,13 @@
|
||||
# Toggles to next overlay. Wraps around.
|
||||
# input_overlay_next =
|
||||
|
||||
# Toggles eject for disks. Used for multiple-disk games.
|
||||
# input_disk_eject_toggle =
|
||||
|
||||
# Cycles through disk images. Use after ejecting.
|
||||
# Complete by toggling eject again.
|
||||
# input_disk_next =
|
||||
|
||||
#### Misc
|
||||
|
||||
# Enable rewinding. This will take a performance hit when playing, so it is disabled by default.
|
||||
|
@ -825,6 +825,8 @@ static const struct bind_map bind_maps[MAX_PLAYERS][RARCH_BIND_LIST_END_NULL] =
|
||||
DECLARE_BIND(volume_up, RARCH_VOLUME_UP),
|
||||
DECLARE_BIND(volume_down, RARCH_VOLUME_DOWN),
|
||||
DECLARE_BIND(overlay_next, RARCH_OVERLAY_NEXT),
|
||||
DECLARE_BIND(disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE),
|
||||
DECLARE_BIND(disk_next, RARCH_DISK_NEXT),
|
||||
},
|
||||
|
||||
{ DECL_PLAYER(2) },
|
||||
|
Loading…
Reference in New Issue
Block a user