libretro: rework controller assignment

This commit is contained in:
OV2 2014-06-02 22:20:19 +02:00
parent 6cdcd4eac0
commit 5e0319ab3e
2 changed files with 330 additions and 84 deletions

View File

@ -21,6 +21,23 @@
#include <sys/types.h>
#include <fcntl.h>
#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)
#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)
#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
static retro_log_printf_t log_cb = NULL;
static retro_video_refresh_t s9x_video_cb = NULL;
static retro_audio_sample_t s9x_audio_cb = NULL;
@ -60,7 +77,7 @@ void retro_set_environment(retro_environment_t cb)
{
environ_cb = cb;
struct retro_variable variables[] = {
const struct retro_variable variables[] = {
// These variable names and possible values constitute an ABI with ZMZ (ZSNES Libretro player).
// Changing "Show layer 1" is fine, but don't change "layer_1"/etc or the possible values ("Yes|No").
// Adding more variables and rearranging them is safe.
@ -82,7 +99,29 @@ void retro_set_environment(retro_environment_t cb)
{ NULL, NULL },
};
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)variables);
static const struct retro_controller_description port_1[] = {
{ "SNES Joypad", RETRO_DEVICE_JOYPAD },
{ "SNES Mouse", RETRO_DEVICE_MOUSE },
{ "Multitap", RETRO_DEVICE_JOYPAD_MULTITAP },
};
static const struct retro_controller_description port_2[] = {
{ "SNES Joypad", RETRO_DEVICE_JOYPAD },
{ "SNES Mouse", RETRO_DEVICE_MOUSE },
{ "Multitap", RETRO_DEVICE_JOYPAD_MULTITAP },
{ "SuperScope", RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE },
{ "Justifier", RETRO_DEVICE_LIGHTGUN_JUSTIFIER },
};
const struct retro_controller_info ports[] = {
{ port_1, 3 },
{ port_2, 5 },
{ 0 },
};
environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
}
static void update_variables(void)
@ -184,14 +223,15 @@ void retro_set_controller_port_device(unsigned port, unsigned device)
{
if(port < 2)
{
int offset = snes_devices[0] == RETRO_DEVICE_JOYPAD_MULTITAP ? 4 : 1;
switch (device)
{
case RETRO_DEVICE_JOYPAD:
S9xSetController(port, CTL_JOYPAD, port*4, 0, 0, 0);
S9xSetController(port, CTL_JOYPAD, port * offset, 0, 0, 0);
snes_devices[port] = RETRO_DEVICE_JOYPAD;
break;
case RETRO_DEVICE_JOYPAD_MULTITAP:
S9xSetController(port, CTL_MP5, port*4+0, port*4+1, port*4+2, port*4+3);
S9xSetController(port, CTL_MP5, port * offset, port * offset + 1, port * offset + 2, port * offset + 3);
snes_devices[port] = RETRO_DEVICE_JOYPAD_MULTITAP;
break;
case RETRO_DEVICE_MOUSE:
@ -206,14 +246,12 @@ void retro_set_controller_port_device(unsigned port, unsigned device)
S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0);
snes_devices[port] = RETRO_DEVICE_LIGHTGUN_JUSTIFIER;
break;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS:
S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0);
snes_devices[port] = RETRO_DEVICE_LIGHTGUN_JUSTIFIERS;
break;
default:
if (log_cb)
log_cb(RETRO_LOG_ERROR, "[libretro]: Invalid device (%d).\n", device);
}
if (!port)
retro_set_controller_port_device(1, snes_devices[1]);
}
else if(device != RETRO_DEVICE_NONE)
log_cb(RETRO_LOG_INFO, "[libretro]: Nonexistent Port (%d).\n", port);
@ -521,19 +559,20 @@ static int16_t snes_justifier_state[2][2] = {{0}, {0}};
static void report_buttons()
{
int _x, _y;
int offset = snes_devices[0] == RETRO_DEVICE_JOYPAD_MULTITAP ? 4 : 1;
for (int port = 0; port <= 1; port++)
{
switch (snes_devices[port])
{
case RETRO_DEVICE_JOYPAD:
for (int i = BTN_FIRST; i <= BTN_LAST; i++)
S9xReportButton(MAKE_BUTTON(port*4 + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_JOYPAD, 0, i));
S9xReportButton(MAKE_BUTTON(port * offset + 1, i), s9x_input_state_cb(port * offset, RETRO_DEVICE_JOYPAD, 0, i));
break;
case RETRO_DEVICE_JOYPAD_MULTITAP:
for (int j = 0; j < 4; j++)
for (int i = BTN_FIRST; i <= BTN_LAST; i++)
S9xReportButton(MAKE_BUTTON(port*4 + j + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_JOYPAD_MULTITAP, j, i));
S9xReportButton(MAKE_BUTTON(port * offset + j + 1, i), s9x_input_state_cb(port * offset + j, RETRO_DEVICE_JOYPAD, 0, i));
break;
case RETRO_DEVICE_MOUSE:
@ -547,20 +586,20 @@ static void report_buttons()
break;
case RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE:
snes_scope_state[0] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, 0, RETRO_DEVICE_ID_LIGHTGUN_X);
snes_scope_state[1] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, 0, RETRO_DEVICE_ID_LIGHTGUN_Y);
snes_scope_state[0] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X);
snes_scope_state[1] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_Y);
S9xReportPointer(BTN_POINTER, snes_scope_state[0], snes_scope_state[1]);
for (int i = SCOPE_TRIGGER; i <= SCOPE_LAST; i++)
S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE, 0, i));
S9xReportButton(MAKE_BUTTON(2, i), s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, i));
break;
case RETRO_DEVICE_LIGHTGUN_JUSTIFIER:
case RETRO_DEVICE_LIGHTGUN_JUSTIFIERS:
snes_justifier_state[0][0] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, 0, RETRO_DEVICE_ID_LIGHTGUN_X);
snes_justifier_state[0][1] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, 0, RETRO_DEVICE_ID_LIGHTGUN_Y);
snes_justifier_state[0][0] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_X);
snes_justifier_state[0][1] += s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, RETRO_DEVICE_ID_LIGHTGUN_Y);
S9xReportPointer(BTN_POINTER, snes_justifier_state[0][0], snes_justifier_state[0][1]);
for (int i = JUSTIFIER_TRIGGER; i <= JUSTIFIER_LAST; i++)
S9xReportButton(MAKE_BUTTON(port + 1, i), s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN_JUSTIFIER, 0, i));
S9xReportButton(MAKE_BUTTON(2, i), s9x_input_state_cb(port, RETRO_DEVICE_LIGHTGUN, 0, i));
break;
default:

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2013 The RetroArch team
/* Copyright (C) 2010-2014 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro.h).
@ -23,15 +23,17 @@
#ifndef LIBRETRO_H__
#define LIBRETRO_H__
#include "port.h"
#include <port.h>
#include <stddef.h>
#include <limits.h>
// Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant.
#ifdef __cplusplus
extern "C" {
#else
#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) && !defined(__cplusplus)
#endif
#ifndef __cplusplus
#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
#define bool unsigned char
#define true 1
#define false 0
@ -44,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,
@ -60,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.
@ -85,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.
@ -94,19 +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
// FIXME: Document this.
#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7
// 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.
@ -134,10 +138,13 @@ extern "C" {
#define RETRO_DEVICE_ID_ANALOG_Y 1
// Id values for MOUSE.
#define RETRO_DEVICE_ID_MOUSE_X 0
#define RETRO_DEVICE_ID_MOUSE_Y 1
#define RETRO_DEVICE_ID_MOUSE_LEFT 2
#define RETRO_DEVICE_ID_MOUSE_RIGHT 3
#define RETRO_DEVICE_ID_MOUSE_X 0
#define RETRO_DEVICE_ID_MOUSE_Y 1
#define RETRO_DEVICE_ID_MOUSE_LEFT 2
#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.
#define RETRO_DEVICE_ID_LIGHTGUN_X 0
@ -153,11 +160,6 @@ extern "C" {
#define RETRO_DEVICE_ID_POINTER_Y 1
#define RETRO_DEVICE_ID_POINTER_PRESSED 2
// Id values for SENSOR types.
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1
#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2
// Returned from retro_get_region().
#define RETRO_REGION_NTSC 0
#define RETRO_REGION_PAL 1
@ -168,7 +170,7 @@ extern "C" {
// 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,
// 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
// Some games have a built-in clock to keep track of time.
@ -181,21 +183,6 @@ extern "C" {
// Video ram lets a frontend peek into a game systems video RAM (VRAM).
#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.
enum retro_key
{
@ -385,7 +372,7 @@ enum retro_mod
// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash.
#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * --
// Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'.
// Should not be used for trivial messages, which should simply be logged to stderr.
// Should not be used for trivial messages, which should simply be logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a fallback, stderr).
#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) --
// Requests the frontend to shutdown.
// Should only be used if game has a specific
@ -401,16 +388,11 @@ enum retro_mod
// It can be used by the frontend to potentially warn
// about too demanding implementations.
//
// The levels are "floating", but roughly defined as:
// 0: Low-powered embedded devices such as Raspberry Pi
// 1: 6th generation consoles, such as Wii/Xbox 1, and phones, tablets, etc.
// 2: 7th generation consoles, such as PS3/360, with sub-par CPUs.
// 3: Modern desktop/laptops with reasonably powerful CPUs.
// 4: High-end desktops with very powerful CPUs.
// The levels are "floating".
//
// This function can be called on a per-game basis,
// as certain games an implementation can play might be
// particularily demanding.
// particularly demanding.
// If called, it should be called in retro_load_game().
//
#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9
@ -421,6 +403,9 @@ enum retro_mod
// If so, no such directory is defined,
// and it's up to the implementation to find a suitable directory.
//
// NOTE: Some cores used this folder also for "save" data such as memory cards, etc, for lack of a better place to put it.
// This is now discouraged, and if possible, cores should try to use the new GET_SAVE_DIRECTORY.
//
#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10
// const enum retro_pixel_format * --
// Sets the internal pixel format used by the implementation.
@ -568,6 +553,158 @@ enum retro_mod
// struct retro_perf_callback * --
// 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,
// such as current latitude / longitude.
//
#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30
// const char ** --
// Returns the "content" directory of the frontend.
// This directory can be used to store specific assets that the core relies upon, such as art assets,
// input data, etc etc.
// The returned value can be NULL.
// If so, no such directory is defined,
// and it's up to the implementation to find a suitable directory.
//
#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31
// const char ** --
// Returns the "save" directory of the frontend.
// This directory can be used to store SRAM, memory cards, high scores, etc, if the libretro core
// cannot use the regular memory interface (retro_get_memory_data()).
//
// NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for similar things before.
// They should still check GET_SYSTEM_DIRECTORY if they want to be backwards compatible.
// The path here can be NULL. It should only be non-NULL if the frontend user has set a specific save path.
//
#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32
// const struct retro_system_av_info * --
// Sets a new av_info structure. This can only be called from within retro_run().
// This should *only* be used if the core is completely altering the internal resolutions, aspect ratios, timings, sampling rate, etc.
// Calling this can require a full reinitialization of video/audio drivers in the frontend,
// so it is important to call it very sparingly, and usually only with the users explicit consent.
// An eventual driver reinitialize will happen so that video and audio callbacks
// happening after this call within the same retro_run() call will target the newly initialized driver.
//
// This callback makes it possible to support configurable resolutions in games, which can be useful to
// avoid setting the "worst case" in max_width/max_height.
//
// ***HIGHLY RECOMMENDED*** Do not call this callback every time resolution changes in an emulator core if it's
// expected to be a temporary change, for the reasons of possible driver reinit.
// 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.
#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
{
@ -598,6 +735,13 @@ struct retro_log_callback
#define RETRO_SIMD_NEON (1 << 5)
#define RETRO_SIMD_SSE3 (1 << 6)
#define RETRO_SIMD_SSSE3 (1 << 7)
#define RETRO_SIMD_MMX (1 << 8)
#define RETRO_SIMD_MMXEXT (1 << 9)
#define RETRO_SIMD_SSE4 (1 << 10)
#define RETRO_SIMD_SSE42 (1 << 11)
#define RETRO_SIMD_AVX2 (1 << 12)
#define RETRO_SIMD_VFPU (1 << 13)
#define RETRO_SIMD_PS (1 << 14)
typedef uint64_t retro_perf_tick_t;
typedef int64_t retro_time_t;
@ -683,10 +827,17 @@ enum retro_sensor_action
RETRO_SENSOR_DUMMY = INT_MAX
};
// Id values for SENSOR types.
#define RETRO_SENSOR_ACCELEROMETER_X 0
#define RETRO_SENSOR_ACCELEROMETER_Y 1
#define RETRO_SENSOR_ACCELEROMETER_Z 2
typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate);
typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id);
struct retro_sensor_interface
{
retro_set_sensor_state_t set_sensor_state;
retro_sensor_get_input_t get_sensor_input;
};
////
@ -743,6 +894,41 @@ struct retro_camera_callback
retro_camera_lifetime_status_t deinitialized;
};
// 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
// 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.
typedef void (*retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance);
// Start location services. The device will start listening for changes to the
// current location at regular intervals (which are defined with retro_location_set_interval_t).
typedef bool (*retro_location_start_t)(void);
// Stop location services. The device will stop listening for changes to the current
// location.
typedef void (*retro_location_stop_t)(void);
// Get the position of the current location. Will set parameters to 0 if no new
// location update has happened since the last time.
typedef bool (*retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy,
double *vert_accuracy);
// Callback which signals when the location driver is initialized and/or deinitialized.
// retro_location_start_t can be called in initialized callback.
typedef void (*retro_location_lifetime_status_t)(void);
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_lifetime_status_t initialized;
retro_location_lifetime_status_t deinitialized;
};
enum retro_rumble_effect
{
RETRO_RUMBLE_STRONG = 0,
@ -796,22 +982,22 @@ struct retro_frame_time_callback
// it should implement context_destroy callback.
// If called, all GPU resources must be reinitialized.
// Usually called when frontend reinits video driver.
// Also called first time video driver is initialized, allowing libretro core to init resources.
// Also called first time video driver is initialized, allowing libretro core to initialize resources.
typedef void (*retro_hw_context_reset_t)(void);
// Gets current framebuffer which is to be rendered to. Could change every frame potentially.
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
// 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);
enum retro_hw_context_type
{
RETRO_HW_CONTEXT_NONE = 0,
RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. Driver can choose to use latest compatibility context.
RETRO_HW_CONTEXT_OPENGLES2, // GLES 2.0
RETRO_HW_CONTEXT_OPENGL_CORE, // Modern desktop core GL context. Use major/minor fields to set GL version.
RETRO_HW_CONTEXT_OPENGLES3, // GLES 3.0
RETRO_HW_CONTEXT_NONE = 0,
RETRO_HW_CONTEXT_OPENGL = 1, // OpenGL 2.x. Driver can choose to use latest compatibility context.
RETRO_HW_CONTEXT_OPENGLES2 = 2, // GLES 2.0
RETRO_HW_CONTEXT_OPENGL_CORE = 3, // Modern desktop core GL context. Use version_major/version_minor fields to set GL version.
RETRO_HW_CONTEXT_OPENGLES3 = 4, // GLES 3.0
RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, // GLES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, use the corresponding enums directly.
RETRO_HW_CONTEXT_DUMMY = INT_MAX
};
@ -819,20 +1005,39 @@ enum retro_hw_context_type
struct retro_hw_render_callback
{
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_proc_address_t get_proc_address; // Set by frontend.
bool depth; // Set if render buffers should have depth component attached.
bool stencil; // Set if stencil buffers should be attached.
// If depth and stencil are true, a packed 24/8 buffer will be added. Only attaching stencil is invalid and will be ignored.
bool bottom_left_origin; // Use conventional bottom-left origin convention. Is false, standard libretro top-left origin semantics are used.
unsigned version_major; // Major version number for core GL context.
unsigned version_minor; // Minor version number for core GL context.
unsigned version_major; // Major version number for core GL context or GLES 3.1+.
unsigned version_minor; // Minor version number for core GL context or GLES 3.1+.
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.
// 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.
};
@ -1063,6 +1268,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.