Reimplement multitap/controller settings - now implements

RETRO_SET_CONTROLLER_INFO
This commit is contained in:
twinaphex 2014-05-02 03:13:37 +02:00
parent 97d0e56650
commit f932017845
2 changed files with 277 additions and 98 deletions

View File

@ -13,6 +13,17 @@
#include <xtl.h> #include <xtl.h>
#endif #endif
#define RETRO_DEVICE_MDPAD_3B RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0)
#define RETRO_DEVICE_MDPAD_6B RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1)
#define RETRO_DEVICE_PAD_AUTO RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 2)
#define RETRO_DEVICE_PORT_NONE RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 3)
#define RETRO_DEVICE_SMSPAD_2B RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 4)
#define RETRO_DEVICE_MDPAD_3B_WAYPLAY RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 5)
#define RETRO_DEVICE_MDPAD_6B_WAYPLAY RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 6)
#define RETRO_DEVICE_MDPAD_3B_TEAMPLAYER RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 7)
#define RETRO_DEVICE_MDPAD_6B_TEAMPLAYER RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 8)
#define RETRO_DEVICE_SMSPAD_4P RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 9)
#include "shared.h" #include "shared.h"
#include "libretro.h" #include "libretro.h"
#include "state.h" #include "state.h"
@ -713,50 +724,6 @@ static void check_variables(void)
} }
} }
static void configure_controls(void)
{
int i;
struct retro_variable var;
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_GAMEPAD;
var.key = "padtype";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
if (!strcmp(var.value, "6-buttons"))
for(i = 0; i < MAX_INPUTS; i++)
config.input[i].padtype = DEVICE_PAD6B;
else if (!strcmp(var.value, "3-buttons"))
for(i = 0; i < MAX_INPUTS; i++)
config.input[i].padtype = DEVICE_PAD3B;
else if (!strcmp(var.value, "2-buttons"))
for(i = 0; i < MAX_INPUTS; i++)
config.input[i].padtype = DEVICE_PAD2B;
else
for(i = 0; i < MAX_INPUTS; i++)
config.input[i].padtype = DEVICE_PAD2B | DEVICE_PAD3B | DEVICE_PAD6B;
var.key = "multitap";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
if (!strcmp(var.value, "4-wayplay"))
input.system[0] = input.system[1] = SYSTEM_WAYPLAY;
else if (!strcmp(var.value, "teamplayer 1"))
input.system[0] = SYSTEM_TEAMPLAYER;
else if (!strcmp(var.value, "teamplayer 2"))
input.system[1] = SYSTEM_TEAMPLAYER;
else if (!strcmp(var.value, "teamplayer 1&2"))
input.system[0] = input.system[1] = SYSTEM_TEAMPLAYER;
else if (!strcmp(var.value, "master system 4p"))
input.system[0] = SYSTEM_MS4PLAY;
var.key = "portb";
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
if (!strcmp(var.value, "disabled"))
input.system[1] = NO_SYSTEM;
input_init();
}
/************************************ /************************************
* libretro implementation * libretro implementation
************************************/ ************************************/
@ -770,9 +737,6 @@ void retro_set_environment(retro_environment_t cb)
{ "force_dtack", "System lockups; enabled|disabled" }, { "force_dtack", "System lockups; enabled|disabled" },
{ "addr_error", "68k address error; enabled|disabled" }, { "addr_error", "68k address error; enabled|disabled" },
{ "lock_on", "Cartridge lock-on; disabled|game genie|action replay (pro)|sonic & knuckles" }, { "lock_on", "Cartridge lock-on; disabled|game genie|action replay (pro)|sonic & knuckles" },
{ "padtype", "Gamepad type; auto|6-buttons|3-buttons|2-buttons" },
{ "multitap", "Multi Tap; disabled|4-wayplay|teamplayer (port 1)|teamplayer (port 2)|teamplayer (both)|master system 4p" },
{ "portb", "Control Port 2; enabled|disabled" },
{ "ym2413", "Master System FM; auto|disabled|enabled" }, { "ym2413", "Master System FM; auto|disabled|enabled" },
{ "dac_bits", "YM2612 DAC quantization; disabled|enabled" }, { "dac_bits", "YM2612 DAC quantization; disabled|enabled" },
{ "blargg_ntsc_filter", "Blargg NTSC filter; disabled|monochrome|composite|svideo|rgb" }, { "blargg_ntsc_filter", "Blargg NTSC filter; disabled|monochrome|composite|svideo|rgb" },
@ -782,8 +746,43 @@ void retro_set_environment(retro_environment_t cb)
{ NULL, NULL }, { NULL, NULL },
}; };
static const struct retro_controller_description port_1[] = {
{ "MD Joypad 3 Button", RETRO_DEVICE_MDPAD_3B },
{ "MD Joypad 6 Button", RETRO_DEVICE_MDPAD_6B },
{ "Joypad Auto", RETRO_DEVICE_PAD_AUTO },
{ "Joypad Port Empty", RETRO_DEVICE_PORT_NONE },
{ "SMS Joypad 2 Button", RETRO_DEVICE_SMSPAD_2B },
{ "MD Joypad 3 Button + WayPlay", RETRO_DEVICE_MDPAD_3B_WAYPLAY },
{ "MD Joypad 6 Button + WayPlay", RETRO_DEVICE_MDPAD_6B_WAYPLAY },
{ "MD Joypad 3 Button + Teamplayer", RETRO_DEVICE_MDPAD_3B_TEAMPLAYER },
{ "MD Joypad 6 Button + Teamplayer", RETRO_DEVICE_MDPAD_6B_TEAMPLAYER },
{ "SMS Joypad 4 Player", RETRO_DEVICE_SMSPAD_4P },
{ "RetroPad", RETRO_DEVICE_JOYPAD },
};
static const struct retro_controller_description port_2[] = {
{ "MD Joypad 3 Button", RETRO_DEVICE_MDPAD_3B },
{ "MD Joypad 6 Button", RETRO_DEVICE_MDPAD_6B },
{ "Joypad Auto", RETRO_DEVICE_PAD_AUTO },
{ "Joypad Port Empty", RETRO_DEVICE_PORT_NONE },
{ "SMS Joypad 2 Button", RETRO_DEVICE_SMSPAD_2B },
{ "MD Joypad 3 Button + WayPlay", RETRO_DEVICE_MDPAD_3B_WAYPLAY },
{ "MD Joypad 6 Button + WayPlay", RETRO_DEVICE_MDPAD_6B_WAYPLAY },
{ "MD Joypad 3 Button + Teamplayer", RETRO_DEVICE_MDPAD_3B_TEAMPLAYER },
{ "MD Joypad 6 Button + Teamplayer", RETRO_DEVICE_MDPAD_6B_TEAMPLAYER },
{ "RetroPad", RETRO_DEVICE_JOYPAD },
};
static const struct retro_controller_info ports[] = {
{ port_1, 11 },
{ port_2, 10 },
{ 0 },
};
environ_cb = cb; environ_cb = cb;
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
} }
void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; }
@ -814,8 +813,63 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
void retro_set_controller_port_device(unsigned port, unsigned device) void retro_set_controller_port_device(unsigned port, unsigned device)
{ {
(void)port; switch(device)
(void)device; {
case RETRO_DEVICE_JOYPAD:
case RETRO_DEVICE_MDPAD_3B:
default:
config.input[port].padtype = DEVICE_PAD3B;
input.dev[port] = DEVICE_PAD3B;
input.system[port] = SYSTEM_GAMEPAD;
break;
case RETRO_DEVICE_MDPAD_6B:
config.input[port].padtype = DEVICE_PAD6B;
input.dev[port] = DEVICE_PAD6B;
input.system[port] = SYSTEM_GAMEPAD;
break;
case RETRO_DEVICE_PAD_AUTO:
config.input[port].padtype = DEVICE_PAD2B | DEVICE_PAD6B | DEVICE_PAD3B;
input.dev[port] = DEVICE_PAD2B | DEVICE_PAD6B | DEVICE_PAD3B;
input.system[port] = SYSTEM_GAMEPAD;
break;
case RETRO_DEVICE_PORT_NONE:
config.input[port].padtype = 0;
input.dev[port] = 0;
input.system[port] = NO_SYSTEM;
break;
case RETRO_DEVICE_SMSPAD_2B:
config.input[port].padtype = DEVICE_PAD2B;
input.dev[port] = DEVICE_PAD2B;
input.system[port] = SYSTEM_GAMEPAD;
break;
case RETRO_DEVICE_MDPAD_3B_WAYPLAY:
config.input[port].padtype = DEVICE_PAD3B;
input.dev[port] = DEVICE_PAD3B;
input.system[0] = input.system[1] = SYSTEM_WAYPLAY;
break;
case RETRO_DEVICE_MDPAD_6B_WAYPLAY:
config.input[port].padtype = DEVICE_PAD6B;
input.dev[port] = DEVICE_PAD6B;
input.system[0] = input.system[1] = SYSTEM_WAYPLAY;
break;
case RETRO_DEVICE_MDPAD_3B_TEAMPLAYER:
config.input[port].padtype = DEVICE_PAD3B;
input.dev[port] = DEVICE_PAD3B;
input.system[port] = SYSTEM_TEAMPLAYER;
break;
case RETRO_DEVICE_MDPAD_6B_TEAMPLAYER:
config.input[port].padtype = DEVICE_PAD6B;
input.dev[port] = DEVICE_PAD6B;
input.system[port] = SYSTEM_TEAMPLAYER;
break;
case RETRO_DEVICE_SMSPAD_4P:
config.input[port].padtype = DEVICE_PAD2B;
input.dev[port] = DEVICE_PAD2B;
input.system[0] = SYSTEM_MS4PLAY;
break;
}
input_init();
} }
size_t retro_serialize_size(void) { return STATE_SIZE; } size_t retro_serialize_size(void) { return STATE_SIZE; }
@ -898,7 +952,8 @@ bool retro_load_game(const struct retro_game_info *info)
if (!load_rom((char *)info->path)) if (!load_rom((char *)info->path))
return false; return false;
configure_controls(); for (i = 0; i < 2; i++)
retro_set_controller_port_device(i, input.dev[i]);
audio_init(44100, vdp_pal ? pal_fps : ntsc_fps); audio_init(44100, vdp_pal ? pal_fps : ntsc_fps);
system_init(); system_init();
@ -987,8 +1042,11 @@ void retro_init(void)
void retro_deinit(void) void retro_deinit(void)
{ {
audio_shutdown(); audio_shutdown();
free(md_ntsc); if (md_ntsc)
free(sms_ntsc); free(md_ntsc);
if (sms_ntsc)
free(sms_ntsc);
} }
void retro_reset(void) { system_reset(); } void retro_reset(void) { system_reset(); }
@ -1020,10 +1078,7 @@ void retro_run(void)
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated); environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated);
if (updated) if (updated)
{
check_variables(); check_variables();
configure_controls();
}
} }
#undef CHUNKSIZE #undef CHUNKSIZE

View File

@ -46,8 +46,22 @@ extern "C" {
// It is not incremented for compatible changes to the API. // It is not incremented for compatible changes to the API.
#define RETRO_API_VERSION 1 #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 #define RETRO_DEVICE_NONE 0
// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller, // 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. // KEYBOARD device lets one poll for raw key pressed.
// It is poll based, so input callback will return with the current pressed state. // 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 #define RETRO_DEVICE_KEYBOARD 3
// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse. // 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), // To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
// PRESSED returns 1 or 0. // 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. // 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. // 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. // Eventually _PRESSED will return false for an index. No further presses are registered at this point.
#define RETRO_DEVICE_POINTER 6 #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). // Buttons for the RetroPad (JOYPAD).
// The placement of these is equivalent to placements on the Super Nintendo controller. // The placement of these is equivalent to placements on the Super Nintendo controller.
// L2/R2/L3/R3 buttons correspond to the PS1 DualShock. // L2/R2/L3/R3 buttons correspond to the PS1 DualShock.
@ -133,10 +138,13 @@ extern "C" {
#define RETRO_DEVICE_ID_ANALOG_Y 1 #define RETRO_DEVICE_ID_ANALOG_Y 1
// Id values for MOUSE. // Id values for MOUSE.
#define RETRO_DEVICE_ID_MOUSE_X 0 #define RETRO_DEVICE_ID_MOUSE_X 0
#define RETRO_DEVICE_ID_MOUSE_Y 1 #define RETRO_DEVICE_ID_MOUSE_Y 1
#define RETRO_DEVICE_ID_MOUSE_LEFT 2 #define RETRO_DEVICE_ID_MOUSE_LEFT 2
#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 #define RETRO_DEVICE_ID_MOUSE_RIGHT 3
#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4
#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5
#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6
// Id values for LIGHTGUN types. // Id values for LIGHTGUN types.
#define RETRO_DEVICE_ID_LIGHTGUN_X 0 #define RETRO_DEVICE_ID_LIGHTGUN_X 0
@ -162,7 +170,7 @@ extern "C" {
// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery. // Regular save ram. This ram is usually found on a game cartridge, backed up by a battery.
// If save game data is too complex for a single memory buffer, // If save game data is too complex for a single memory buffer,
// the SYSTEM_DIRECTORY environment callback can be used. // the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment callback can be used.
#define RETRO_MEMORY_SAVE_RAM 0 #define RETRO_MEMORY_SAVE_RAM 0
// Some games have a built-in clock to keep track of time. // Some games have a built-in clock to keep track of time.
@ -175,21 +183,6 @@ extern "C" {
// Video ram lets a frontend peek into a game systems video RAM (VRAM). // Video ram lets a frontend peek into a game systems video RAM (VRAM).
#define RETRO_MEMORY_VIDEO_RAM 3 #define RETRO_MEMORY_VIDEO_RAM 3
// Special memory types.
#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM)
#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM)
#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM)
#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM)
#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM)
#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC)
// Special game types passed into retro_load_game_special().
// Only used when multiple ROMs are required.
#define RETRO_GAME_TYPE_BSX 0x101
#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102
#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103
#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104
// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. // Keysyms used for ID in input state callback when polling RETRO_KEYBOARD.
enum retro_key enum retro_key
{ {
@ -607,6 +600,116 @@ enum retro_mod
// This call is not a free pass for not trying to provide correct values in retro_get_system_av_info(). // This call is not a free pass for not trying to provide correct values in retro_get_system_av_info().
// //
// If this returns false, the frontend does not acknowledge a changed av_info struct. // If this returns false, the frontend does not acknowledge a changed av_info struct.
#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33
// const struct retro_get_proc_address_interface * --
// Allows a libretro core to announce support for the get_proc_address() interface.
// This interface allows for a standard way to extend libretro where use of environment calls are too indirect,
// e.g. for cases where the frontend wants to call directly into the core.
//
// If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK **MUST** be called from within retro_set_environment().
//
#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34
// const struct retro_subsystem_info * --
// This environment call introduces the concept of libretro "subsystems".
// A subsystem is a variant of a libretro core which supports different kinds of games.
// The purpose of this is to support e.g. emulators which might have special needs, e.g. Super Nintendos Super GameBoy, Sufami Turbo.
// It can also be used to pick among subsystems in an explicit way if the libretro implementation is a multi-system emulator itself.
//
// Loading a game via a subsystem is done with retro_load_game_special(),
// 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_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
{
const char *extension; // The extension associated with a memory type, e.g. "psram".
unsigned type; // The memory type for retro_get_memory(). This should be at least 0x100 to avoid conflict with standardized libretro memory types.
};
struct retro_subsystem_rom_info
{
const char *desc; // Describes what the ROM is (SGB bios, GB rom, etc).
const char *valid_extensions; // Same definition as retro_get_system_info().
bool need_fullpath; // Same definition as retro_get_system_info().
bool block_extract; // Same definition as retro_get_system_info().
bool required; // This is set if the ROM is required to load a game. If this is set to false, a zeroed-out retro_game_info can be passed.
// ROMs can have multiple associated persistent memory types (retro_get_memory()).
const struct retro_subsystem_memory_info *memory;
unsigned num_memory;
};
struct retro_subsystem_info
{
const char *desc; // Human-readable string of the subsystem type, e.g. "Super GameBoy"
// A computer friendly short string identifier for the subsystem type.
// This name must be [a-z].
// E.g. if desc is "Super GameBoy", this can be "sgb".
// This identifier can be used for command-line interfaces, etc.
const char *ident;
// Infos for each ROM. The first entry is assumed to be the "most significant" ROM for frontend purposes.
// E.g. with Super GameBoy, the first ROM should be the GameBoy ROM, as it is the most "significant" ROM to a user.
// If a frontend creates new file paths based on the ROM used (e.g. savestates), it should use the path for the first ROM to do so.
const struct retro_subsystem_rom_info *roms;
unsigned num_roms; // Number of ROMs associated with a subsystem.
unsigned id; // The type passed to retro_load_game_special().
};
typedef void (*retro_proc_address_t)(void);
// libretro API extension functions:
// (None here so far).
//////
// Get a symbol from a libretro core.
// Cores should only return symbols which are actual extensions to the libretro API.
// Frontends should not use this to obtain symbols to standard libretro entry points (static linking or dlsym).
// The symbol name must be equal to the function name, e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo".
// The returned function pointer must be cast to the corresponding type.
typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym);
struct retro_get_proc_address_interface
{
retro_get_proc_address_t get_proc_address;
};
enum retro_log_level enum retro_log_level
{ {
@ -643,6 +746,7 @@ struct retro_log_callback
#define RETRO_SIMD_SSE42 (1 << 11) #define RETRO_SIMD_SSE42 (1 << 11)
#define RETRO_SIMD_AVX2 (1 << 12) #define RETRO_SIMD_AVX2 (1 << 12)
#define RETRO_SIMD_VFPU (1 << 13) #define RETRO_SIMD_VFPU (1 << 13)
#define RETRO_SIMD_PS (1 << 14)
typedef uint64_t retro_perf_tick_t; typedef uint64_t retro_perf_tick_t;
typedef int64_t retro_time_t; typedef int64_t retro_time_t;
@ -889,7 +993,6 @@ typedef void (*retro_hw_context_reset_t)(void);
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
// Get a symbol from HW context. // Get a symbol from HW context.
typedef void (*retro_proc_address_t)(void);
typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
enum retro_hw_context_type enum retro_hw_context_type
@ -906,7 +1009,17 @@ enum retro_hw_context_type
struct retro_hw_render_callback struct retro_hw_render_callback
{ {
enum retro_hw_context_type context_type; // Which API to use. Set by libretro core. enum retro_hw_context_type context_type; // Which API to use. Set by libretro core.
retro_hw_context_reset_t context_reset; // Called when a context has been created or when it has been reset.
// Called when a context has been created or when it has been reset.
// An OpenGL context is only valid after context_reset() has been called.
//
// When context_reset is called, OpenGL resources in the libretro implementation are guaranteed to be invalid.
// It is possible that context_reset is called multiple times during an application lifecycle.
// If context_reset is called without any notification (context_destroy),
// the OpenGL context was lost and resources should just be recreated
// without any attempt to "free" old resources.
retro_hw_context_reset_t context_reset;
retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend.
retro_hw_get_proc_address_t get_proc_address; // Set by frontend. retro_hw_get_proc_address_t get_proc_address; // Set by frontend.
bool depth; // Set if render buffers should have depth component attached. bool depth; // Set if render buffers should have depth component attached.
@ -919,7 +1032,16 @@ struct retro_hw_render_callback
bool cache_context; // If this is true, the frontend will go very far to avoid resetting context in scenarios like toggling fullscreen, etc. 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. // 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.
retro_hw_context_reset_t context_destroy; // A callback to be called before the context is destroyed in a controlled way by the frontend.
// OpenGL resources can be deinitialized cleanly at this step.
// context_destroy can be set to NULL, in which resources will just be destroyed without any notification.
//
// Even when context_destroy is non-NULL, it is possible that context_reset is called without any destroy notification.
// This happens if context is lost by external factors (such as notified by GL_ARB_robustness).
// In this case, the context is assumed to be already dead,
// and the libretro implementation must not try to free any OpenGL resources in the subsequent context_reset.
bool debug_context; // Creates a debug context. bool debug_context; // Creates a debug context.
}; };
@ -1150,6 +1272,8 @@ void retro_get_system_info(struct retro_system_info *info);
void retro_get_system_av_info(struct retro_system_av_info *info); void retro_get_system_av_info(struct retro_system_av_info *info);
// Sets device to be used for player 'port'. // 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); void retro_set_controller_port_device(unsigned port, unsigned device);
// Resets the current game. // Resets the current game.