mirror of
https://github.com/CTCaer/RetroArch.git
synced 2025-01-18 08:52:41 +00:00
Begin implementing SET_CONTROLLER_INFO.
This commit is contained in:
parent
063bf83a5f
commit
b4eaf81fed
@ -133,31 +133,17 @@ If set explicitly here, overrides config file for that port.
|
||||
Disconnects an input device from port number PORT. Possible values for PORT are 1 to 8. This may be needed for some odd games to run properly.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--scope, -p\fR
|
||||
Connects a Super Scope into port 2 of an emulated SNES. It is controlled with your mouse.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--justifier, -j\fR
|
||||
Connects a Konami Justifier into port 2 of an emulated SNES. It is controlled with your mouse.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--justifiers, -J\fR
|
||||
Connects two Konami Justifier into port 2 of an emulated SNES. Currently, only player 1 is controlled with the mouse.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--multitap, -4\fR
|
||||
Connects a four-way multitap into an emulated SNES. This allows for up to 5 players.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--dualanalog PORT, -A PORT\fR
|
||||
Connects a DualAnalog controller into port PORT. Possible values are 1 to 8.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--device PORT:ID, -d PORT:ID\fR
|
||||
Connects a generic input device ID into port PORT. Possible values for port are 1 to 8.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
ID is an unsigned number corresponding to the device for a libretro core.
|
||||
|
||||
.TP
|
||||
\fB--record PATH, -r PATH\fR
|
||||
Activates video recording of gameplay into PATH. Using .mkv extension is recommended.
|
||||
|
55
dynamic.c
55
dynamic.c
@ -254,6 +254,18 @@ const struct retro_subsystem_info *libretro_find_subsystem_info(const struct ret
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct retro_controller_description *libretro_find_controller_description(const struct retro_controller_info *info, unsigned id)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < info->num_types; i++)
|
||||
{
|
||||
if (info->types[i].id == id)
|
||||
return &info->types[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void load_symbols(bool is_dummy)
|
||||
{
|
||||
if (is_dummy)
|
||||
@ -434,6 +446,7 @@ void uninit_libretro_sym(void)
|
||||
|
||||
// No longer valid.
|
||||
free(g_extern.system.special);
|
||||
free(g_extern.system.ports);
|
||||
memset(&g_extern.system, 0, sizeof(g_extern.system));
|
||||
#ifdef HAVE_CAMERA
|
||||
g_extern.camera_active = false;
|
||||
@ -907,16 +920,6 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
// Private extensions for internal use, not part of libretro API.
|
||||
case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH:
|
||||
RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n");
|
||||
|
||||
if (path_file_exists((const char*)data))
|
||||
strlcpy(g_settings.libretro, (const char*)data, sizeof(g_settings.libretro));
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY:
|
||||
{
|
||||
const char **dir = (const char**)data;
|
||||
@ -959,6 +962,38 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_CONTROLLER_INFO:
|
||||
{
|
||||
RARCH_LOG("Environ SET_CONTROLLER_INFO.\n");
|
||||
unsigned i, j;
|
||||
const struct retro_controller_info *info = (const struct retro_controller_info*)data;
|
||||
for (i = 0; info[i].types; i++)
|
||||
{
|
||||
RARCH_LOG("Controller port: %u\n", i);
|
||||
for (j = 0; j < info[i].num_types; j++)
|
||||
RARCH_LOG(" %s (ident: %s, ID: %u)\n", info[i].types[j].desc, info[i].types[j].ident, info[i].types[j].id);
|
||||
}
|
||||
|
||||
free(g_extern.system.ports);
|
||||
g_extern.system.ports = (struct retro_controller_info*)calloc(i, sizeof(*g_extern.system.ports));
|
||||
if (!g_extern.system.ports)
|
||||
return false;
|
||||
|
||||
memcpy(g_extern.system.ports, info, i * sizeof(*g_extern.system.ports));
|
||||
g_extern.system.num_ports = i;
|
||||
break;
|
||||
}
|
||||
|
||||
// Private extensions for internal use, not part of libretro API.
|
||||
case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH:
|
||||
RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n");
|
||||
|
||||
if (path_file_exists((const char*)data))
|
||||
strlcpy(g_settings.libretro, (const char*)data, sizeof(g_settings.libretro));
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
case RETRO_ENVIRONMENT_EXEC:
|
||||
case RETRO_ENVIRONMENT_EXEC_ESCAPE:
|
||||
|
||||
|
@ -65,6 +65,7 @@ void libretro_free_system_info(struct retro_system_info *info);
|
||||
void libretro_get_current_core_pathname(char *name, size_t size);
|
||||
|
||||
const struct retro_subsystem_info *libretro_find_subsystem_info(const struct retro_subsystem_info *info, unsigned num_info, const char *ident);
|
||||
const struct retro_controller_description *libretro_find_controller_description(const struct retro_controller_info *info, unsigned id);
|
||||
|
||||
extern void (*pretro_init)(void);
|
||||
extern void (*pretro_deinit)(void);
|
||||
|
@ -934,10 +934,6 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
|
||||
RETRO_DEVICE_JOYPAD,
|
||||
RETRO_DEVICE_ANALOG,
|
||||
RETRO_DEVICE_MOUSE,
|
||||
RETRO_DEVICE_JOYPAD_MULTITAP,
|
||||
RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE,
|
||||
RETRO_DEVICE_LIGHTGUN_JUSTIFIER,
|
||||
RETRO_DEVICE_LIGHTGUN_JUSTIFIERS,
|
||||
};
|
||||
|
||||
unsigned current_device, current_index, i;
|
||||
@ -2211,11 +2207,7 @@ void menu_set_settings_label(char *type_str, size_t type_str_size, unsigned *w,
|
||||
case RETRO_DEVICE_NONE: name = "None"; break;
|
||||
case RETRO_DEVICE_JOYPAD: name = "Joypad"; break;
|
||||
case RETRO_DEVICE_ANALOG: name = "Joypad w/ Analog"; break;
|
||||
case RETRO_DEVICE_JOYPAD_MULTITAP: name = "Multitap"; break;
|
||||
case RETRO_DEVICE_MOUSE: name = "Mouse"; break;
|
||||
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER: name = "Justifier"; break;
|
||||
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS: name = "Justifiers"; break;
|
||||
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE: name = "SuperScope"; break;
|
||||
default: name = "Unknown"; break;
|
||||
}
|
||||
|
||||
|
@ -449,6 +449,9 @@ struct global
|
||||
|
||||
struct retro_subsystem_info *special;
|
||||
unsigned num_special;
|
||||
|
||||
struct retro_controller_info *ports;
|
||||
unsigned num_ports;
|
||||
} system;
|
||||
|
||||
struct
|
||||
|
75
libretro.h
75
libretro.h
@ -46,8 +46,22 @@ extern "C" {
|
||||
// It is not incremented for compatible changes to the API.
|
||||
#define RETRO_API_VERSION 1
|
||||
|
||||
// Libretro's fundamental device abstractions.
|
||||
#define RETRO_DEVICE_MASK 0xff
|
||||
//
|
||||
// Libretros fundamental device abstractions.
|
||||
/////////
|
||||
//
|
||||
// Libretros input system consists of some standardized device types such as a joypad (with/without analog),
|
||||
// mouse, keyboard, lightgun and a pointer. The functionality of these devices are fixed, and individual cores map
|
||||
// their own concept of a controller to libretros abstractions.
|
||||
// This makes it possible for frontends to map the abstract types to a real input device,
|
||||
// and not having to worry about binding input correctly to arbitrary controller layouts.
|
||||
|
||||
|
||||
#define RETRO_DEVICE_TYPE_SHIFT 8
|
||||
#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1)
|
||||
#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base)
|
||||
|
||||
// Input disabled.
|
||||
#define RETRO_DEVICE_NONE 0
|
||||
|
||||
// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller,
|
||||
@ -62,6 +76,7 @@ extern "C" {
|
||||
|
||||
// KEYBOARD device lets one poll for raw key pressed.
|
||||
// It is poll based, so input callback will return with the current pressed state.
|
||||
// For event/text based keyboard input, see RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK.
|
||||
#define RETRO_DEVICE_KEYBOARD 3
|
||||
|
||||
// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse.
|
||||
@ -87,7 +102,7 @@ extern "C" {
|
||||
//
|
||||
// To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
|
||||
// PRESSED returns 1 or 0.
|
||||
// If using a mouse, PRESSED will usually correspond to the left mouse button.
|
||||
// If using a mouse on a desktop, PRESSED will usually correspond to the left mouse button, but this is a frontend decision.
|
||||
// PRESSED will only return 1 if the pointer is inside the game screen.
|
||||
//
|
||||
// For multi-touch, the index variable can be used to successively query more presses.
|
||||
@ -96,16 +111,6 @@ extern "C" {
|
||||
// Eventually _PRESSED will return false for an index. No further presses are registered at this point.
|
||||
#define RETRO_DEVICE_POINTER 6
|
||||
|
||||
// These device types are specializations of the base types above.
|
||||
// They should only be used in retro_set_controller_type() to inform libretro implementations
|
||||
// about use of a very specific device type.
|
||||
//
|
||||
// In input state callback, however, only the base type should be used in the 'device' field.
|
||||
#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD)
|
||||
#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN)
|
||||
#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN)
|
||||
#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN)
|
||||
|
||||
// Buttons for the RetroPad (JOYPAD).
|
||||
// The placement of these is equivalent to placements on the Super Nintendo controller.
|
||||
// L2/R2/L3/R3 buttons correspond to the PS1 DualShock.
|
||||
@ -611,7 +616,47 @@ enum retro_mod
|
||||
// and this environment call allows a libretro core to expose which subsystems are supported for use with retro_load_game_special().
|
||||
// A core passes an array of retro_game_special_info which is terminated with a zeroed out retro_game_special_info struct.
|
||||
//
|
||||
// If a core wants to use this functionality, SET_SPECIAL_GAME_TYPES **MUST** be called from within retro_set_environment().
|
||||
// If a core wants to use this functionality, SET_SUBSYSTEM_INFO **MUST** be called from within retro_set_environment().
|
||||
//
|
||||
#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35
|
||||
// const struct retro_controller_info * --
|
||||
// This environment call lets a libretro core tell the frontend which
|
||||
// controller types are recognized in calls to retro_set_controller_port_device().
|
||||
//
|
||||
// Some emulators such as Super Nintendo
|
||||
// support multiple lightgun types which must be specifically selected from.
|
||||
// It is therefore sometimes necessary for a frontend to be able to tell
|
||||
// the core about a special kind of input device which is not covered by the
|
||||
// libretro input API.
|
||||
//
|
||||
// In order for a frontend to understand the workings of an input device,
|
||||
// it must be a specialized type
|
||||
// of the generic device types already defined in the libretro API.
|
||||
//
|
||||
// Which devices are supported can vary per input port.
|
||||
// The core must pass an array of const struct retro_controller_info which is terminated with
|
||||
// a blanked out struct. Each element of the struct corresponds to an ascending port index to retro_set_controller_port_device().
|
||||
// Even if special device types are set in the libretro core, libretro should only poll input based on the base input device types.
|
||||
|
||||
struct retro_controller_description
|
||||
{
|
||||
// Human-readable description of the controller. Even if using a generic input device type, this can be
|
||||
// set to the particular device type the core uses.
|
||||
const char *desc;
|
||||
|
||||
// A computer-friendly short string identifier ([a-z]).
|
||||
const char *ident;
|
||||
|
||||
// Device type passed to retro_set_controller_port_device(). If the device type is a sub-class of a generic input device type,
|
||||
// use the RETRO_DEVICE_SUBCLASS macro to create an ID. E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1).
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
struct retro_controller_info
|
||||
{
|
||||
const struct retro_controller_description *types;
|
||||
unsigned num_types;
|
||||
};
|
||||
|
||||
struct retro_subsystem_memory_info
|
||||
{
|
||||
@ -1208,6 +1253,8 @@ void retro_get_system_info(struct retro_system_info *info);
|
||||
void retro_get_system_av_info(struct retro_system_av_info *info);
|
||||
|
||||
// Sets device to be used for player 'port'.
|
||||
// By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all available ports.
|
||||
// Setting a particular device type is not a guarantee that libretro cores will only poll input based on that particular device type. It is only a hint to the libretro core when a core cannot automatically detect the appropriate input device type on its own. It is also relevant when a core can change its behavior depending on device type.
|
||||
void retro_set_controller_port_device(unsigned port, unsigned device);
|
||||
|
||||
// Resets the current game.
|
||||
|
102
retroarch.c
102
retroarch.c
@ -783,11 +783,9 @@ static void print_help(void)
|
||||
|
||||
printf("\t-N/--nodevice: Disconnects controller device connected to port (1 to %d).\n", MAX_PLAYERS);
|
||||
printf("\t-A/--dualanalog: Connect a DualAnalog controller to port (1 to %d).\n", MAX_PLAYERS);
|
||||
printf("\t-m/--mouse: Connect a mouse into port of the device (1 to %d).\n", MAX_PLAYERS);
|
||||
puts("\t-p/--scope: Connect a virtual SuperScope into port 2. (SNES specific).");
|
||||
puts("\t-j/--justifier: Connect a virtual Konami Justifier into port 2. (SNES specific).");
|
||||
puts("\t-J/--justifiers: Daisy chain two virtual Konami Justifiers into port 2. (SNES specific).");
|
||||
puts("\t-4/--multitap: Connect a SNES multitap to port 2. (SNES specific).");
|
||||
printf("\t-m/--mouse: Connect a mouse into controller port (1 to %d).\n", MAX_PLAYERS);
|
||||
printf("\t-d/--device: Connect a generic device into port of the device (1 to %d).\n", MAX_PLAYERS);
|
||||
puts("\t\tFormat is port:ID, where ID is an unsigned number corresponding to the particular device.\n");
|
||||
|
||||
#ifdef HAVE_BSV_MOVIE
|
||||
puts("\t-P/--bsvplay: Playback a BSV movie file.");
|
||||
@ -933,12 +931,9 @@ static void parse_input(int argc, char *argv[])
|
||||
{ "appendconfig", 1, &val, 'C' },
|
||||
{ "mouse", 1, NULL, 'm' },
|
||||
{ "nodevice", 1, NULL, 'N' },
|
||||
{ "scope", 0, NULL, 'p' },
|
||||
{ "justifier", 0, NULL, 'j' },
|
||||
{ "justifiers", 0, NULL, 'J' },
|
||||
{ "dualanalog", 1, NULL, 'A' },
|
||||
{ "device", 1, NULL, 'd' },
|
||||
{ "savestate", 1, NULL, 'S' },
|
||||
{ "multitap", 0, NULL, '4' },
|
||||
#ifdef HAVE_BSV_MOVIE
|
||||
{ "bsvplay", 1, NULL, 'P' },
|
||||
{ "bsvrecord", 1, NULL, 'R' },
|
||||
@ -989,7 +984,7 @@ static void parse_input(int argc, char *argv[])
|
||||
#define BSV_MOVIE_ARG
|
||||
#endif
|
||||
|
||||
const char *optstring = "hs:fvS:m:p4jJA:c:U:DN:" BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG;
|
||||
const char *optstring = "hs:fvS:m:A:c:U:DN:d:" BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -1006,25 +1001,28 @@ static void parse_input(int argc, char *argv[])
|
||||
print_help();
|
||||
exit(0);
|
||||
|
||||
case '4':
|
||||
g_settings.input.libretro_device[1] = RETRO_DEVICE_JOYPAD_MULTITAP;
|
||||
g_extern.has_set_libretro_device[1] = true;
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
g_settings.input.libretro_device[1] = RETRO_DEVICE_LIGHTGUN_JUSTIFIER;
|
||||
g_extern.has_set_libretro_device[1] = true;
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
g_settings.input.libretro_device[1] = RETRO_DEVICE_LIGHTGUN_JUSTIFIERS;
|
||||
g_extern.has_set_libretro_device[1] = true;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
strlcpy(g_extern.subsystem, optarg, sizeof(g_extern.subsystem));
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
{
|
||||
struct string_list *list = string_split(optarg, ":");
|
||||
port = (list && list->size == 2) ? strtol(list->elems[0].data, NULL, 0) : 0;
|
||||
unsigned id = (list && list->size == 2) ? strtoul(list->elems[1].data, NULL, 0) : 0;
|
||||
string_list_free(list);
|
||||
|
||||
if (port < 1 || port > MAX_PLAYERS)
|
||||
{
|
||||
RARCH_ERR("Connect device to a valid port.\n");
|
||||
print_help();
|
||||
rarch_fail(1, "parse_input()");
|
||||
}
|
||||
g_settings.input.libretro_device[port - 1] = id;
|
||||
g_extern.has_set_libretro_device[port - 1] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'A':
|
||||
port = strtol(optarg, NULL, 0);
|
||||
if (port < 1 || port > MAX_PLAYERS)
|
||||
@ -1079,11 +1077,6 @@ static void parse_input(int argc, char *argv[])
|
||||
g_extern.has_set_libretro_device[port - 1] = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
g_settings.input.libretro_device[1] = RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE;
|
||||
g_extern.has_set_libretro_device[1] = true;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
strlcpy(g_extern.config_path, optarg, sizeof(g_extern.config_path));
|
||||
break;
|
||||
@ -1274,39 +1267,26 @@ static void init_controllers(void)
|
||||
|
||||
pretro_set_controller_port_device(i, device);
|
||||
|
||||
switch (device)
|
||||
const struct retro_controller_description *desc = NULL;
|
||||
if (i < g_extern.system.num_ports)
|
||||
desc = libretro_find_controller_description(&g_extern.system.ports[i], device);
|
||||
|
||||
const char *ident = desc ? desc->desc : NULL;
|
||||
|
||||
if (!ident)
|
||||
{
|
||||
case RETRO_DEVICE_NONE:
|
||||
RARCH_LOG("Disconnecting device from port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_ANALOG:
|
||||
RARCH_LOG("Connecting dualanalog to port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
RARCH_LOG("Connecting mouse to port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER:
|
||||
RARCH_LOG("Connecting Justifier to port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS:
|
||||
RARCH_LOG("Connecting Justifiers to port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_JOYPAD_MULTITAP:
|
||||
RARCH_LOG("Connecting Multitap to port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE:
|
||||
RARCH_LOG("Connecting scope to port %u.\n", i + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
switch (device)
|
||||
{
|
||||
case RETRO_DEVICE_MOUSE: ident = "mouse"; break;
|
||||
case RETRO_DEVICE_ANALOG: ident = "analog"; break;
|
||||
default: ident = "Unknown"; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (device == RETRO_DEVICE_NONE)
|
||||
RARCH_LOG("Disconnecting device from port %u.\n", i + 1);
|
||||
else
|
||||
RARCH_LOG("Connecting %s to port %u.\n", ident, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user