Merge pull request #58 from GregorR/serialization-quirks

Report platform-dependent savestates
This commit is contained in:
Twinaphex 2016-10-10 18:36:08 +02:00 committed by GitHub
commit 3ceb4f9117
2 changed files with 327 additions and 90 deletions

View File

@ -1988,6 +1988,7 @@ void retro_init(void)
{ {
struct retro_log_callback log; struct retro_log_callback log;
unsigned level, rgb565; unsigned level, rgb565;
uint64_t serialization_quirks = RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT;
sms_ntsc = calloc(1, sizeof(sms_ntsc_t)); sms_ntsc = calloc(1, sizeof(sms_ntsc_t));
md_ntsc = calloc(1, sizeof(md_ntsc_t)); md_ntsc = calloc(1, sizeof(md_ntsc_t));
@ -2009,6 +2010,8 @@ void retro_init(void)
log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n");
#endif #endif
check_system_specs(); check_system_specs();
environ_cb(RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS, &serialization_quirks);
} }
void retro_deinit(void) void retro_deinit(void)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2014 The RetroArch team /* Copyright (C) 2010-2016 The RetroArch team
* *
* --------------------------------------------------------------------------------------- * ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro.h). * The following license statement only applies to this libretro API header (libretro.h).
@ -43,6 +43,40 @@ extern "C" {
#endif #endif
#endif #endif
#ifndef RETRO_CALLCONV
# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__)
# define RETRO_CALLCONV __attribute__((cdecl))
# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64)
# define RETRO_CALLCONV __cdecl
# else
# define RETRO_CALLCONV /* all other platforms only have one calling convention each */
# endif
#endif
#ifndef RETRO_API
# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
# ifdef RETRO_IMPORT_SYMBOLS
# ifdef __GNUC__
# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__))
# else
# define RETRO_API RETRO_CALLCONV __declspec(dllimport)
# endif
# else
# ifdef __GNUC__
# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__))
# else
# define RETRO_API RETRO_CALLCONV __declspec(dllexport)
# endif
# endif
# else
# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__)
# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
# else
# define RETRO_API RETRO_CALLCONV
# endif
# endif
#endif
/* Used for checking API/ABI mismatches that can break libretro /* Used for checking API/ABI mismatches that can break libretro
* implementations. * implementations.
* It is not incremented for compatible changes to the API. * It is not incremented for compatible changes to the API.
@ -172,6 +206,8 @@ extern "C" {
#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 #define RETRO_DEVICE_ID_MOUSE_WHEELUP 4
#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 #define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5
#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 #define RETRO_DEVICE_ID_MOUSE_MIDDLE 6
#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7
#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8
/* Id values for LIGHTGUN types. */ /* Id values for LIGHTGUN types. */
#define RETRO_DEVICE_ID_LIGHTGUN_X 0 #define RETRO_DEVICE_ID_LIGHTGUN_X 0
@ -206,6 +242,8 @@ enum retro_language
RETRO_LANGUAGE_KOREAN = 9, RETRO_LANGUAGE_KOREAN = 9,
RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10,
RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11,
RETRO_LANGUAGE_ESPERANTO = 12,
RETRO_LANGUAGE_POLISH = 13,
RETRO_LANGUAGE_LAST, RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */ /* Ensure sizeof(enum) == sizeof(int) */
@ -693,9 +731,10 @@ enum retro_mod
* location-based information from the host device, * location-based information from the host device,
* such as current latitude / longitude. * such as current latitude / longitude.
*/ */
#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 #define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */
#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30
/* const char ** -- /* const char ** --
* Returns the "content" directory of the frontend. * Returns the "core assets" directory of the frontend.
* This directory can be used to store specific assets that the * This directory can be used to store specific assets that the
* core relies upon, such as art assets, * core relies upon, such as art assets,
* input data, etc etc. * input data, etc etc.
@ -851,6 +890,122 @@ enum retro_mod
* Returns the specified language of the frontend, if specified by the user. * Returns the specified language of the frontend, if specified by the user.
* It can be used by the core for localization purposes. * It can be used by the core for localization purposes.
*/ */
#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_framebuffer * --
* Returns a preallocated framebuffer which the core can use for rendering
* the frame into when not using SET_HW_RENDER.
* The framebuffer returned from this call must not be used
* after the current call to retro_run() returns.
*
* The goal of this call is to allow zero-copy behavior where a core
* can render directly into video memory, avoiding extra bandwidth cost by copying
* memory from core to video memory.
*
* If this call succeeds and the core renders into it,
* the framebuffer pointer and pitch can be passed to retro_video_refresh_t.
* If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used,
* the core must pass the exact
* same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER;
* i.e. passing a pointer which is offset from the
* buffer is undefined. The width, height and pitch parameters
* must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER.
*
* It is possible for a frontend to return a different pixel format
* than the one used in SET_PIXEL_FORMAT. This can happen if the frontend
* needs to perform conversion.
*
* It is still valid for a core to render to a different buffer
* even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds.
*
* A frontend must make sure that the pointer obtained from this function is
* writeable (and readable).
*/
enum retro_hw_render_interface_type
{
RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
};
/* Base struct. All retro_hw_render_interface_* types
* contain at least these fields. */
struct retro_hw_render_interface
{
enum retro_hw_render_interface_type interface_type;
unsigned interface_version;
};
#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* const struct retro_hw_render_interface ** --
* Returns an API specific rendering interface for accessing API specific data.
* Not all HW rendering APIs support or need this.
* The contents of the returned pointer is specific to the rendering API
* being used. See the various headers like libretro_vulkan.h, etc.
*
* GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
* Similarly, after context_destroyed callback returns,
* the contents of the HW_RENDER_INTERFACE are invalidated.
*/
#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* const bool * --
* If true, the libretro implementation supports achievements
* either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
* or via retro_get_memory_data/retro_get_memory_size.
*
* This must be called before the first call to retro_run.
*/
enum retro_hw_render_context_negotiation_interface_type
{
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0,
RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX
};
/* Base struct. All retro_hw_render_context_negotiation_interface_* types
* contain at least these fields. */
struct retro_hw_render_context_negotiation_interface
{
enum retro_hw_render_context_negotiation_interface_type interface_type;
unsigned interface_version;
};
#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* const struct retro_hw_render_context_negotiation_interface * --
* Sets an interface which lets the libretro core negotiate with frontend how a context is created.
* The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
* This interface will be used when the frontend is trying to create a HW rendering context,
* so it will be used after SET_HW_RENDER, but before the context_reset callback.
*/
/* Serialized state is incomplete in some way. Set if serialization is
* usable in typical end-user cases but should not be relied upon to
* implement frame-sensitive frontend features such as netplay or
* rerecording. */
#define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0)
/* The core must spend some time initializing before serialization is
* supported. retro_serialize() will initially fail; retro_unserialize()
* and retro_serialize_size() may or may not work correctly either. */
#define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1)
/* Serialization size may change within a session. */
#define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2)
/* Set by the frontend to acknowledge that it supports variable-sized
* states. */
#define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3)
/* Serialized state can only be loaded during the same session. */
#define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4)
/* Serialized state cannot be loaded on an architecture with a different
* endianness from the one it was saved on. */
#define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5)
/* Serialized state cannot be loaded on a different platform from the one it
* was saved on for reasons other than endianness, such as word size
* dependence */
#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6)
#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
/* uint64_t * --
* Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
* recognize or support. Should be set in either retro_init or retro_load_game, but not both.
*/
#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ #define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ #define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */
@ -907,9 +1062,9 @@ struct retro_memory_descriptor
/* To go from emulated address to physical address, the following /* To go from emulated address to physical address, the following
* order applies: * order applies:
* Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */
*
* The address space name must consist of only a-zA-Z0-9_-, /* The address space name must consist of only a-zA-Z0-9_-,
* should be as short as feasible (maximum length is 8 plus the NUL), * should be as short as feasible (maximum length is 8 plus the NUL),
* and may not be any other address space plus one or more 0-9A-F * and may not be any other address space plus one or more 0-9A-F
* at the end. * at the end.
@ -935,6 +1090,37 @@ struct retro_memory_descriptor
* The length can't be used for that purpose; the frontend may want * The length can't be used for that purpose; the frontend may want
* to append arbitrary data to an address, without a separator. */ * to append arbitrary data to an address, without a separator. */
const char *addrspace; const char *addrspace;
/* TODO: When finalizing this one, add a description field, which should be
* "WRAM" or something roughly equally long. */
/* TODO: When finalizing this one, replace 'select' with 'limit', which tells
* which bits can vary and still refer to the same address (limit = ~select).
* TODO: limit? range? vary? something else? */
/* TODO: When finalizing this one, if 'len' is above what 'select' (or
* 'limit') allows, it's bankswitched. Bankswitched data must have both 'len'
* and 'select' != 0, and the mappings don't tell how the system switches the
* banks. */
/* TODO: When finalizing this one, fix the 'len' bit removal order.
* For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00.
* Algorithm: Take bits highest to lowest, but if it goes above len, clear
* the most recent addition and continue on the next bit.
* TODO: Can the above be optimized? Is "remove the lowest bit set in both
* pointer and 'len'" equivalent? */
/* TODO: Some emulators (MAME?) emulate big endian systems by only accessing
* the emulated memory in 32-bit chunks, native endian. But that's nothing
* compared to Darek Mihocka <http://www.emulators.com/docs/nx07_vm101.htm>
* (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE
* RAM backwards! I'll want to represent both of those, via some flags.
*
* I suspect MAME either didn't think of that idea, or don't want the #ifdef.
* Not sure which, nor do I really care. */
/* TODO: Some of those flags are unused and/or don't really make sense. Clean
* them up. */
}; };
/* The frontend may use the largest value of 'start'+'select' in a /* The frontend may use the largest value of 'start'+'select' in a
@ -1064,7 +1250,7 @@ struct retro_subsystem_info
unsigned id; unsigned id;
}; };
typedef void (*retro_proc_address_t)(void); typedef void (RETRO_CALLCONV *retro_proc_address_t)(void);
/* libretro API extension functions: /* libretro API extension functions:
* (None here so far). * (None here so far).
@ -1080,7 +1266,7 @@ typedef void (*retro_proc_address_t)(void);
* e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". * 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. * The returned function pointer must be cast to the corresponding type.
*/ */
typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym); typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym);
struct retro_get_proc_address_interface struct retro_get_proc_address_interface
{ {
@ -1098,7 +1284,7 @@ enum retro_log_level
}; };
/* Logging function. Takes log level argument as well. */ /* Logging function. Takes log level argument as well. */
typedef void (*retro_log_printf_t)(enum retro_log_level level, typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level,
const char *fmt, ...); const char *fmt, ...);
struct retro_log_callback struct retro_log_callback
@ -1125,6 +1311,11 @@ struct retro_log_callback
#define RETRO_SIMD_VFPU (1 << 13) #define RETRO_SIMD_VFPU (1 << 13)
#define RETRO_SIMD_PS (1 << 14) #define RETRO_SIMD_PS (1 << 14)
#define RETRO_SIMD_AES (1 << 15) #define RETRO_SIMD_AES (1 << 15)
#define RETRO_SIMD_VFPV3 (1 << 16)
#define RETRO_SIMD_VFPV4 (1 << 17)
#define RETRO_SIMD_POPCNT (1 << 18)
#define RETRO_SIMD_MOVBE (1 << 19)
#define RETRO_SIMD_CMOV (1 << 20)
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;
@ -1142,34 +1333,34 @@ struct retro_perf_counter
/* Returns current time in microseconds. /* Returns current time in microseconds.
* Tries to use the most accurate timer available. * Tries to use the most accurate timer available.
*/ */
typedef retro_time_t (*retro_perf_get_time_usec_t)(void); typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void);
/* A simple counter. Usually nanoseconds, but can also be CPU cycles. /* A simple counter. Usually nanoseconds, but can also be CPU cycles.
* Can be used directly if desired (when creating a more sophisticated * Can be used directly if desired (when creating a more sophisticated
* performance counter system). * performance counter system).
* */ * */
typedef retro_perf_tick_t (*retro_perf_get_counter_t)(void); typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void);
/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ /* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */
typedef uint64_t (*retro_get_cpu_features_t)(void); typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void);
/* Asks frontend to log and/or display the state of performance counters. /* Asks frontend to log and/or display the state of performance counters.
* Performance counters can always be poked into manually as well. * Performance counters can always be poked into manually as well.
*/ */
typedef void (*retro_perf_log_t)(void); typedef void (RETRO_CALLCONV *retro_perf_log_t)(void);
/* Register a performance counter. /* Register a performance counter.
* ident field must be set with a discrete value and other values in * ident field must be set with a discrete value and other values in
* retro_perf_counter must be 0. * retro_perf_counter must be 0.
* Registering can be called multiple times. To avoid calling to * Registering can be called multiple times. To avoid calling to
* frontend redundantly, you can check registered field first. */ * frontend redundantly, you can check registered field first. */
typedef void (*retro_perf_register_t)(struct retro_perf_counter *counter); typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter);
/* Starts a registered counter. */ /* Starts a registered counter. */
typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter); typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter);
/* Stops a registered counter. */ /* Stops a registered counter. */
typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter); typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter);
/* For convenience it can be useful to wrap register, start and stop in macros. /* For convenience it can be useful to wrap register, start and stop in macros.
* E.g.: * E.g.:
@ -1232,10 +1423,10 @@ enum retro_sensor_action
#define RETRO_SENSOR_ACCELEROMETER_Y 1 #define RETRO_SENSOR_ACCELEROMETER_Y 1
#define RETRO_SENSOR_ACCELEROMETER_Z 2 #define RETRO_SENSOR_ACCELEROMETER_Z 2
typedef bool (*retro_set_sensor_state_t)(unsigned port, typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
enum retro_sensor_action action, unsigned rate); enum retro_sensor_action action, unsigned rate);
typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id); typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id);
struct retro_sensor_interface struct retro_sensor_interface
{ {
@ -1252,22 +1443,22 @@ enum retro_camera_buffer
}; };
/* Starts the camera driver. Can only be called in retro_run(). */ /* Starts the camera driver. Can only be called in retro_run(). */
typedef bool (*retro_camera_start_t)(void); typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void);
/* Stops the camera driver. Can only be called in retro_run(). */ /* Stops the camera driver. Can only be called in retro_run(). */
typedef void (*retro_camera_stop_t)(void); typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void);
/* Callback which signals when the camera driver is initialized /* Callback which signals when the camera driver is initialized
* and/or deinitialized. * and/or deinitialized.
* retro_camera_start_t can be called in initialized callback. * retro_camera_start_t can be called in initialized callback.
*/ */
typedef void (*retro_camera_lifetime_status_t)(void); typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void);
/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. /* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer.
* Width, height and pitch are similar to retro_video_refresh_t. * Width, height and pitch are similar to retro_video_refresh_t.
* First pixel is top-left origin. * First pixel is top-left origin.
*/ */
typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer,
unsigned width, unsigned height, size_t pitch); unsigned width, unsigned height, size_t pitch);
/* A callback for when OpenGL textures are used. /* A callback for when OpenGL textures are used.
@ -1288,7 +1479,7 @@ typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer,
* GL-specific typedefs are avoided here to avoid relying on gl.h in * GL-specific typedefs are avoided here to avoid relying on gl.h in
* the API definition. * the API definition.
*/ */
typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id,
unsigned texture_target, const float *affine); unsigned texture_target, const float *affine);
struct retro_camera_callback struct retro_camera_callback
@ -1298,13 +1489,17 @@ struct retro_camera_callback
*/ */
uint64_t caps; uint64_t caps;
unsigned width; /* Desired resolution for camera. Is only used as a hint. */ /* Desired resolution for camera. Is only used as a hint. */
unsigned width;
unsigned height; unsigned height;
retro_camera_start_t start; /* Set by frontend. */
retro_camera_stop_t stop; /* Set by frontend. */ /* Set by frontend. */
retro_camera_start_t start;
retro_camera_stop_t stop;
/* Set by libretro core if raw framebuffer callbacks will be used. */ /* Set by libretro core if raw framebuffer callbacks will be used. */
retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer;
/* Set by libretro core if OpenGL texture callbacks will be used. */ /* Set by libretro core if OpenGL texture callbacks will be used. */
retro_camera_frame_opengl_texture_t frame_opengl_texture; retro_camera_frame_opengl_texture_t frame_opengl_texture;
@ -1330,28 +1525,28 @@ struct retro_camera_callback
* interval_ms is the interval expressed in milliseconds. * interval_ms is the interval expressed in milliseconds.
* interval_distance is the distance interval expressed in meters. * interval_distance is the distance interval expressed in meters.
*/ */
typedef void (*retro_location_set_interval_t)(unsigned interval_ms, typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms,
unsigned interval_distance); unsigned interval_distance);
/* Start location services. The device will start listening for changes to the /* Start location services. The device will start listening for changes to the
* current location at regular intervals (which are defined with * current location at regular intervals (which are defined with
* retro_location_set_interval_t). */ * retro_location_set_interval_t). */
typedef bool (*retro_location_start_t)(void); typedef bool (RETRO_CALLCONV *retro_location_start_t)(void);
/* Stop location services. The device will stop listening for changes /* Stop location services. The device will stop listening for changes
* to the current location. */ * to the current location. */
typedef void (*retro_location_stop_t)(void); typedef void (RETRO_CALLCONV *retro_location_stop_t)(void);
/* Get the position of the current location. Will set parameters to /* Get the position of the current location. Will set parameters to
* 0 if no new location update has happened since the last time. */ * 0 if no new location update has happened since the last time. */
typedef bool (*retro_location_get_position_t)(double *lat, double *lon, typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon,
double *horiz_accuracy, double *vert_accuracy); double *horiz_accuracy, double *vert_accuracy);
/* Callback which signals when the location driver is initialized /* Callback which signals when the location driver is initialized
* and/or deinitialized. * and/or deinitialized.
* retro_location_start_t can be called in initialized callback. * retro_location_start_t can be called in initialized callback.
*/ */
typedef void (*retro_location_lifetime_status_t)(void); typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void);
struct retro_location_callback struct retro_location_callback
{ {
@ -1379,7 +1574,7 @@ enum retro_rumble_effect
* *
* Returns true if rumble state request was honored. * Returns true if rumble state request was honored.
* Calling this before first retro_run() is likely to return false. */ * Calling this before first retro_run() is likely to return false. */
typedef bool (*retro_set_rumble_state_t)(unsigned port, typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port,
enum retro_rumble_effect effect, uint16_t strength); enum retro_rumble_effect effect, uint16_t strength);
struct retro_rumble_interface struct retro_rumble_interface
@ -1388,7 +1583,7 @@ struct retro_rumble_interface
}; };
/* Notifies libretro that audio data should be written. */ /* Notifies libretro that audio data should be written. */
typedef void (*retro_audio_callback_t)(void); typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void);
/* True: Audio driver in frontend is active, and callback is /* True: Audio driver in frontend is active, and callback is
* expected to be called regularily. * expected to be called regularily.
@ -1397,7 +1592,7 @@ typedef void (*retro_audio_callback_t)(void);
* called with true. * called with true.
* Initial state is false (inactive). * Initial state is false (inactive).
*/ */
typedef void (*retro_audio_set_state_callback_t)(bool enabled); typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled);
struct retro_audio_callback struct retro_audio_callback
{ {
@ -1414,7 +1609,7 @@ struct retro_audio_callback
* *
* In those scenarios the reference frame time value will be used. */ * In those scenarios the reference frame time value will be used. */
typedef int64_t retro_usec_t; typedef int64_t retro_usec_t;
typedef void (*retro_frame_time_callback_t)(retro_usec_t usec); typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec);
struct retro_frame_time_callback struct retro_frame_time_callback
{ {
retro_frame_time_callback_t callback; retro_frame_time_callback_t callback;
@ -1438,15 +1633,15 @@ struct retro_frame_time_callback
* Also called first time video driver is initialized, * Also called first time video driver is initialized,
* allowing libretro core to initialize resources. * allowing libretro core to initialize resources.
*/ */
typedef void (*retro_hw_context_reset_t)(void); typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void);
/* Gets current framebuffer which is to be rendered to. /* Gets current framebuffer which is to be rendered to.
* Could change every frame potentially. * Could change every frame potentially.
*/ */
typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void);
/* Get a symbol from HW context. */ /* Get a symbol from HW context. */
typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym);
enum retro_hw_context_type enum retro_hw_context_type
{ {
@ -1464,6 +1659,9 @@ enum retro_hw_context_type
* use the corresponding enums directly. */ * use the corresponding enums directly. */
RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, RETRO_HW_CONTEXT_OPENGLES_VERSION = 5,
/* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
RETRO_HW_CONTEXT_VULKAN = 6,
RETRO_HW_CONTEXT_DUMMY = INT_MAX RETRO_HW_CONTEXT_DUMMY = INT_MAX
}; };
@ -1486,23 +1684,28 @@ struct retro_hw_render_callback
*/ */
retro_hw_context_reset_t context_reset; retro_hw_context_reset_t context_reset;
/* Set by frontend. */ /* Set by frontend.
* TODO: This is rather obsolete. The frontend should not
* be providing preallocated framebuffers. */
retro_hw_get_current_framebuffer_t get_current_framebuffer; retro_hw_get_current_framebuffer_t get_current_framebuffer;
/* Set by frontend. */ /* Set by frontend. */
retro_hw_get_proc_address_t get_proc_address; retro_hw_get_proc_address_t get_proc_address;
/* Set if render buffers should have depth component attached. */ /* Set if render buffers should have depth component attached.
* TODO: Obsolete. */
bool depth; bool depth;
/* Set if stencil buffers should be attached. */ /* Set if stencil buffers should be attached.
* TODO: Obsolete. */
bool stencil; bool stencil;
/* If depth and stencil are true, a packed 24/8 buffer will be added. /* If depth and stencil are true, a packed 24/8 buffer will be added.
* Only attaching stencil is invalid and will be ignored. */ * Only attaching stencil is invalid and will be ignored. */
/* Use conventional bottom-left origin convention. If false, /* Use conventional bottom-left origin convention. If false,
* standard libretro top-left origin semantics are used. */ * standard libretro top-left origin semantics are used.
* TODO: Move to GL specific interface. */
bool bottom_left_origin; bool bottom_left_origin;
/* Major version number for core GL context or GLES 3.1+. */ /* Major version number for core GL context or GLES 3.1+. */
@ -1513,6 +1716,7 @@ struct retro_hw_render_callback
/* If this is true, the frontend will go very far to avoid /* If this is true, the frontend will go very far to avoid
* resetting context in scenarios like toggling fullscreen, etc. * resetting context in scenarios like toggling fullscreen, etc.
* TODO: Obsolete? Maybe frontend should just always assume this ...
*/ */
bool cache_context; bool cache_context;
@ -1562,7 +1766,7 @@ struct retro_hw_render_callback
* Similarily if only a keycode event is generated with no corresponding * Similarily if only a keycode event is generated with no corresponding
* character, character should be 0. * character, character should be 0.
*/ */
typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode,
uint32_t character, uint16_t key_modifiers); uint32_t character, uint16_t key_modifiers);
struct retro_keyboard_callback struct retro_keyboard_callback
@ -1586,24 +1790,24 @@ struct retro_keyboard_callback
/* If ejected is true, "ejects" the virtual disk tray. /* If ejected is true, "ejects" the virtual disk tray.
* When ejected, the disk image index can be set. * When ejected, the disk image index can be set.
*/ */
typedef bool (*retro_set_eject_state_t)(bool ejected); typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected);
/* Gets current eject state. The initial state is 'not ejected'. */ /* Gets current eject state. The initial state is 'not ejected'. */
typedef bool (*retro_get_eject_state_t)(void); typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void);
/* Gets current disk index. First disk is index 0. /* Gets current disk index. First disk is index 0.
* If return value is >= get_num_images(), no disk is currently inserted. * If return value is >= get_num_images(), no disk is currently inserted.
*/ */
typedef unsigned (*retro_get_image_index_t)(void); typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void);
/* Sets image index. Can only be called when disk is ejected. /* Sets image index. Can only be called when disk is ejected.
* The implementation supports setting "no disk" by using an * The implementation supports setting "no disk" by using an
* index >= get_num_images(). * index >= get_num_images().
*/ */
typedef bool (*retro_set_image_index_t)(unsigned index); typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index);
/* Gets total number of images which are available to use. */ /* Gets total number of images which are available to use. */
typedef unsigned (*retro_get_num_images_t)(void); typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void);
struct retro_game_info; struct retro_game_info;
@ -1619,14 +1823,14 @@ struct retro_game_info;
* returned 4 before. * returned 4 before.
* Index 1 will be removed, and the new index is 3. * Index 1 will be removed, and the new index is 3.
*/ */
typedef bool (*retro_replace_image_index_t)(unsigned index, typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
const struct retro_game_info *info); const struct retro_game_info *info);
/* Adds a new valid index (get_num_images()) to the internal disk list. /* Adds a new valid index (get_num_images()) to the internal disk list.
* This will increment subsequent return values from get_num_images() by 1. * This will increment subsequent return values from get_num_images() by 1.
* This image index cannot be used until a disk image has been set * This image index cannot be used until a disk image has been set
* with replace_image_index. */ * with replace_image_index. */
typedef bool (*retro_add_image_index_t)(void); typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
struct retro_disk_control_callback struct retro_disk_control_callback
{ {
@ -1779,11 +1983,41 @@ struct retro_game_info
const char *meta; /* String of implementation specific meta-data. */ const char *meta; /* String of implementation specific meta-data. */
}; };
#define RETRO_MEMORY_ACCESS_WRITE (1 << 0)
/* The core will write to the buffer provided by retro_framebuffer::data. */
#define RETRO_MEMORY_ACCESS_READ (1 << 1)
/* The core will read from retro_framebuffer::data. */
#define RETRO_MEMORY_TYPE_CACHED (1 << 0)
/* The memory in data is cached.
* If not cached, random writes and/or reading from the buffer is expected to be very slow. */
struct retro_framebuffer
{
void *data; /* The framebuffer which the core can render into.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER.
The initial contents of data are unspecified. */
unsigned width; /* The framebuffer width used by the core. Set by core. */
unsigned height; /* The framebuffer height used by the core. Set by core. */
size_t pitch; /* The number of bytes between the beginning of a scanline,
and beginning of the next scanline.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
enum retro_pixel_format format; /* The pixel format the core must use to render into data.
This format could differ from the format used in
SET_PIXEL_FORMAT.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
unsigned access_flags; /* How the core will access the memory in the framebuffer.
RETRO_MEMORY_ACCESS_* flags.
Set by core. */
unsigned memory_flags; /* Flags telling core how the memory has been mapped.
RETRO_MEMORY_TYPE_* flags.
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
};
/* Callbacks */ /* Callbacks */
/* Environment callback. Gives implementations a way of performing /* Environment callback. Gives implementations a way of performing
* uncommon tasks. Extensible. */ * uncommon tasks. Extensible. */
typedef bool (*retro_environment_t)(unsigned cmd, void *data); typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data);
/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian /* Render a frame. Pixel format is 15-bit 0RGB1555 native endian
* unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT).
@ -1796,14 +2030,14 @@ typedef bool (*retro_environment_t)(unsigned cmd, void *data);
* Certain graphic APIs, such as OpenGL ES, do not like textures * Certain graphic APIs, such as OpenGL ES, do not like textures
* that are not packed in memory. * that are not packed in memory.
*/ */
typedef void (*retro_video_refresh_t)(const void *data, unsigned width, typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width,
unsigned height, size_t pitch); unsigned height, size_t pitch);
/* Renders a single audio frame. Should only be used if implementation /* Renders a single audio frame. Should only be used if implementation
* generates a single sample at a time. * generates a single sample at a time.
* Format is signed 16-bit native endian. * Format is signed 16-bit native endian.
*/ */
typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right);
/* Renders multiple audio frames in one go. /* Renders multiple audio frames in one go.
* *
@ -1811,11 +2045,11 @@ typedef void (*retro_audio_sample_t)(int16_t left, int16_t right);
* I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames.
* Only one of the audio callbacks must ever be used. * Only one of the audio callbacks must ever be used.
*/ */
typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data,
size_t frames); size_t frames);
/* Polls input. */ /* Polls input. */
typedef void (*retro_input_poll_t)(void); typedef void (RETRO_CALLCONV *retro_input_poll_t)(void);
/* Queries for input for player 'port'. device will be masked with /* Queries for input for player 'port'. device will be masked with
* RETRO_DEVICE_MASK. * RETRO_DEVICE_MASK.
@ -1824,7 +2058,7 @@ typedef void (*retro_input_poll_t)(void);
* have been set with retro_set_controller_port_device() * have been set with retro_set_controller_port_device()
* will still use the higher level RETRO_DEVICE_JOYPAD to request input. * will still use the higher level RETRO_DEVICE_JOYPAD to request input.
*/ */
typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device,
unsigned index, unsigned id); unsigned index, unsigned id);
/* Sets callbacks. retro_set_environment() is guaranteed to be called /* Sets callbacks. retro_set_environment() is guaranteed to be called
@ -1832,25 +2066,25 @@ typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device,
* *
* The rest of the set_* functions are guaranteed to have been called * The rest of the set_* functions are guaranteed to have been called
* before the first call to retro_run() is made. */ * before the first call to retro_run() is made. */
void retro_set_environment(retro_environment_t); RETRO_API void retro_set_environment(retro_environment_t);
void retro_set_video_refresh(retro_video_refresh_t); RETRO_API void retro_set_video_refresh(retro_video_refresh_t);
void retro_set_audio_sample(retro_audio_sample_t); RETRO_API void retro_set_audio_sample(retro_audio_sample_t);
void retro_set_audio_sample_batch(retro_audio_sample_batch_t); RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t);
void retro_set_input_poll(retro_input_poll_t); RETRO_API void retro_set_input_poll(retro_input_poll_t);
void retro_set_input_state(retro_input_state_t); RETRO_API void retro_set_input_state(retro_input_state_t);
/* Library global initialization/deinitialization. */ /* Library global initialization/deinitialization. */
void retro_init(void); RETRO_API void retro_init(void);
void retro_deinit(void); RETRO_API void retro_deinit(void);
/* Must return RETRO_API_VERSION. Used to validate ABI compatibility /* Must return RETRO_API_VERSION. Used to validate ABI compatibility
* when the API is revised. */ * when the API is revised. */
unsigned retro_api_version(void); RETRO_API unsigned retro_api_version(void);
/* Gets statically known system info. Pointers provided in *info /* Gets statically known system info. Pointers provided in *info
* must be statically allocated. * must be statically allocated.
* Can be called at any time, even before retro_init(). */ * Can be called at any time, even before retro_init(). */
void retro_get_system_info(struct retro_system_info *info); RETRO_API void retro_get_system_info(struct retro_system_info *info);
/* Gets information about system audio/video timings and geometry. /* Gets information about system audio/video timings and geometry.
* Can be called only after retro_load_game() has successfully completed. * Can be called only after retro_load_game() has successfully completed.
@ -1858,7 +2092,7 @@ void retro_get_system_info(struct retro_system_info *info);
* variable if needed. * variable if needed.
* E.g. geom.aspect_ratio might not be initialized if core doesn't * E.g. geom.aspect_ratio might not be initialized if core doesn't
* desire a particular aspect ratio. */ * desire a particular aspect ratio. */
void retro_get_system_av_info(struct retro_system_av_info *info); RETRO_API 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 * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all
@ -1868,10 +2102,10 @@ void retro_get_system_av_info(struct retro_system_av_info *info);
* hint to the libretro core when a core cannot automatically detect the * 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 * appropriate input device type on its own. It is also relevant when a
* core can change its behavior depending on device type. */ * core can change its behavior depending on device type. */
void retro_set_controller_port_device(unsigned port, unsigned device); RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device);
/* Resets the current game. */ /* Resets the current game. */
void retro_reset(void); RETRO_API void retro_reset(void);
/* Runs the game for one video frame. /* Runs the game for one video frame.
* During retro_run(), input_poll callback must be called at least once. * During retro_run(), input_poll callback must be called at least once.
@ -1881,7 +2115,7 @@ void retro_reset(void);
* a frame if GET_CAN_DUPE returns true. * a frame if GET_CAN_DUPE returns true.
* In this case, the video callback can take a NULL argument for data. * In this case, the video callback can take a NULL argument for data.
*/ */
void retro_run(void); RETRO_API void retro_run(void);
/* Returns the amount of data the implementation requires to serialize /* Returns the amount of data the implementation requires to serialize
* internal state (save states). * internal state (save states).
@ -1889,35 +2123,35 @@ void retro_run(void);
* returned size is never allowed to be larger than a previous returned * returned size is never allowed to be larger than a previous returned
* value, to ensure that the frontend can allocate a save state buffer once. * value, to ensure that the frontend can allocate a save state buffer once.
*/ */
size_t retro_serialize_size(void); RETRO_API size_t retro_serialize_size(void);
/* Serializes internal state. If failed, or size is lower than /* Serializes internal state. If failed, or size is lower than
* retro_serialize_size(), it should return false, true otherwise. */ * retro_serialize_size(), it should return false, true otherwise. */
bool retro_serialize(void *data, size_t size); RETRO_API bool retro_serialize(void *data, size_t size);
bool retro_unserialize(const void *data, size_t size); RETRO_API bool retro_unserialize(const void *data, size_t size);
void retro_cheat_reset(void); RETRO_API void retro_cheat_reset(void);
void retro_cheat_set(unsigned index, bool enabled, const char *code); RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
/* Loads a game. */ /* Loads a game. */
bool retro_load_game(const struct retro_game_info *game); RETRO_API bool retro_load_game(const struct retro_game_info *game);
/* Loads a "special" kind of game. Should not be used, /* Loads a "special" kind of game. Should not be used,
* except in extreme cases. */ * except in extreme cases. */
bool retro_load_game_special( RETRO_API bool retro_load_game_special(
unsigned game_type, unsigned game_type,
const struct retro_game_info *info, size_t num_info const struct retro_game_info *info, size_t num_info
); );
/* Unloads a currently loaded game. */ /* Unloads a currently loaded game. */
void retro_unload_game(void); RETRO_API void retro_unload_game(void);
/* Gets region of game. */ /* Gets region of game. */
unsigned retro_get_region(void); RETRO_API unsigned retro_get_region(void);
/* Gets region of memory. */ /* Gets region of memory. */
void *retro_get_memory_data(unsigned id); RETRO_API void *retro_get_memory_data(unsigned id);
size_t retro_get_memory_size(unsigned id); RETRO_API size_t retro_get_memory_size(unsigned id);
#ifdef __cplusplus #ifdef __cplusplus
} }