mirror of
https://github.com/libretro/RetroArch
synced 2025-02-07 21:39:54 +00:00
Merge pull request #646 from libretro/controller-info
Controller info libretro API
This commit is contained in:
commit
54961c0dbf
@ -123,41 +123,22 @@ If a ROM is skipped, use a blank ("") command line argument.
|
||||
ROMs must be loaded in an order which depends on the particular subsystem used.
|
||||
See verbose log output to learn how a particular subsystem wants ROMs to be loaded.
|
||||
|
||||
.TP
|
||||
\fB--mouse PORT, -m PORT\fR
|
||||
Connects a mouse into port number PORT. Possible values for PORT are 1 to 8.
|
||||
If set explicitly here, overrides config file for that port.
|
||||
|
||||
.TP
|
||||
\fB--nodevice PORT, -N PORT\fR
|
||||
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.
|
||||
|
75
dynamic.c
75
dynamic.c
@ -1,6 +1,6 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -134,7 +134,7 @@ static dylib_t libretro_get_system_info_lib(const char *path, struct retro_syste
|
||||
if (!lib)
|
||||
return NULL;
|
||||
|
||||
void (*proc)(struct retro_system_info*) =
|
||||
void (*proc)(struct retro_system_info*) =
|
||||
(void (*)(struct retro_system_info*))dylib_proc(lib, "retro_get_system_info");
|
||||
|
||||
if (!proc)
|
||||
@ -222,7 +222,7 @@ static bool find_first_libretro(char *path, size_t size,
|
||||
continue;
|
||||
}
|
||||
|
||||
struct string_list *supported_ext = string_split(info.valid_extensions, "|");
|
||||
struct string_list *supported_ext = string_split(info.valid_extensions, "|");
|
||||
|
||||
if (string_list_find_elem(supported_ext, ext))
|
||||
{
|
||||
@ -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)
|
||||
@ -399,7 +411,7 @@ void init_libretro_sym(bool dummy)
|
||||
function_t sym = dylib_proc(NULL, "retro_init");
|
||||
if (sym)
|
||||
{
|
||||
RARCH_ERR("Serious problem. RetroArch wants to load libretro dyamically, but it is already linked.\n");
|
||||
RARCH_ERR("Serious problem. RetroArch wants to load libretro dyamically, but it is already linked.\n");
|
||||
RARCH_ERR("This could happen if other modules RetroArch depends on link against libretro directly.\n");
|
||||
RARCH_ERR("Proceeding could cause a crash. Aborting ...\n");
|
||||
rarch_fail(1, "init_libretro_sym()");
|
||||
@ -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;
|
||||
@ -470,7 +483,7 @@ function_t dylib_proc(dylib_t lib, const char *proc)
|
||||
#else
|
||||
void *ptr_sym = NULL;
|
||||
if (lib)
|
||||
ptr_sym = dlsym(lib, proc);
|
||||
ptr_sym = dlsym(lib, proc);
|
||||
else
|
||||
{
|
||||
void *handle = dlopen(NULL, RTLD_LAZY);
|
||||
@ -639,7 +652,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY:
|
||||
*(const char**)data = *g_extern.savefile_dir ? g_extern.savefile_dir : NULL;
|
||||
RARCH_LOG("Environ SAVE_DIRECTORY: \"%s\".\n", g_extern.savefile_dir);
|
||||
break;
|
||||
break;
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT:
|
||||
{
|
||||
@ -659,7 +672,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
g_extern.system.pix_fmt = pix_fmt;
|
||||
break;
|
||||
}
|
||||
@ -706,7 +719,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK:
|
||||
{
|
||||
RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n");
|
||||
@ -788,12 +801,12 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
#ifdef HAVE_DYNAMIC
|
||||
*path = g_settings.libretro;
|
||||
#else
|
||||
*path = NULL;
|
||||
*path = NULL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
//FIXME - PS3 audio driver needs to be fixed so that threaded audio works correctly
|
||||
//FIXME - PS3 audio driver needs to be fixed so that threaded audio works correctly
|
||||
//(audio is already on a thread for PS3 audio driver so that's probably the problem)
|
||||
#if defined(HAVE_THREADS) && !defined(__CELLOS_LV2__)
|
||||
case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK:
|
||||
@ -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 (ID: %u)\n", info[i].types[j].desc, 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);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
* Copyright (C) 2012-2014 - Michael Lelli
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -89,7 +89,7 @@ unsigned menu_type_is(unsigned type)
|
||||
unsigned ret = 0;
|
||||
bool type_found;
|
||||
|
||||
type_found =
|
||||
type_found =
|
||||
type == RGUI_SETTINGS ||
|
||||
type == RGUI_SETTINGS_GENERAL_OPTIONS ||
|
||||
type == RGUI_SETTINGS_CORE_OPTIONS ||
|
||||
@ -273,7 +273,7 @@ static int shader_manager_toggle_setting(void *data, unsigned setting, unsigned
|
||||
else if ((dist_shader % 3) == 0 || setting == RGUI_SETTINGS_SHADER_PRESET)
|
||||
{
|
||||
dist_shader /= 3;
|
||||
struct gfx_shader_pass *pass = setting == RGUI_SETTINGS_SHADER_PRESET ?
|
||||
struct gfx_shader_pass *pass = setting == RGUI_SETTINGS_SHADER_PRESET ?
|
||||
&rgui->shader.pass[dist_shader] : NULL;
|
||||
switch (action)
|
||||
{
|
||||
@ -558,7 +558,7 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
|
||||
g_settings.block_sram_overwrite = false;
|
||||
break;
|
||||
case RGUI_SETTINGS_PER_CORE_CONFIG:
|
||||
if (action == RGUI_ACTION_OK || action == RGUI_ACTION_RIGHT
|
||||
if (action == RGUI_ACTION_OK || action == RGUI_ACTION_RIGHT
|
||||
|| action == RGUI_ACTION_LEFT)
|
||||
g_settings.core_specific_config = !g_settings.core_specific_config;
|
||||
else if (action == RGUI_ACTION_START)
|
||||
@ -929,23 +929,30 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
|
||||
break;
|
||||
case RGUI_SETTINGS_BIND_DEVICE_TYPE:
|
||||
{
|
||||
static const unsigned device_types[] = {
|
||||
RETRO_DEVICE_NONE,
|
||||
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;
|
||||
unsigned types = 0;
|
||||
unsigned devices[128];
|
||||
|
||||
devices[types++] = RETRO_DEVICE_NONE;
|
||||
devices[types++] = RETRO_DEVICE_JOYPAD;
|
||||
devices[types++] = RETRO_DEVICE_ANALOG;
|
||||
|
||||
const struct retro_controller_info *desc = port < g_extern.system.num_ports ? &g_extern.system.ports[port] : NULL;
|
||||
if (desc)
|
||||
{
|
||||
for (i = 0; i < desc->num_types; i++)
|
||||
{
|
||||
unsigned id = desc->types[i].id;
|
||||
if (types < ARRAY_SIZE(devices) && id != RETRO_DEVICE_NONE && id != RETRO_DEVICE_JOYPAD && id != RETRO_DEVICE_ANALOG)
|
||||
devices[types++] = id;
|
||||
}
|
||||
}
|
||||
|
||||
current_device = g_settings.input.libretro_device[port];
|
||||
current_index = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(device_types); i++)
|
||||
for (i = 0; i < types; i++)
|
||||
{
|
||||
if (current_device == device_types[i])
|
||||
if (current_device == devices[i])
|
||||
{
|
||||
current_index = i;
|
||||
break;
|
||||
@ -960,12 +967,12 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
|
||||
break;
|
||||
|
||||
case RGUI_ACTION_LEFT:
|
||||
current_device = device_types[(current_index + ARRAY_SIZE(device_types) - 1) % ARRAY_SIZE(device_types)];
|
||||
current_device = devices[(current_index + types - 1) % types];
|
||||
break;
|
||||
|
||||
case RGUI_ACTION_RIGHT:
|
||||
case RGUI_ACTION_OK:
|
||||
current_device = device_types[(current_index + 1) % ARRAY_SIZE(device_types)];
|
||||
current_device = devices[(current_index + 1) % types];
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1075,7 +1082,7 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
|
||||
// FIXME: The array indices here look totally wrong ... Fixed it so it looks kind of sane for now.
|
||||
if (keybind_action != KEYBINDS_ACTION_NONE)
|
||||
driver.input->set_keybinds(driver.input_data, g_settings.input.device[port], port,
|
||||
setting - RGUI_SETTINGS_BIND_BEGIN, keybind_action);
|
||||
setting - RGUI_SETTINGS_BIND_BEGIN, keybind_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1338,17 +1345,17 @@ int menu_set_settings(void *data, unsigned setting, unsigned action)
|
||||
if (g_extern.console.screen.resolutions.current.idx)
|
||||
{
|
||||
g_extern.console.screen.resolutions.current.idx--;
|
||||
g_extern.console.screen.resolutions.current.id =
|
||||
g_extern.console.screen.resolutions.current.id =
|
||||
g_extern.console.screen.resolutions.list[g_extern.console.screen.resolutions.current.idx];
|
||||
}
|
||||
}
|
||||
else if (action == RGUI_ACTION_RIGHT)
|
||||
{
|
||||
if (g_extern.console.screen.resolutions.current.idx + 1 <
|
||||
if (g_extern.console.screen.resolutions.current.idx + 1 <
|
||||
g_extern.console.screen.resolutions.count)
|
||||
{
|
||||
g_extern.console.screen.resolutions.current.idx++;
|
||||
g_extern.console.screen.resolutions.current.id =
|
||||
g_extern.console.screen.resolutions.current.id =
|
||||
g_extern.console.screen.resolutions.list[g_extern.console.screen.resolutions.current.idx];
|
||||
}
|
||||
}
|
||||
@ -2205,18 +2212,23 @@ void menu_set_settings_label(char *type_str, size_t type_str_size, unsigned *w,
|
||||
}
|
||||
case RGUI_SETTINGS_BIND_DEVICE_TYPE:
|
||||
{
|
||||
const char *name;
|
||||
switch (g_settings.input.libretro_device[rgui->current_pad])
|
||||
const struct retro_controller_description *desc = NULL;
|
||||
if (rgui->current_pad < g_extern.system.num_ports)
|
||||
{
|
||||
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;
|
||||
desc = libretro_find_controller_description(&g_extern.system.ports[rgui->current_pad],
|
||||
g_settings.input.libretro_device[rgui->current_pad]);
|
||||
}
|
||||
|
||||
const char *name = desc ? desc->desc : NULL;
|
||||
if (!name) // Find generic name.
|
||||
{
|
||||
switch (g_settings.input.libretro_device[rgui->current_pad])
|
||||
{
|
||||
case RETRO_DEVICE_NONE: name = "None"; break;
|
||||
case RETRO_DEVICE_JOYPAD: name = "Joypad"; break;
|
||||
case RETRO_DEVICE_ANALOG: name = "Joypad w/ Analog"; break;
|
||||
default: name = "Unknown"; break;
|
||||
}
|
||||
}
|
||||
|
||||
strlcpy(type_str, name, type_str_size);
|
||||
|
@ -449,6 +449,9 @@ struct global
|
||||
|
||||
struct retro_subsystem_info *special;
|
||||
unsigned num_special;
|
||||
|
||||
struct retro_controller_info *ports;
|
||||
unsigned num_ports;
|
||||
} system;
|
||||
|
||||
struct
|
||||
|
@ -39,8 +39,7 @@ unsigned retro_api_version(void)
|
||||
|
||||
void retro_set_controller_port_device(unsigned port, unsigned device)
|
||||
{
|
||||
(void)port;
|
||||
(void)device;
|
||||
logging.log(RETRO_LOG_INFO, "Plugging device %u into port %u.\n", device, port);
|
||||
}
|
||||
|
||||
void retro_get_system_info(struct retro_system_info *info)
|
||||
@ -130,6 +129,19 @@ void retro_set_environment(retro_environment_t cb)
|
||||
};
|
||||
|
||||
cb(RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO, (void*)types);
|
||||
|
||||
static const struct retro_controller_description controllers[] = {
|
||||
{ "Dummy Controller #1", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) },
|
||||
{ "Dummy Controller #2", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1) },
|
||||
{ "Augmented Joypad", RETRO_DEVICE_JOYPAD }, // Test overriding generic description in UI.
|
||||
};
|
||||
|
||||
static const struct retro_controller_info ports[] = {
|
||||
{ controllers, 3 },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
|
||||
}
|
||||
|
||||
void retro_set_audio_sample(retro_audio_sample_t cb)
|
||||
@ -261,7 +273,7 @@ static void render_checkered(void)
|
||||
for (unsigned x = 0; x < 320; x++)
|
||||
{
|
||||
unsigned index_x = ((x - x_coord) >> 4) & 1;
|
||||
line[x] = (index_y ^ index_x) ? color_r : color_g;
|
||||
line[x] = (index_y ^ index_x) ? color_r : color_g;
|
||||
}
|
||||
}
|
||||
|
||||
|
84
libretro.h
84
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.
|
||||
@ -548,12 +553,12 @@ enum retro_mod
|
||||
// If this interface is not used, libretro cores should log to stderr as desired.
|
||||
#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28
|
||||
// struct retro_perf_callback * --
|
||||
// Gets an interface for performance counters. This is useful for performance logging in a
|
||||
// Gets an interface for performance counters. This is useful for performance logging in a
|
||||
// cross-platform way and for detecting architecture-specific features, such as SIMD support.
|
||||
#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29
|
||||
// struct retro_location_callback * --
|
||||
// Gets access to the location interface.
|
||||
// The purpose of this interface is to be able to retrieve location-based information from the host device,
|
||||
// The purpose of this interface is to be able to retrieve location-based information from the host device,
|
||||
// such as current latitude / longitude.
|
||||
//
|
||||
#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30
|
||||
@ -611,7 +616,44 @@ 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;
|
||||
|
||||
// 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
|
||||
{
|
||||
@ -827,7 +869,7 @@ typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, uns
|
||||
//
|
||||
// texture_target is the texture target for the GL texture.
|
||||
// These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly more depending on extensions.
|
||||
//
|
||||
//
|
||||
// affine points to a packed 3x3 column-major matrix used to apply an affine transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0))
|
||||
// After transform, normalized texture coord (0, 0) should be bottom-left and (1, 1) should be top-right (or (width, height) for RECTANGLE).
|
||||
//
|
||||
@ -855,7 +897,7 @@ struct retro_camera_callback
|
||||
};
|
||||
|
||||
// Sets the interval of time and/or distance at which to update/poll location-based data.
|
||||
// To ensure compatibility with all location-based implementations, values for both
|
||||
// To ensure compatibility with all location-based implementations, values for both
|
||||
// interval_ms and interval_distance should be provided.
|
||||
// interval_ms is the interval expressed in milliseconds.
|
||||
// interval_distance is the distance interval expressed in meters.
|
||||
@ -883,7 +925,7 @@ struct retro_location_callback
|
||||
retro_location_start_t start;
|
||||
retro_location_stop_t stop;
|
||||
retro_location_get_position_t get_position;
|
||||
retro_location_set_interval_t set_interval;
|
||||
retro_location_set_interval_t set_interval;
|
||||
|
||||
retro_location_lifetime_status_t initialized;
|
||||
retro_location_lifetime_status_t deinitialized;
|
||||
@ -975,7 +1017,7 @@ struct retro_hw_render_callback
|
||||
unsigned version_minor; // Minor version number for core GL context.
|
||||
|
||||
bool cache_context; // If this is true, the frontend will go very far to avoid resetting context in scenarios like toggling fullscreen, etc.
|
||||
// The reset callback might still be called in extreme situations such as if the context is lost beyond recovery.
|
||||
// The reset callback might still be called in extreme situations such as if the context is lost beyond recovery.
|
||||
// For optimal stability, set this to false, and allow context to be reset at any time.
|
||||
retro_hw_context_reset_t context_destroy; // A callback to be called before the context is destroyed. Resources can be deinitialized at this step. This can be set to NULL, in which resources will just be destroyed without any notification.
|
||||
bool debug_context; // Creates a debug context.
|
||||
@ -1208,6 +1250,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.
|
||||
|
145
retroarch.c
145
retroarch.c
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2014 - Daniel De Matteis
|
||||
* Copyright (C) 2012-2014 - Michael Lelli
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -132,7 +132,7 @@ static bool take_screenshot_raw(void)
|
||||
// Negative pitch is needed as screenshot takes bottom-up,
|
||||
// but we use top-down.
|
||||
return screenshot_dump(screenshot_dir,
|
||||
(const uint8_t*)data + (height - 1) * pitch,
|
||||
(const uint8_t*)data + (height - 1) * pitch,
|
||||
width, height, -pitch, false);
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_
|
||||
unsigned owidth = width;
|
||||
unsigned oheight = height;
|
||||
g_extern.filter.psize(&owidth, &oheight);
|
||||
g_extern.filter.prender(g_extern.filter.colormap, g_extern.filter.buffer,
|
||||
g_extern.filter.prender(g_extern.filter.colormap, g_extern.filter.buffer,
|
||||
g_extern.filter.pitch, g_extern.filter.scaler_out, scaler->out_stride, width, height);
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
@ -515,7 +515,7 @@ static inline void input_poll_overlay(void)
|
||||
input_overlay_poll(driver.overlay, &polled_data, x, y);
|
||||
|
||||
driver.overlay_state.buttons |= polled_data.buttons;
|
||||
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(driver.overlay_state.keys); j++)
|
||||
driver.overlay_state.keys[j] |= polled_data.keys[j];
|
||||
|
||||
@ -543,7 +543,7 @@ static inline void input_poll_overlay(void)
|
||||
{
|
||||
uint32_t orig_bits = old_key_state.keys[i];
|
||||
uint32_t new_bits = driver.overlay_state.keys[i];
|
||||
|
||||
|
||||
for (j = 0; j < 32; j++)
|
||||
if ((orig_bits & (1 << j)) != (new_bits & (1 << j)))
|
||||
input_keyboard_event(new_bits & (1 << j), i * 32 + j, 0, key_mod);
|
||||
@ -783,11 +783,8 @@ 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-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.");
|
||||
@ -931,14 +928,10 @@ static void parse_input(int argc, char *argv[])
|
||||
{ "verbose", 0, NULL, 'v' },
|
||||
{ "config", 1, NULL, 'c' },
|
||||
{ "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 +982,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:A:c:U:DN:d:" BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -1006,25 +999,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)
|
||||
@ -1055,18 +1051,6 @@ static void parse_input(int argc, char *argv[])
|
||||
g_extern.verbose = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
port = strtol(optarg, NULL, 0);
|
||||
if (port < 1 || port > MAX_PLAYERS)
|
||||
{
|
||||
RARCH_ERR("Connect mouse to a valid port.\n");
|
||||
print_help();
|
||||
rarch_fail(1, "parse_input()");
|
||||
}
|
||||
g_settings.input.libretro_device[port - 1] = RETRO_DEVICE_MOUSE;
|
||||
g_extern.has_set_libretro_device[port - 1] = true;
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
port = strtol(optarg, NULL, 0);
|
||||
if (port < 1 || port > MAX_PLAYERS)
|
||||
@ -1079,11 +1063,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 +1253,25 @@ 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_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 (ID: %u) to port %u.\n", ident, device, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1707,9 +1672,9 @@ void rarch_init_autosave(void)
|
||||
|
||||
if (pretro_get_memory_size(type) > 0)
|
||||
{
|
||||
g_extern.autosave[i] = autosave_new(path,
|
||||
pretro_get_memory_data(type),
|
||||
pretro_get_memory_size(type),
|
||||
g_extern.autosave[i] = autosave_new(path,
|
||||
pretro_get_memory_data(type),
|
||||
pretro_get_memory_size(type),
|
||||
g_settings.autosave_interval);
|
||||
if (!g_extern.autosave[i])
|
||||
RARCH_WARN("Could not initialize autosave.\n");
|
||||
@ -2270,7 +2235,7 @@ static void check_pause(void)
|
||||
if (driver.audio_data)
|
||||
audio_stop_func();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
RARCH_LOG("Unpaused.\n");
|
||||
if (driver.audio_data)
|
||||
@ -2698,7 +2663,7 @@ void rarch_check_block_hotkey(void)
|
||||
{
|
||||
driver.block_hotkey = driver.block_input;
|
||||
|
||||
// If we haven't bound anything to this,
|
||||
// If we haven't bound anything to this,
|
||||
// always allow hotkeys.
|
||||
static const struct retro_keybind *bind = &g_settings.input.binds[0][RARCH_ENABLE_HOTKEY];
|
||||
if (!driver.block_hotkey && bind->key == RETROK_UNKNOWN && bind->joykey == NO_BTN && bind->joyaxis == AXIS_NONE)
|
||||
@ -2793,7 +2758,7 @@ static void do_state_checks(void)
|
||||
#ifdef HAVE_BSV_MOVIE
|
||||
check_movie();
|
||||
#endif
|
||||
|
||||
|
||||
check_shader_dir();
|
||||
check_cheats();
|
||||
check_disk();
|
||||
@ -2915,7 +2880,7 @@ int rarch_main_init(int argc, char *argv[])
|
||||
int sjlj_ret;
|
||||
if ((sjlj_ret = setjmp(g_extern.error_sjlj_context)) > 0)
|
||||
{
|
||||
RARCH_ERR("Fatal error received in: \"%s\"\n", g_extern.error_string);
|
||||
RARCH_ERR("Fatal error received in: \"%s\"\n", g_extern.error_string);
|
||||
return sjlj_ret;
|
||||
}
|
||||
g_extern.error_in_init = true;
|
||||
@ -2988,9 +2953,9 @@ int rarch_main_init(int argc, char *argv[])
|
||||
if (!g_extern.netplay)
|
||||
#endif
|
||||
rarch_init_rewind();
|
||||
|
||||
|
||||
init_controllers();
|
||||
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
rarch_init_recording();
|
||||
#endif
|
||||
@ -3008,7 +2973,7 @@ int rarch_main_init(int argc, char *argv[])
|
||||
if (g_extern.use_sram)
|
||||
rarch_init_autosave();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
allow_cheats &= !g_extern.netplay;
|
||||
#endif
|
||||
@ -3064,7 +3029,7 @@ static inline void update_frame_time(void)
|
||||
#ifdef HAVE_FFMPEG
|
||||
is_locked_fps |= g_extern.recording;
|
||||
#endif
|
||||
|
||||
|
||||
if (!g_extern.system.frame_time_last || is_locked_fps)
|
||||
delta = g_extern.system.frame_time.reference;
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user