+ /* 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 /* Old name, kept for compatibility. */
+#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30
+ /* const char ** --
+ * Returns the "core assets" 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, unless there is no
+ * save directory available. The save directory should be used to
+ * store SRAM, memory cards, high scores, etc, if the libretro core
+ * cannot use the regular memory interface (retro_get_memory_data()).
+ *
+ * If the frontend cannot designate a save directory, it will return
+ * NULL to indicate that the core should attempt to operate without a
+ * save directory set.
+ *
+ * NOTE: early libretro cores used the system directory for save
+ * files. Cores that need to be backwards-compatible can still check
+ * GET_SYSTEM_DIRECTORY.
+ */
+#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 reinitialization.
+ * This call is not a free pass for not trying to provide
+ * correct values in retro_get_system_av_info(). If you need to change
+ * things like aspect ratio or nominal width/height,
+ * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant
+ * of SET_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 Nintendo's 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 subclasses 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 specifcally
+ * provided by the Libretro API.
+ *
+ * In order for a frontend to understand the workings of those devices,
+ * they must be defined as a specialized subclass of the generic device
+ * types already defined in the libretro API.
+ *
+ * The core must pass an array of const struct retro_controller_info which
+ * is terminated with a blanked out struct. Each element of the
+ * retro_controller_info struct corresponds to the ascending port index
+ * that is passed to retro_set_controller_port_device() when that function
+ * is called to indicate to the core that the frontend has changed the
+ * active device subclass. SEE ALSO: retro_set_controller_port_device()
+ *
+ * The ascending input port indexes provided by the core in the struct
+ * are generally presented by frontends as ascending User # or Player #,
+ * such as Player 1, Player 2, Player 3, etc. Which device subclasses are
+ * supported can vary per input port.
+ *
+ * The first inner element of each entry in the retro_controller_info array
+ * is a retro_controller_description struct that specifies the names and
+ * codes of all device subclasses that are available for the corresponding
+ * User or Player, beginning with the generic Libretro device that the
+ * subclasses are derived from. The second inner element of each entry is the
+ * total number of subclasses that are listed in the retro_controller_description.
+ *
+ * NOTE: Even if special device types are set in the libretro core,
+ * libretro should only poll input based on the base input device types.
+ */
+#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* const struct retro_memory_map * --
+ * This environment call lets a libretro core tell the frontend
+ * about the memory maps this core emulates.
+ * This can be used to implement, for example, cheats in a core-agnostic way.
+ *
+ * Should only be used by emulators; it doesn't make much sense for
+ * anything else.
+ * It is recommended to expose all relevant pointers through
+ * retro_get_memory_* as well.
+ *
+ * Can be called from retro_init and retro_load_game.
+ */
+#define RETRO_ENVIRONMENT_SET_GEOMETRY 37
+ /* const struct retro_game_geometry * --
+ * This environment call is similar to SET_SYSTEM_AV_INFO for changing
+ * video parameters, but provides a guarantee that drivers will not be
+ * reinitialized.
+ * This can only be called from within retro_run().
+ *
+ * The purpose of this call is to allow a core to alter nominal
+ * width/heights as well as aspect ratios on-the-fly, which can be
+ * useful for some emulators to change in run-time.
+ *
+ * max_width/max_height arguments are ignored and cannot be changed
+ * with this call as this could potentially require a reinitialization or a
+ * non-constant time operation.
+ * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required.
+ *
+ * A frontend must guarantee that this environment call completes in
+ * constant time.
+ */
+#define RETRO_ENVIRONMENT_GET_USERNAME 38
+ /* const char **
+ * Returns the specified username of the frontend, if specified by the user.
+ * This username can be used as a nickname for a core that has online facilities
+ * or any other mode where personalization of the user is desirable.
+ * The returned value can be NULL.
+ * If this environ callback is used by a core that requires a valid username,
+ * a default username should be specified by the core.
+ */
+#define RETRO_ENVIRONMENT_GET_LANGUAGE 39
+ /* unsigned * --
+ * Returns the specified language of the frontend, if specified by the user.
+ * 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).
+ */
+#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.
+ */
+#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.
+ */
+#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_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* N/A (null) * --
+ * The frontend will try to use a 'shared' hardware context (mostly applicable
+ * to OpenGL) when a hardware context is being set up.
+ *
+ * Returns true if the frontend supports shared hardware contexts and false
+ * if the frontend does not support shared hardware contexts.
+ *
+ * This will do nothing on its own until SET_HW_RENDER env callbacks are
+ * being used.
+ */
+#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_vfs_interface_info * --
+ * Gets access to the VFS interface.
+ * VFS presence needs to be queried prior to load_game or any
+ * get_system/save/other_directory being called to let front end know
+ * core supports VFS before it starts handing out paths.
+ * It is recomended to do so in retro_set_environment
+ */
+#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_led_interface * --
+ * Gets an interface which is used by a libretro core to set
+ * state of LEDs.
+ */
+#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* int * --
+ * Tells the core if the frontend wants audio or video.
+ * If disabled, the frontend will discard the audio or video,
+ * so the core may decide to skip generating a frame or generating audio.
+ * This is mainly used for increasing performance.
+ * Bit 0 (value 1): Enable Video
+ * Bit 1 (value 2): Enable Audio
+ * Bit 2 (value 4): Use Fast Savestates.
+ * Bit 3 (value 8): Hard Disable Audio
+ * Other bits are reserved for future use and will default to zero.
+ * If video is disabled:
+ * * The frontend wants the core to not generate any video,
+ * including presenting frames via hardware acceleration.
+ * * The frontend's video frame callback will do nothing.
+ * * After running the frame, the video output of the next frame should be
+ * no different than if video was enabled, and saving and loading state
+ * should have no issues.
+ * If audio is disabled:
+ * * The frontend wants the core to not generate any audio.
+ * * The frontend's audio callbacks will do nothing.
+ * * After running the frame, the audio output of the next frame should be
+ * no different than if audio was enabled, and saving and loading state
+ * should have no issues.
+ * Fast Savestates:
+ * * Guaranteed to be created by the same binary that will load them.
+ * * Will not be written to or read from the disk.
+ * * Suggest that the core assumes loading state will succeed.
+ * * Suggest that the core updates its memory buffers in-place if possible.
+ * * Suggest that the core skips clearing memory.
+ * * Suggest that the core skips resetting the system.
+ * * Suggest that the core may skip validation steps.
+ * Hard Disable Audio:
+ * * Used for a secondary core when running ahead.
+ * * Indicates that the frontend will never need audio from the core.
+ * * Suggests that the core may stop synthesizing audio, but this should not
+ * compromise emulation accuracy.
+ * * Audio output for the next frame does not matter, and the frontend will
+ * never need an accurate audio state in the future.
+ * * State will never be saved when using Hard Disable Audio.
+ */
+#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_midi_interface ** --
+ * Returns a MIDI interface that can be used for raw data I/O.
+ */
+
+#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* bool * --
+ * Boolean value that indicates whether or not the frontend is in
+ * fastforwarding mode.
+ */
+
+#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* float * --
+ * Float value that lets us know what target refresh rate
+ * is curently in use by the frontend.
+ *
+ * The core can use the returned value to set an ideal
+ * refresh rate/framerate.
+ */
+
+#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* bool * --
+ * Boolean value that indicates whether or not the frontend supports
+ * input bitmasks being returned by retro_input_state_t. The advantage
+ * of this is that retro_input_state_t has to be only called once to
+ * grab all button states instead of multiple times.
+ *
+ * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
+ * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD).
+ * It will return a bitmask of all the digital buttons.
+ */
+
+/* VFS functionality */
+
+/* File paths:
+ * File paths passed as parameters when using this API shall be well formed UNIX-style,
+ * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator.
+ * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead).
+ * Other than the directory separator, cores shall not make assumptions about path format:
+ * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths.
+ * Cores may replace the basename or remove path components from the end, and/or add new components;
+ * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end.
+ * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much.
+ * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable).
+ * Cores are allowed to try using them, but must remain functional if the front rejects such requests.
+ * Cores are encouraged to use the libretro-common filestream functions for file I/O,
+ * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate
+ * and provide platform-specific fallbacks in cases where front ends do not support VFS. */
+
+/* Opaque file handle
+ * Introduced in VFS API v1 */
+struct retro_vfs_file_handle;
+
+/* Opaque directory handle
+ * Introduced in VFS API v3 */
+struct retro_vfs_dir_handle;
+
+/* File open flags
+ * Introduced in VFS API v1 */
+#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */
+#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */
+#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/
+#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */
+
+/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use,
+ and how they react to unlikely external interference (for example someone else writing to that file,
+ or the file's server going down), behavior will not change. */
+#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0)
+/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */
+#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0)
+
+/* Seek positions */
+#define RETRO_VFS_SEEK_POSITION_START 0
+#define RETRO_VFS_SEEK_POSITION_CURRENT 1
+#define RETRO_VFS_SEEK_POSITION_END 2
+
+/* stat() result flags
+ * Introduced in VFS API v3 */
+#define RETRO_VFS_STAT_IS_VALID (1 << 0)
+#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1)
+#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2)
+
+/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle
+ * Introduced in VFS API v1 */
+typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream);
+
+/* Open a file for reading or writing. If path points to a directory, this will
+ * fail. Returns the opaque file handle, or NULL for error.
+ * Introduced in VFS API v1 */
+typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints);
+
+/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure.
+ * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream);
+
+/* Return the size of the file in bytes, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream);
+
+/* Truncate file to specified size. Returns 0 on success or -1 on error
+ * Introduced in VFS API v2 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length);
+
+/* Get the current read / write position for the file. Returns -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream);
+
+/* Set the current read/write position for the file. Returns the new position, -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position);
+
+/* Read data from a file. Returns the number of bytes read, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len);
+
+/* Write data to a file. Returns the number of bytes written, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len);
+
+/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure.
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream);
+
+/* Delete the specified file. Returns 0 on success, -1 on failure
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path);
+
+/* Rename the specified file. Returns 0 on success, -1 on failure
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path);
+
+/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid.
+ * Additionally stores file size in given variable, unless NULL is given.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size);
+
+/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir);
+
+/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error.
+ * Support for the include_hidden argument may vary depending on the platform.
+ * Introduced in VFS API v3 */
+typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden);
+
+/* Read the directory entry at the current position, and move the read pointer to the next position.
+ * Returns true on success, false if already on the last entry.
+ * Introduced in VFS API v3 */
+typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Get the name of the last entry read. Returns a string on success, or NULL for error.
+ * The returned string pointer is valid until the next call to readdir or closedir.
+ * Introduced in VFS API v3 */
+typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error).
+ * Introduced in VFS API v3 */
+typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure.
+ * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream);
+
+struct retro_vfs_interface
+{
+ /* VFS API v1 */
+ retro_vfs_get_path_t get_path;
+ retro_vfs_open_t open;
+ retro_vfs_close_t close;
+ retro_vfs_size_t size;
+ retro_vfs_tell_t tell;
+ retro_vfs_seek_t seek;
+ retro_vfs_read_t read;
+ retro_vfs_write_t write;
+ retro_vfs_flush_t flush;
+ retro_vfs_remove_t remove;
+ retro_vfs_rename_t rename;
+ /* VFS API v2 */
+ retro_vfs_truncate_t truncate;
+ /* VFS API v3 */
+ retro_vfs_stat_t stat;
+ retro_vfs_mkdir_t mkdir;
+ retro_vfs_opendir_t opendir;
+ retro_vfs_readdir_t readdir;
+ retro_vfs_dirent_get_name_t dirent_get_name;
+ retro_vfs_dirent_is_dir_t dirent_is_dir;
+ retro_vfs_closedir_t closedir;
+};
+
+struct retro_vfs_interface_info
+{
+ /* Set by core: should this be higher than the version the front end supports,
+ * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call
+ * Introduced in VFS API v1 */
+ uint32_t required_interface_version;
+
+ /* Frontend writes interface pointer here. The frontend also sets the actual
+ * version, must be at least required_interface_version.
+ * Introduced in VFS API v1 */
+ struct retro_vfs_interface *iface;
+};
+
+enum retro_hw_render_interface_type
+{
+ RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
+ RETRO_HW_RENDER_INTERFACE_D3D9 = 1,
+ RETRO_HW_RENDER_INTERFACE_D3D10 = 2,
+ RETRO_HW_RENDER_INTERFACE_D3D11 = 3,
+ RETRO_HW_RENDER_INTERFACE_D3D12 = 4,
+ RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5,
+ 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;
+};
+
+typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state);
+struct retro_led_interface
+{
+ retro_set_led_state_t set_led_state;
+};
+
+/* Retrieves the current state of the MIDI input.
+ * Returns true if it's enabled, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void);
+
+/* Retrieves the current state of the MIDI output.
+ * Returns true if it's enabled, false otherwise */
+typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void);
+
+/* Reads next byte from the input stream.
+ * Returns true if byte is read, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte);
+
+/* Writes byte to the output stream.
+ * 'delta_time' is in microseconds and represent time elapsed since previous write.
+ * Returns true if byte is written, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time);
+
+/* Flushes previously written data.
+ * Returns true if successful, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void);
+
+struct retro_midi_interface
+{
+ retro_midi_input_enabled_t input_enabled;
+ retro_midi_output_enabled_t output_enabled;
+ retro_midi_read_t read;
+ retro_midi_write_t write;
+ retro_midi_flush_t flush;
+};
+
+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;
+};
+
+/* 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_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_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */
+#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */
+#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */
+#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
+#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
+#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
+#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */
+#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
+#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
+struct retro_memory_descriptor
+{
+ uint64_t flags;
+
+ /* Pointer to the start of the relevant ROM or RAM chip.
+ * It's strongly recommended to use 'offset' if possible, rather than
+ * doing math on the pointer.
+ *
+ * If the same byte is mapped my multiple descriptors, their descriptors
+ * must have the same pointer.
+ * If 'start' does not point to the first byte in the pointer, put the
+ * difference in 'offset' instead.
+ *
+ * May be NULL if there's nothing usable here (e.g. hardware registers and
+ * open bus). No flags should be set if the pointer is NULL.
+ * It's recommended to minimize the number of descriptors if possible,
+ * but not mandatory. */
+ void *ptr;
+ size_t offset;
+
+ /* This is the location in the emulated address space
+ * where the mapping starts. */
+ size_t start;
+
+ /* Which bits must be same as in 'start' for this mapping to apply.
+ * The first memory descriptor to claim a certain byte is the one
+ * that applies.
+ * A bit which is set in 'start' must also be set in this.
+ * Can be zero, in which case each byte is assumed mapped exactly once.
+ * In this case, 'len' must be a power of two. */
+ size_t select;
+
+ /* If this is nonzero, the set bits are assumed not connected to the
+ * memory chip's address pins. */
+ size_t disconnect;
+
+ /* This one tells the size of the current memory area.
+ * If, after start+disconnect are applied, the address is higher than
+ * this, the highest bit of the address is cleared.
+ *
+ * If the address is still too high, the next highest bit is cleared.
+ * Can be zero, in which case it's assumed to be infinite (as limited
+ * by 'select' and 'disconnect'). */
+ size_t len;
+
+ /* To go from emulated address to physical address, the following
+ * order applies:
+ * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */
+
+ /* 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),
+ * and may not be any other address space plus one or more 0-9A-F
+ * at the end.
+ * However, multiple memory descriptors for the same address space is
+ * allowed, and the address space name can be empty. NULL is treated
+ * as empty.
+ *
+ * Address space names are case sensitive, but avoid lowercase if possible.
+ * The same pointer may exist in multiple address spaces.
+ *
+ * Examples:
+ * blank+blank - valid (multiple things may be mapped in the same namespace)
+ * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace)
+ * 'A'+'B' - valid (neither is a prefix of each other)
+ * 'S'+blank - valid ('S' is not in 0-9A-F)
+ * 'a'+blank - valid ('a' is not in 0-9A-F)
+ * 'a'+'A' - valid (neither is a prefix of each other)
+ * 'AR'+blank - valid ('R' is not in 0-9A-F)
+ * 'ARB'+blank - valid (the B can't be part of the address either, because
+ * there is no namespace 'AR')
+ * blank+'B' - not valid, because it's ambigous which address space B1234
+ * would refer to.
+ * The length can't be used for that purpose; the frontend may want
+ * to append arbitrary data to an address, without a separator. */
+ 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
+ * certain namespace to infer the size of the address space.
+ *
+ * If the address space is larger than that, a mapping with .ptr=NULL
+ * should be at the end of the array, with .select set to all ones for
+ * as long as the address space is big.
+ *
+ * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags):
+ * SNES WRAM:
+ * .start=0x7E0000, .len=0x20000
+ * (Note that this must be mapped before the ROM in most cases; some of the
+ * ROM mappers
+ * try to claim $7E0000, or at least $7E8000.)
+ * SNES SPC700 RAM:
+ * .addrspace="S", .len=0x10000
+ * SNES WRAM mirrors:
+ * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000
+ * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000
+ * SNES WRAM mirrors, alternate equivalent descriptor:
+ * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF
+ * (Various similar constructions can be created by combining parts of
+ * the above two.)
+ * SNES LoROM (512KB, mirrored a couple of times):
+ * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024
+ * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024
+ * SNES HiROM (4MB):
+ * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024
+ * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024
+ * SNES ExHiROM (8MB):
+ * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024
+ * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024
+ * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024
+ * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024
+ * Clarify the size of the address space:
+ * .ptr=NULL, .select=0xFFFFFF
+ * .len can be implied by .select in many of them, but was included for clarity.
+ */
+
+struct retro_memory_map
+{
+ const struct retro_memory_descriptor *descriptors;
+ unsigned num_descriptors;
+};
+
+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
+{
+ /* The extension associated with a memory type, e.g. "psram". */
+ const char *extension;
+
+ /* The memory type for retro_get_memory(). This should be at
+ * least 0x100 to avoid conflict with standardized
+ * libretro memory types. */
+ unsigned type;
+};
+
+struct retro_subsystem_rom_info
+{
+ /* Describes what the content is (SGB BIOS, GB ROM, etc). */
+ const char *desc;
+
+ /* Same definition as retro_get_system_info(). */
+ const char *valid_extensions;
+
+ /* Same definition as retro_get_system_info(). */
+ bool need_fullpath;
+
+ /* Same definition as retro_get_system_info(). */
+ bool block_extract;
+
+ /* This is set if the content is required to load a game.
+ * If this is set to false, a zeroed-out retro_game_info can be passed. */
+ bool required;
+
+ /* Content can have multiple associated persistent
+ * memory types (retro_get_memory()). */
+ const struct retro_subsystem_memory_info *memory;
+ unsigned num_memory;
+};
+
+struct retro_subsystem_info
+{
+ /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */
+ const char *desc;
+
+ /* 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 content file. The first entry is assumed to be the
+ * "most significant" content for frontend purposes.
+ * E.g. with Super GameBoy, the first content should be the GameBoy ROM,
+ * as it is the most "significant" content to a user.
+ * If a frontend creates new file paths based on the content used
+ * (e.g. savestates), it should use the path for the first ROM to do so. */
+ const struct retro_subsystem_rom_info *roms;
+
+ /* Number of content files associated with a subsystem. */
+ unsigned num_roms;
+
+ /* The type passed to retro_load_game_special(). */
+ unsigned id;
+};
+
+typedef void (RETRO_CALLCONV *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_CALLCONV *retro_get_proc_address_t)(const char *sym);
+
+struct retro_get_proc_address_interface
+{
+ retro_get_proc_address_t get_proc_address;
+};