Add preliminary disk swapping interface.

Works with Mednafen's disk swapping model.
This commit is contained in:
Themaister 2013-02-21 23:44:07 +01:00
parent bd4d97337c
commit e3dfba2c34
9 changed files with 134 additions and 3 deletions

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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();

View File

@ -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.

View File

@ -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) },