diff --git a/Makefile.common b/Makefile.common index c25caef3..0023269a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -17,7 +17,11 @@ SOURCES_C := $(CORE_DIR)/sdl/SDL_error.c \ $(CORE_DIR)/sdl/video/SDL_surface.c ifneq ($(STATIC_LINKING), 1) -SOURCES_C += $(CORE_DIR)/libretro/libretro-common/streams/file_stream.c +SOURCES_C += $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ + $(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \ + $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ + $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ + $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c endif SOURCES_CXX := $(CORE_DIR)/ai/ai.cpp \ diff --git a/nxengine/graphics/nxsurface.cpp b/nxengine/graphics/nxsurface.cpp index 27820228..2a73da20 100644 --- a/nxengine/graphics/nxsurface.cpp +++ b/nxengine/graphics/nxsurface.cpp @@ -1,12 +1,14 @@ #include #include + +#include + #include "../settings.h" #include "../config.h" #include "graphics.h" #include "nxsurface.h" #include "nxsurface.fdh" -#include "../libretro/libretro.h" #include "../nx.h" #include "../extract-auto/cachefiles.h" diff --git a/nxengine/libretro/libretro-common/include/boolean.h b/nxengine/libretro/libretro-common/include/boolean.h index 6ce2b83c..2c18ef76 100644 --- a/nxengine/libretro/libretro-common/include/boolean.h +++ b/nxengine/libretro/libretro-common/include/boolean.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 The RetroArch team +/* Copyright (C) 2010-2017 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (boolean.h). diff --git a/nxengine/libretro/libretro-common/include/compat/strl.h b/nxengine/libretro/libretro-common/include/compat/strl.h index 465a75ee..9aa93e92 100644 --- a/nxengine/libretro/libretro-common/include/compat/strl.h +++ b/nxengine/libretro/libretro-common/include/compat/strl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2016 The RetroArch team +/* Copyright (C) 2010-2017 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (strl.h). @@ -30,9 +30,9 @@ #include "../../../config.h" #endif -#ifdef __cplusplus -extern "C" { -#endif +#include + +RETRO_BEGIN_DECLS #ifdef __MACH__ #ifndef HAVE_STRL @@ -41,7 +41,7 @@ extern "C" { #endif #ifndef HAVE_STRL -/* Avoid possible naming collisions during link since +/* Avoid possible naming collisions during link since * we prefer to use the actual name. */ #define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size) @@ -52,9 +52,9 @@ size_t strlcat(char *dest, const char *source, size_t size); #endif -#ifdef __cplusplus -} -#endif +char *strldup(const char *s, size_t n); + +RETRO_END_DECLS #endif diff --git a/nxengine/libretro/libretro.h b/nxengine/libretro/libretro-common/include/libretro.h similarity index 85% rename from nxengine/libretro/libretro.h rename to nxengine/libretro/libretro-common/include/libretro.h index b100865c..7362725a 100644 --- a/nxengine/libretro/libretro.h +++ b/nxengine/libretro/libretro-common/include/libretro.h @@ -77,7 +77,7 @@ extern "C" { # endif #endif -/* Used for checking API/ABI mismatches that can break libretro +/* Used for checking API/ABI mismatches that can break libretro * implementations. * It is not incremented for compatible changes to the API. */ @@ -87,13 +87,13 @@ extern "C" { * Libretro's fundamental device abstractions. * * Libretro's input system consists of some standardized device types, - * such as a joypad (with/without analog), mouse, keyboard, lightgun + * such as a joypad (with/without analog), mouse, keyboard, lightgun * and a pointer. * - * The functionality of these devices are fixed, and individual cores + * The functionality of these devices are fixed, and individual cores * map their own concept of a controller to libretro's 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 + * 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. */ @@ -104,43 +104,50 @@ extern "C" { /* Input disabled. */ #define RETRO_DEVICE_NONE 0 -/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo - * controller, but with additional L2/R2/L3/R3 buttons, similar to a +/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo + * controller, but with additional L2/R2/L3/R3 buttons, similar to a * PS1 DualShock. */ #define RETRO_DEVICE_JOYPAD 1 /* The mouse is a simple mouse, similar to Super Nintendo's mouse. * X and Y coordinates are reported relatively to last poll (poll callback). - * It is up to the libretro implementation to keep track of where the mouse + * It is up to the libretro implementation to keep track of where the mouse * pointer is supposed to be on the screen. - * The frontend must make sure not to interfere with its own hardware + * The frontend must make sure not to interfere with its own hardware * mouse pointer. */ #define RETRO_DEVICE_MOUSE 2 /* KEYBOARD device lets one poll for raw key pressed. - * It is poll based, so input callback will return with the current + * 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. */ +/* LIGHTGUN device is similar to Guncon-2 for PlayStation 2. + * It reports X/Y coordinates in screen space (similar to the pointer) + * in the range [-0x8000, 0x7fff] in both axes, with zero being center. + * As well as reporting on/off screen state. It features a trigger, + * start/select buttons, auxiliary action buttons and a + * directional pad. A forced off-screen shot can be requested for + * auto-reloading function in some games. + */ #define RETRO_DEVICE_LIGHTGUN 4 /* The ANALOG device is an extension to JOYPAD (RetroPad). - * Similar to DualShock it adds two analog sticks. - * This is treated as a separate device type as it returns values in the - * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. - * Positive Y axis is down. - * Only use ANALOG type when polling for analog values of the axes. + * Similar to DualShock2 it adds two analog sticks and all buttons can + * be analog. This is treated as a separate device type as it returns + * axis values in the full analog range of [-0x8000, 0x7fff]. + * Positive X axis is right. Positive Y axis is down. + * Buttons are returned in the range [0, 0x7fff]. + * Only use ANALOG type when polling for analog values. */ #define RETRO_DEVICE_ANALOG 5 /* Abstracts the concept of a pointing mechanism, e.g. touch. - * This allows libretro to query in absolute coordinates where on the + * This allows libretro to query in absolute coordinates where on the * screen a mouse (or something similar) is being placed. * For a touch centric device, coordinates reported are the coordinates * of the press. @@ -148,33 +155,34 @@ extern "C" { * Coordinates in X and Y are reported as: * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, * and 0x7fff corresponds to the far right/bottom of the screen. - * The "screen" is here defined as area that is passed to the frontend and + * The "screen" is here defined as area that is passed to the frontend and * later displayed on the monitor. * * The frontend is free to scale/resize this screen as it sees fit, however, - * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the + * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the * game image, etc. * - * To check if the pointer coordinates are valid (e.g. a touch display + * 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 on a desktop, PRESSED will usually correspond to the + * 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 + * For multi-touch, the index variable can be used to successively query * more presses. * If index = 0 returns true for _PRESSED, coordinates can be extracted - * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with + * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with * index = 1, and so on. - * Eventually _PRESSED will return false for an index. No further presses + * Eventually _PRESSED will return false for an index. No further presses * are registered at this point. */ #define RETRO_DEVICE_POINTER 6 /* Buttons for the RetroPad (JOYPAD). - * The placement of these is equivalent to placements on the + * The placement of these is equivalent to placements on the * Super Nintendo controller. - * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ + * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. + * Also used as id values for RETRO_DEVICE_INDEX_ANALOG_BUTTON */ #define RETRO_DEVICE_ID_JOYPAD_B 0 #define RETRO_DEVICE_ID_JOYPAD_Y 1 #define RETRO_DEVICE_ID_JOYPAD_SELECT 2 @@ -193,10 +201,11 @@ extern "C" { #define RETRO_DEVICE_ID_JOYPAD_R3 15 /* Index / Id values for ANALOG device. */ -#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 -#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 -#define RETRO_DEVICE_ID_ANALOG_X 0 -#define RETRO_DEVICE_ID_ANALOG_Y 1 +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 /* Id values for MOUSE. */ #define RETRO_DEVICE_ID_MOUSE_X 0 @@ -208,15 +217,30 @@ extern "C" { #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. */ -#define RETRO_DEVICE_ID_LIGHTGUN_X 0 -#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 -#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 -#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 -#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 -#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 -#define RETRO_DEVICE_ID_LIGHTGUN_START 6 +#define RETRO_DEVICE_ID_MOUSE_BUTTON_4 9 +#define RETRO_DEVICE_ID_MOUSE_BUTTON_5 10 + +/* Id values for LIGHTGUN. */ +#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X 13 /*Absolute Position*/ +#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y 14 /*Absolute*/ +#define RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN 15 /*Status Check*/ +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_RELOAD 16 /*Forced off-screen shot*/ +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_A 3 +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_B 4 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 +#define RETRO_DEVICE_ID_LIGHTGUN_SELECT 7 +#define RETRO_DEVICE_ID_LIGHTGUN_AUX_C 8 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP 9 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN 10 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT 11 +#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT 12 +/* deprecated */ +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 /*Relative Position*/ +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 /*Relative*/ +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 /*Use Aux:A*/ +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 /*Use Aux:B*/ +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 /*Use Start*/ /* Id values for POINTER. */ #define RETRO_DEVICE_ID_POINTER_X 0 @@ -249,11 +273,11 @@ enum retro_language RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ - RETRO_LANGUAGE_DUMMY = INT_MAX + RETRO_LANGUAGE_DUMMY = INT_MAX }; /* Passed to retro_get_memory_data/size(). - * If the memory type doesn't apply to the + * If the memory type doesn't apply to the * implementation NULL/0 can be returned. */ #define RETRO_MEMORY_MASK 0xff @@ -443,7 +467,7 @@ enum retro_mod RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; -/* If set, this call is not part of the public libretro API yet. It can +/* If set, this call is not part of the public libretro API yet. It can * change or be removed at any time. */ #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 /* Environment callback to be used internally in frontend. */ @@ -453,11 +477,11 @@ enum retro_mod #define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- * Sets screen rotation of graphics. * Is only implemented if rotation can be accelerated by hardware. - * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, + * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, * 270 degrees counter-clockwise respectively. */ #define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- - * Boolean value whether or not the implementation should use overscan, + * Boolean value whether or not the implementation should use overscan, * or crop away overscan. */ #define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- @@ -465,15 +489,15 @@ enum retro_mod * passing NULL to video frame callback. */ - /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), + /* 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 + * 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 via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * 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) -- @@ -501,15 +525,15 @@ enum retro_mod #define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 /* const char ** -- * Returns the "system" directory of the frontend. - * This directory can be used to store system specific + * This directory can be used to store system specific * content such as BIOSes, configuration data, 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. * - * NOTE: Some cores used this folder also for "save" data such as + * 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 + * This is now discouraged, and if possible, cores should try to * use the new GET_SAVE_DIRECTORY. */ #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 @@ -517,19 +541,19 @@ enum retro_mod * Sets the internal pixel format used by the implementation. * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. * This pixel format however, is deprecated (see enum retro_pixel_format). - * If the call returns false, the frontend does not support this pixel + * If the call returns false, the frontend does not support this pixel * format. * - * This function should be called inside retro_load_game() or + * This function should be called inside retro_load_game() or * retro_get_system_av_info(). */ #define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 /* const struct retro_input_descriptor * -- * Sets an array of retro_input_descriptors. * It is up to the frontend to present this in a usable way. - * The array is terminated by retro_input_descriptor::description + * The array is terminated by retro_input_descriptor::description * being set to NULL. - * This function can be called at any time, but it is recommended + * This function can be called at any time, but it is recommended * to call it as early as possible. */ #define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 @@ -538,52 +562,52 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 /* const struct retro_disk_control_callback * -- - * Sets an interface which frontend can use to eject and insert + * Sets an interface which frontend can use to eject and insert * disk images. - * This is used for games which consist of multiple images and + * This is used for games which consist of multiple images and * must be manually swapped out by the user (e.g. PSX). */ #define RETRO_ENVIRONMENT_SET_HW_RENDER 14 /* struct retro_hw_render_callback * -- - * Sets an interface to let a libretro core render with + * Sets an interface to let a libretro core render with * hardware acceleration. * Should be called in retro_load_game(). - * If successful, libretro cores will be able to render to a + * If successful, libretro cores will be able to render to a * frontend-provided framebuffer. - * The size of this framebuffer will be at least as large as + * The size of this framebuffer will be at least as large as * max_width/max_height provided in get_av_info(). - * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or + * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or * NULL to retro_video_refresh_t. */ #define RETRO_ENVIRONMENT_GET_VARIABLE 15 /* struct retro_variable * -- * Interface to acquire user-defined information from environment * that cannot feasibly be supported in a multi-system way. - * 'key' should be set to a key which has already been set by + * 'key' should be set to a key which has already been set by * SET_VARIABLES. * 'data' will be set to a value or NULL. */ #define RETRO_ENVIRONMENT_SET_VARIABLES 16 /* const struct retro_variable * -- * Allows an implementation to signal the environment - * which variables it might want to check for later using + * which variables it might want to check for later using * GET_VARIABLE. - * This allows the frontend to present these variables to + * This allows the frontend to present these variables to * a user dynamically. - * This should be called as early as possible (ideally in + * This should be called as early as possible (ideally in * retro_set_environment). * - * 'data' points to an array of retro_variable structs + * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. - * retro_variable::key should be namespaced to not collide - * with other implementations' keys. E.g. A core called + * retro_variable::key should be namespaced to not collide + * with other implementations' keys. E.g. A core called * 'foo' should use keys named as 'foo_option'. - * retro_variable::value should contain a human readable - * description of the key as well as a '|' delimited list + * retro_variable::value should contain a human readable + * description of the key as well as a '|' delimited list * of expected values. * - * The number of possible options should be very limited, - * i.e. it should be feasible to cycle through options + * The number of possible options should be very limited, + * i.e. it should be feasible to cycle through options * without a keyboard. * * First entry should be treated as a default. @@ -591,11 +615,11 @@ enum retro_mod * Example entry: * { "foo_option", "Speed hack coprocessor X; false|true" } * - * Text before first ';' is description. This ';' must be - * followed by a space, and followed by a list of possible + * Text before first ';' is description. This ';' must be + * followed by a space, and followed by a list of possible * values split up with '|'. * - * Only strings are operated on. The possible values will + * Only strings are operated on. The possible values will * generally be displayed and stored as-is by the frontend. */ #define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 @@ -606,72 +630,72 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 /* const bool * -- - * If true, the libretro implementation supports calls to + * If true, the libretro implementation supports calls to * retro_load_game() with NULL as argument. * Used by cores which can run without particular game data. * This should be called within retro_set_environment() only. */ #define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 /* const char ** -- - * Retrieves the absolute path from where this libretro + * Retrieves the absolute path from where this libretro * implementation was loaded. - * NULL is returned if the libretro was loaded statically - * (i.e. linked statically to frontend), or if the path cannot be + * NULL is returned if the libretro was loaded statically + * (i.e. linked statically to frontend), or if the path cannot be * determined. - * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can + * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can * be loaded without ugly hacks. */ - - /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. + + /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. * It was not used by any known core at the time, * and was removed from the API. */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 /* const struct retro_audio_callback * -- - * Sets an interface which is used to notify a libretro core about audio + * Sets an interface which is used to notify a libretro core about audio * being available for writing. - * The callback can be called from any thread, so a core using this must + * The callback can be called from any thread, so a core using this must * have a thread safe audio implementation. - * It is intended for games where audio and video are completely + * It is intended for games where audio and video are completely * asynchronous and audio can be generated on the fly. - * This interface is not recommended for use with emulators which have + * This interface is not recommended for use with emulators which have * highly synchronous audio. * - * The callback only notifies about writability; the libretro core still + * The callback only notifies about writability; the libretro core still * has to call the normal audio callbacks - * to write audio. The audio callbacks must be called from within the + * to write audio. The audio callbacks must be called from within the * notification callback. * The amount of audio data to write is up to the implementation. * Generally, the audio callback will be called continously in a loop. * - * Due to thread safety guarantees and lack of sync between audio and - * video, a frontend can selectively disallow this interface based on - * internal configuration. A core using this interface must also + * Due to thread safety guarantees and lack of sync between audio and + * video, a frontend can selectively disallow this interface based on + * internal configuration. A core using this interface must also * implement the "normal" audio interface. * - * A libretro core using SET_AUDIO_CALLBACK should also make use of + * A libretro core using SET_AUDIO_CALLBACK should also make use of * SET_FRAME_TIME_CALLBACK. */ #define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 /* const struct retro_frame_time_callback * -- - * Lets the core know how much time has passed since last + * Lets the core know how much time has passed since last * invocation of retro_run(). - * The frontend can tamper with the timing to fake fast-forward, + * The frontend can tamper with the timing to fake fast-forward, * slow-motion, frame stepping, etc. - * In this case the delta time will use the reference value + * In this case the delta time will use the reference value * in frame_time_callback.. */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 /* struct retro_rumble_interface * -- - * Gets an interface which is used by a libretro core to set + * Gets an interface which is used by a libretro core to set * state of rumble motors in controllers. - * A strong and weak motor is supported, and they can be + * A strong and weak motor is supported, and they can be * controlled indepedently. */ #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 /* uint64_t * -- - * Gets a bitmask telling which device type are expected to be + * Gets a bitmask telling which device type are expected to be * handled properly in a call to retro_input_state_t. - * Devices which are not handled or recognized always return + * Devices which are not handled or recognized always return * 0 in retro_input_state_t. * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). * Should only be called in retro_run(). @@ -680,56 +704,56 @@ enum retro_mod /* struct retro_sensor_interface * -- * Gets access to the sensor interface. * The purpose of this interface is to allow - * setting state related to sensors such as polling rate, + * setting state related to sensors such as polling rate, * enabling/disable it entirely, etc. - * Reading sensor state is done via the normal + * Reading sensor state is done via the normal * input_state_callback API. */ #define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) /* struct retro_camera_callback * -- * Gets an interface to a video camera driver. - * A libretro core can use this interface to get access to a + * A libretro core can use this interface to get access to a * video camera. - * New video frames are delivered in a callback in same + * New video frames are delivered in a callback in same * thread as retro_run(). * * GET_CAMERA_INTERFACE should be called in retro_load_game(). * - * Depending on the camera implementation used, camera frames + * Depending on the camera implementation used, camera frames * will be delivered as a raw framebuffer, * or as an OpenGL texture directly. * - * The core has to tell the frontend here which types of + * The core has to tell the frontend here which types of * buffers can be handled properly. - * An OpenGL texture can only be handled when using a + * An OpenGL texture can only be handled when using a * libretro GL core (SET_HW_RENDER). - * It is recommended to use a libretro GL core when + * It is recommended to use a libretro GL core when * using camera interface. * - * The camera is not started automatically. The retrieved start/stop + * The camera is not started automatically. The retrieved start/stop * functions must be used to explicitly * start and stop the camera driver. */ #define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 /* struct retro_log_callback * -- - * Gets an interface for logging. This is useful for + * Gets an interface for logging. This is useful for * logging in a cross-platform way - * as certain platforms cannot use use stderr for logging. + * as certain platforms cannot use stderr for logging. * It also allows the frontend to * show logging information in a more suitable way. - * If this interface is not used, libretro cores should + * If this interface is not used, libretro cores should * log to stderr as desired. */ #define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 /* struct retro_perf_callback * -- - * Gets an interface for performance counters. This is useful - * for performance logging in a cross-platform way and for detecting + * 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 + * The purpose of this interface is to be able to retrieve * location-based information from the host device, * such as current latitude / longitude. */ @@ -737,7 +761,7 @@ enum retro_mod #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 + * 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. @@ -747,75 +771,75 @@ enum retro_mod #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, + * 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 + * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for * similar things before. - * They should still check GET_SYSTEM_DIRECTORY if they want to + * 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 + * 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 + * 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 + * 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 + * 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 + * 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 + * An eventual driver reinitialize will happen so that video and * audio callbacks - * happening after this call within the same retro_run() call will + * 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 + * 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 + * ***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 + * 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 + * 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 + * 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 + * Allows a libretro core to announce support for the * get_proc_address() interface. - * This interface allows for a standard way to extend libretro where + * 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 + * 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 + * 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 + * 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 + * 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 + * 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 + * 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 @@ -823,15 +847,15 @@ enum retro_mod */ #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 + * 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 + * 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 + * 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, @@ -839,52 +863,52 @@ enum retro_mod * 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 + * 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, + * 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 + * 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 + * Should only be used by emulators; it doesn't make much sense for * anything else. - * It is recommended to expose all relevant pointers through + * 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 + * 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 + * 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 + * 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 + * A frontend must guarantee that this environment call completes in * constant time. */ -#define RETRO_ENVIRONMENT_GET_USERNAME 38 +#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 + * 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, + * 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 @@ -923,6 +947,118 @@ enum retro_mod * writeable (and readable). */ +#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 */ + +/* Opaque file handle + * Introduced in VFS API v1 */ +struct retro_vfs_file_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) + +/* 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 succes, -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); + +/* 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 whence); + +/* 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); + +struct retro_vfs_interface +{ + 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; +}; + +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, @@ -1008,7 +1144,6 @@ struct retro_hw_render_context_negotiation_interface * 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_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ #define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ @@ -1022,56 +1157,56 @@ 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 + * 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 + * 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 + * 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 + * 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 + /* 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 + * 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. + * 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 + /* 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 + * 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 + * 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 + /* 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_-, + /* 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 + * 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 + * 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. @@ -1085,11 +1220,11 @@ struct retro_memory_descriptor * '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 + * '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 + * 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 + * 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; @@ -1111,32 +1246,32 @@ struct retro_memory_descriptor * 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 * (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 * 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 + * 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 + * (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 @@ -1145,7 +1280,7 @@ struct retro_memory_descriptor * .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 + * (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 @@ -1171,13 +1306,13 @@ struct retro_memory_map 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 + /* 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 + /* 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). */ @@ -1195,8 +1330,8 @@ 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 + /* The memory type for retro_get_memory(). This should be at + * least 0x100 to avoid conflict with standardized * libretro memory types. */ unsigned type; }; @@ -1215,11 +1350,11 @@ struct retro_subsystem_rom_info /* Same definition as retro_get_system_info(). */ bool block_extract; - /* This is set if the content is required to load a game. + /* 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 + /* Content can have multiple associated persistent * memory types (retro_get_memory()). */ const struct retro_subsystem_memory_info *memory; unsigned num_memory; @@ -1237,17 +1372,17 @@ struct retro_subsystem_info */ const char *ident; - /* Infos for each content file. The first entry is assumed to be the + /* 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, + * 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 + * 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; }; @@ -1258,13 +1393,13 @@ typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); * (None here so far). * * Get a symbol from a libretro core. - * Cores should only return symbols which are actual + * Cores should only return symbols which are actual * extensions to the libretro API. * - * Frontends should not use this to obtain symbols to standard + * 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, + * 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. */ @@ -1339,7 +1474,7 @@ struct retro_perf_counter typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void); /* 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). * */ typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); @@ -1353,9 +1488,9 @@ typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void); typedef void (RETRO_CALLCONV *retro_perf_log_t)(void); /* 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. - * 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. */ typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); @@ -1426,7 +1561,7 @@ enum retro_sensor_action #define RETRO_SENSOR_ACCELEROMETER_Y 1 #define RETRO_SENSOR_ACCELEROMETER_Z 2 -typedef bool (RETRO_CALLCONV *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); typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); @@ -1451,7 +1586,7 @@ typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); /* Stops the camera driver. Can only be called in retro_run(). */ 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. * retro_camera_start_t can be called in initialized callback. */ @@ -1461,36 +1596,36 @@ typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); * Width, height and pitch are similar to retro_video_refresh_t. * First pixel is top-left origin. */ -typedef void (RETRO_CALLCONV *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); /* A callback for when OpenGL textures are used. * * texture_id is a texture owned by camera driver. - * Its state or content should be considered immutable, except for things like + * Its state or content should be considered immutable, except for things like * texture filtering and clamping. * * texture_target is the texture target for the GL texture. - * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly + * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly * more depending on extensions. * - * affine points to a packed 3x3 column-major matrix used to apply an affine + * affine points to a packed 3x3 column-major matrix used to apply an affine * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) - * After transform, normalized texture coord (0, 0) should be bottom-left + * After transform, normalized texture coord (0, 0) should be bottom-left * and (1, 1) should be top-right (or (width, height) for RECTANGLE). * - * 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. */ -typedef void (RETRO_CALLCONV *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); struct retro_camera_callback { - /* Set by libretro core. + /* Set by libretro core. * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). */ - uint64_t caps; + uint64_t caps; /* Desired resolution for camera. Is only used as a hint. */ unsigned width; @@ -1504,22 +1639,22 @@ struct retro_camera_callback retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; /* 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; - /* Set by libretro core. Called after camera driver is initialized and + /* Set by libretro core. Called after camera driver is initialized and * ready to be started. * Can be NULL, in which this callback is not called. */ retro_camera_lifetime_status_t initialized; - /* Set by libretro core. Called right before camera driver is + /* Set by libretro core. Called right before camera driver is * deinitialized. * Can be NULL, in which this callback is not called. */ retro_camera_lifetime_status_t deinitialized; }; -/* Sets the interval of time and/or distance at which to update/poll +/* Sets the interval of time and/or distance at which to update/poll * location-based data. * * To ensure compatibility with all location-based implementations, @@ -1532,20 +1667,20 @@ typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_m unsigned interval_distance); /* 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). */ 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. */ 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. */ typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, 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. * retro_location_start_t can be called in initialized callback. */ @@ -1570,14 +1705,14 @@ enum retro_rumble_effect RETRO_RUMBLE_DUMMY = INT_MAX }; -/* Sets rumble state for joypad plugged in port 'port'. +/* Sets rumble state for joypad plugged in port 'port'. * Rumble effects are controlled independently, * and setting e.g. strong rumble does not override weak rumble. * Strength has a range of [0, 0xffff]. * - * 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. */ -typedef bool (RETRO_CALLCONV *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); struct retro_rumble_interface @@ -1588,10 +1723,10 @@ struct retro_rumble_interface /* Notifies libretro that audio data should be written. */ 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. - * False: Audio driver in frontend is paused or inactive. - * Audio callback will not be called until set_state has been + * False: Audio driver in frontend is paused or inactive. + * Audio callback will not be called until set_state has been * called with true. * Initial state is false (inactive). */ @@ -1603,11 +1738,11 @@ struct retro_audio_callback retro_audio_set_state_callback_t set_state; }; -/* Notifies a libretro core of time spent since last invocation +/* Notifies a libretro core of time spent since last invocation * of retro_run() in microseconds. * * It will be called right before retro_run() every frame. - * The frontend can tamper with timing to support cases like + * The frontend can tamper with timing to support cases like * fast-forward, slow-motion and framestepping. * * In those scenarios the reference frame time value will be used. */ @@ -1616,8 +1751,8 @@ typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec); struct retro_frame_time_callback { retro_frame_time_callback_t callback; - /* Represents the time of one frame. It is computed as - * 1000000 / fps, but the implementation will resolve the + /* Represents the time of one frame. It is computed as + * 1000000 / fps, but the implementation will resolve the * rounding to ensure that framestepping, etc is exact. */ retro_usec_t reference; }; @@ -1633,7 +1768,7 @@ 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, + * Also called first time video driver is initialized, * allowing libretro core to initialize resources. */ typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); @@ -1650,7 +1785,7 @@ enum retro_hw_context_type { RETRO_HW_CONTEXT_NONE = 0, /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ - RETRO_HW_CONTEXT_OPENGL = 1, + RETRO_HW_CONTEXT_OPENGL = 1, /* OpenGL ES 2.0. */ RETRO_HW_CONTEXT_OPENGLES2 = 2, /* Modern desktop core GL context. Use version_major/ @@ -1676,10 +1811,10 @@ struct retro_hw_render_callback /* 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 + * 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 + * 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 @@ -1704,48 +1839,48 @@ struct retro_hw_render_callback * TODO: Obsolete. */ 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. */ - /* Use conventional bottom-left origin convention. If false, + /* Use conventional bottom-left origin convention. If false, * standard libretro top-left origin semantics are used. * TODO: Move to GL specific interface. */ bool bottom_left_origin; - + /* Major version number for core GL context or GLES 3.1+. */ unsigned version_major; /* Minor version number for core GL context or GLES 3.1+. */ unsigned version_minor; - /* 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. * TODO: Obsolete? Maybe frontend should just always assume this ... */ bool cache_context; - /* The reset callback might still be called in extreme situations + /* 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 + * For optimal stability, set this to false, and allow context to be * reset at any time. */ - - /* A callback to be called before the context is destroyed in a + + /* A callback to be called before the context is destroyed in a * controlled way by the frontend. */ retro_hw_context_reset_t context_destroy; /* OpenGL resources can be deinitialized cleanly at this step. - * context_destroy can be set to NULL, in which resources will + * 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 + * 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 + * 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 + * and the libretro implementation must not try to free any OpenGL * resources in the subsequent context_reset. */ @@ -1753,7 +1888,7 @@ struct retro_hw_render_callback bool debug_context; }; -/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. +/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. * Called by the frontend in response to keyboard events. * down is set if the key is being pressed, or false if it is being released. * keycode is the RETROK value of the char. @@ -1761,16 +1896,16 @@ struct retro_hw_render_callback * key_modifiers is a set of RETROKMOD values or'ed together. * * The pressed/keycode state can be indepedent of the character. - * It is also possible that multiple characters are generated from a + * It is also possible that multiple characters are generated from a * single keypress. * Keycode events should be treated separately from character events. * However, when possible, the frontend should try to synchronize these. * If only a character is posted, keycode should be RETROK_UNKNOWN. * - * 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. */ -typedef void (RETRO_CALLCONV *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); struct retro_keyboard_callback @@ -1779,15 +1914,15 @@ struct retro_keyboard_callback }; /* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. - * Should be set for implementations which can swap out multiple disk + * Should be set for implementations which can swap out multiple disk * images in runtime. * * If the implementation can do this automatically, it should strive to do so. * However, there are cases where the user must manually do so. * - * Overview: To swap a disk image, eject the disk image with + * Overview: To swap a disk image, eject the disk image with * set_eject_state(true). - * Set the disk index with set_image_index(index). Insert the disk again + * Set the disk index with set_image_index(index). Insert the disk again * with set_eject_state(false). */ @@ -1805,7 +1940,7 @@ typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void); /* 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(). */ typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); @@ -1819,11 +1954,11 @@ struct retro_game_info; * Arguments to pass in info have same requirements as retro_load_game(). * Virtual disk tray must be ejected when calling this. * - * Replacing a disk image with info = NULL will remove the disk image + * Replacing a disk image with info = NULL will remove the disk image * from the internal list. * As a result, calls to get_image_index() can change. * - * E.g. replace_image_index(1, NULL), and previous get_image_index() + * E.g. replace_image_index(1, NULL), and previous get_image_index() * returned 4 before. * Index 1 will be removed, and the new index is 3. */ @@ -1832,7 +1967,7 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index, /* 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 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. */ typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); @@ -1863,7 +1998,7 @@ enum retro_pixel_format /* RGB565, native endian. * This pixel format is the recommended format to use if a 15/16-bit - * format is desired as it is the pixel format that is typically + * format is desired as it is the pixel format that is typically * available on a wide range of low-power devices. * * It is also natively supported in APIs like OpenGL ES. */ @@ -1893,43 +2028,43 @@ struct retro_input_descriptor /* Human readable description for parameters. * The pointer must remain valid until * retro_unload_game() is called. */ - const char *description; + const char *description; }; struct retro_system_info { - /* All pointers are owned by libretro implementation, and pointers must + /* All pointers are owned by libretro implementation, and pointers must * remain valid until retro_deinit() is called. */ - const char *library_name; /* Descriptive name of library. Should not + const char *library_name; /* Descriptive name of library. Should not * contain any version numbers, etc. */ const char *library_version; /* Descriptive version of core. */ - const char *valid_extensions; /* A string listing probably content - * extensions the core will be able to + const char *valid_extensions; /* A string listing probably content + * extensions the core will be able to * load, separated with pipe. * I.e. "bin|rom|iso". - * Typically used for a GUI to filter + * Typically used for a GUI to filter * out extensions. */ - /* If true, retro_load_game() is guaranteed to provide a valid pathname + /* If true, retro_load_game() is guaranteed to provide a valid pathname * in retro_game_info::path. * ::data and ::size are both invalid. * - * If false, ::data and ::size are guaranteed to be valid, but ::path + * If false, ::data and ::size are guaranteed to be valid, but ::path * might not be valid. * - * This is typically set to true for libretro implementations that must + * This is typically set to true for libretro implementations that must * load from file. - * Implementations should strive for setting this to false, as it allows + * Implementations should strive for setting this to false, as it allows * the frontend to perform patching, etc. */ - bool need_fullpath; + bool need_fullpath; - /* If true, the frontend is not allowed to extract any archives before + /* If true, the frontend is not allowed to extract any archives before * loading the real content. - * Necessary for certain libretro implementations that load games + * Necessary for certain libretro implementations that load games * from zipped archives. */ - bool block_extract; + bool block_extract; }; struct retro_game_geometry @@ -1961,14 +2096,14 @@ struct retro_system_av_info struct retro_variable { /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - * If NULL, obtains the complete environment string if more + * If NULL, obtains the complete environment string if more * complex parsing is necessary. - * The environment string is formatted as key-value pairs + * The environment string is formatted as key-value pairs * delimited by semicolons as so: * "key1=value1;key2=value2;..." */ const char *key; - + /* Value to be obtained. If key does not exist, it is set to NULL. */ const char *value; }; @@ -1983,7 +2118,7 @@ struct retro_game_info * of passing NULL, which will help more cores to succeed. * retro_system_info::need_fullpath requires * that this path is valid. */ - const void *data; /* Memory buffer of loaded game. Will be NULL + const void *data; /* Memory buffer of loaded game. Will be NULL * if need_fullpath was set. */ size_t size; /* Size of memory buffer. */ const char *meta; /* String of implementation specific meta-data. */ @@ -2021,25 +2156,25 @@ struct retro_framebuffer /* Callbacks */ -/* Environment callback. Gives implementations a way of performing +/* Environment callback. Gives implementations a way of performing * uncommon tasks. Extensible. */ 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). * * Width and height specify dimensions of buffer. * Pitch specifices length in bytes between two lines in buffer. * - * For performance reasons, it is highly recommended to have a frame + * For performance reasons, it is highly recommended to have a frame * that is packed in memory, i.e. pitch == width * byte_per_pixel. - * 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. */ typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, 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. * Format is signed 16-bit native endian. */ @@ -2057,20 +2192,20 @@ typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, /* Polls input. */ 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. * - * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that + * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that * have been set with retro_set_controller_port_device() * will still use the higher level RETRO_DEVICE_JOYPAD to request input. */ -typedef int16_t (RETRO_CALLCONV *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); -/* Sets callbacks. retro_set_environment() is guaranteed to be called +/* Sets callbacks. retro_set_environment() is guaranteed to be called * before retro_init(). * - * 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. */ RETRO_API void retro_set_environment(retro_environment_t); RETRO_API void retro_set_video_refresh(retro_video_refresh_t); @@ -2087,26 +2222,26 @@ RETRO_API void retro_deinit(void); * when the API is revised. */ 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. * Can be called at any time, even before retro_init(). */ RETRO_API void retro_get_system_info(struct retro_system_info *info); /* Gets information about system audio/video timings and geometry. * Can be called only after retro_load_game() has successfully completed. - * NOTE: The implementation of this function might not initialize every + * NOTE: The implementation of this function might not initialize every * 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. */ RETRO_API 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 + * 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 + * 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. */ RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); @@ -2115,18 +2250,18 @@ RETRO_API void retro_reset(void); /* Runs the game for one video frame. * During retro_run(), input_poll callback must be called at least once. - * + * * If a frame is not rendered for reasons where a game "dropped" a frame, - * this still counts as a frame, and retro_run() should explicitly dupe + * this still counts as a frame, and retro_run() should explicitly dupe * a frame if GET_CAN_DUPE returns true. * In this case, the video callback can take a NULL argument for data. */ 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). - * Between calls to retro_load_game() and retro_unload_game(), the - * returned size is never allowed to be larger than a previous returned + * Between calls to retro_load_game() and retro_unload_game(), the + * 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. */ RETRO_API size_t retro_serialize_size(void); diff --git a/nxengine/libretro/libretro-common/include/retro_assert.h b/nxengine/libretro/libretro-common/include/retro_assert.h new file mode 100644 index 00000000..3ef0300e --- /dev/null +++ b/nxengine/libretro/libretro-common/include/retro_assert.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_assert.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __RETRO_ASSERT_H +#define __RETRO_ASSERT_H + +#include + +#ifdef RARCH_INTERNAL +#define retro_assert(cond) do { \ + if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \ +} while(0) +#else +#define retro_assert(cond) assert(cond) +#endif + +#endif diff --git a/nxengine/libretro/libretro-common/include/retro_common.h b/nxengine/libretro/libretro-common/include/retro_common.h index d84cafb5..5938bea1 100644 --- a/nxengine/libretro/libretro-common/include/retro_common.h +++ b/nxengine/libretro/libretro-common/include/retro_common.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2016 The RetroArch team +/* Copyright (C) 2010-2017 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common.h). @@ -26,11 +26,12 @@ /* This file is designed to normalize the libretro-common compiling environment. It is not to be used in public API headers, as they should be designed as leanly as possible. -Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, +Nonetheless.. in the meantime, if you do something like use ssize_t, which is not fully portable, in a public API, you may need this. */ /* conditional compilation is handled inside here */ #include -#endif \ No newline at end of file +#endif + diff --git a/nxengine/libretro/libretro-common/include/retro_common_api.h b/nxengine/libretro/libretro-common/include/retro_common_api.h new file mode 100644 index 00000000..d637b964 --- /dev/null +++ b/nxengine/libretro/libretro-common/include/retro_common_api.h @@ -0,0 +1,107 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_common_api.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _LIBRETRO_COMMON_RETRO_COMMON_API_H +#define _LIBRETRO_COMMON_RETRO_COMMON_API_H + +/* +This file is designed to normalize the libretro-common compiling environment +for public API headers. This should be leaner than a normal compiling environment, +since it gets #included into other project's sources. +*/ + +/* ------------------------------------ */ + +/* +Ordinarily we want to put #ifdef __cplusplus extern "C" in C library +headers to enable them to get used by c++ sources. +However, we want to support building this library as C++ as well, so a +special technique is called for. +*/ + +#define RETRO_BEGIN_DECLS +#define RETRO_END_DECLS + +#ifdef __cplusplus + +#ifdef CXX_BUILD +/* build wants everything to be built as c++, so no extern "C" */ +#else +#undef RETRO_BEGIN_DECLS +#undef RETRO_END_DECLS +#define RETRO_BEGIN_DECLS extern "C" { +#define RETRO_END_DECLS } +#endif + +#else + +/* header is included by a C source file, so no extern "C" */ + +#endif + +/* +IMO, this non-standard ssize_t should not be used. +However, it's a good example of how to handle something like this. +*/ +#ifdef _MSC_VER +#ifndef HAVE_SSIZE_T +#define HAVE_SSIZE_T +#if defined(_WIN64) +typedef __int64 ssize_t; +#elif defined(_WIN32) +typedef int ssize_t; +#endif +#endif +#elif defined(__MACH__) +#include +#endif + +#ifdef _MSC_VER +#ifndef PRId64 +#define PRId64 "I64d" +#define PRIu64 "I64u" +#define PRIuPTR "Iu" +#endif +#else +#include +#endif +#define STRING_REP_INT64 "%" PRId64 +#define STRING_REP_UINT64 "%" PRIu64 +#define STRING_REP_USIZE "%" PRIuPTR + +/* +I would like to see retro_inline.h moved in here; possibly boolean too. + +rationale: these are used in public APIs, and it is easier to find problems +and write code that works the first time portably when theyre included uniformly +than to do the analysis from scratch each time you think you need it, for each feature. + +Moreover it helps force you to make hard decisions: if you EVER bring in boolean.h, +then you should pay the price everywhere, so you can see how much grief it will cause. + +Of course, another school of thought is that you should do as little damage as possible +in as few places as possible... +*/ + + +/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ +#endif diff --git a/nxengine/libretro/libretro-common/include/retro_environment.h b/nxengine/libretro/libretro-common/include/retro_environment.h new file mode 100644 index 00000000..12ee429d --- /dev/null +++ b/nxengine/libretro/libretro-common/include/retro_environment.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_environment.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_ENVIRONMENT_H +#define __LIBRETRO_SDK_ENVIRONMENT_H + +/* +This file is designed to create a normalized environment for compiling +libretro-common's private implementations, or any other sources which might +enjoy use of it's environment (RetroArch for instance). +This should be an elaborately crafted environment so that sources don't +need to be full of platform-specific workarounds. +*/ + +#if defined (__cplusplus) +#if 0 +printf("This is C++, version %d.\n", __cplusplus); +#endif +/* The expected values would be + * 199711L, for ISO/IEC 14882:1998 or 14882:2003 + */ + +#elif defined(__STDC__) +/* This is standard C. */ + +#if (__STDC__ == 1) +/* The implementation is ISO-conforming. */ +#define __STDC_ISO__ +#else +/* The implementation is not ISO-conforming. */ +#endif + +#if defined(__STDC_VERSION__) +#if (__STDC_VERSION__ >= 201112L) +/* This is C11. */ +#define __STDC_C11__ +#elif (__STDC_VERSION__ >= 199901L) +/* This is C99. */ +#define __STDC_C99__ +#elif (__STDC_VERSION__ >= 199409L) +/* This is C89 with amendment 1. */ +#define __STDC_C89__ +#define __STDC_C89_AMENDMENT_1__ +#else +/* This is C89 without amendment 1. */ +#define __STDC_C89__ +#endif +#else /* !defined(__STDC_VERSION__) */ +/* This is C89. __STDC_VERSION__ is not defined. */ +#define __STDC_C89__ +#endif + +#else /* !defined(__STDC__) */ +/* This is not standard C. __STDC__ is not defined. */ +#endif + + + +#endif diff --git a/nxengine/libretro/libretro-common/include/retro_inline.h b/nxengine/libretro/libretro-common/include/retro_inline.h new file mode 100644 index 00000000..ffdaa4a3 --- /dev/null +++ b/nxengine/libretro/libretro-common/include/retro_inline.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_inline.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_INLINE_H +#define __LIBRETRO_SDK_INLINE_H + +#ifndef INLINE + +#if defined(_WIN32) || defined(__INTEL_COMPILER) +#define INLINE __inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L +#define INLINE inline +#elif defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE +#endif + +#endif +#endif diff --git a/nxengine/libretro/libretro-common/include/retro_miscellaneous.h b/nxengine/libretro/libretro-common/include/retro_miscellaneous.h new file mode 100644 index 00000000..4768b909 --- /dev/null +++ b/nxengine/libretro/libretro-common/include/retro_miscellaneous.h @@ -0,0 +1,142 @@ +/* Copyright (C) 2010-2017 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_miscellaneous.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __RARCH_MISCELLANEOUS_H +#define __RARCH_MISCELLANEOUS_H + +#include +#include +#include + +#if defined(_WIN32) && !defined(_XBOX) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#elif defined(_WIN32) && defined(_XBOX) +#include +#endif + +#include + +#ifdef _MSC_VER +#include +#endif + +static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count) +{ + uint32_t i; + for (i = 0; i < count;i++) + a[i] &= ~b[i]; +} + +static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count) +{ + uint32_t i; + for (i = 0; i < count; i++) + { + if (ptr[i] != 0) + return true; + } + return false; +} + +#ifndef PATH_MAX_LENGTH +#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(GEKKO)|| defined(WIIU) +#define PATH_MAX_LENGTH 512 +#else +#define PATH_MAX_LENGTH 4096 +#endif +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +#define BITS_GET_ELEM(a, i) ((a).data[i]) +#define BITS_GET_ELEM_PTR(a, i) ((a)->data[i]) + +#define BIT_SET(a, bit) ((a)[(bit) >> 3] |= (1 << ((bit) & 7))) +#define BIT_CLEAR(a, bit) ((a)[(bit) >> 3] &= ~(1 << ((bit) & 7))) +#define BIT_GET(a, bit) (((a)[(bit) >> 3] >> ((bit) & 7)) & 1) + +#define BIT16_SET(a, bit) ((a) |= (1 << ((bit) & 15))) +#define BIT16_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 15))) +#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1) +#define BIT16_CLEAR_ALL(a) ((a) = 0) + +#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31))) +#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31))) +#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1) +#define BIT32_CLEAR_ALL(a) ((a) = 0) + +#define BIT64_SET(a, bit) ((a) |= (UINT64_C(1) << ((bit) & 63))) +#define BIT64_CLEAR(a, bit) ((a) &= ~(UINT64_C(1) << ((bit) & 63))) +#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1) +#define BIT64_CLEAR_ALL(a) ((a) = 0) + +#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (1 << ((bit) & 31))) +#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31))) +#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1) +#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a)) + +#define BIT128_SET_PTR(a, bit) BIT128_SET(*a, bit) +#define BIT128_CLEAR_PTR(a, bit) BIT128_CLEAR(*a, bit) +#define BIT128_GET_PTR(a, bit) BIT128_GET(*a, bit) +#define BIT128_CLEAR_ALL_PTR(a) BIT128_CLEAR_ALL(*a) + +#define BIT256_SET(a, bit) BIT128_SET(a, bit) +#define BIT256_CLEAR(a, bit) BIT128_CLEAR(a, bit) +#define BIT256_GET(a, bit) BIT128_GET(a, bit) +#define BIT256_CLEAR_ALL(a) BIT128_CLEAR_ALL(a) + +#define BIT256_SET_PTR(a, bit) BIT256_SET(*a, bit) +#define BIT256_CLEAR_PTR(a, bit) BIT256_CLEAR(*a, bit) +#define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit) +#define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a) + +#define BITS_COPY16_PTR(a,bits) \ +{ \ + BIT128_CLEAR_ALL_PTR(a); \ + BITS_GET_ELEM_PTR(a, 0) = (bits) & 0xffff; \ +} + +#define BITS_COPY32_PTR(a,bits) \ +{ \ + BIT128_CLEAR_ALL_PTR(a); \ + BITS_GET_ELEM_PTR(a, 0) = (bits); \ +} + +/* Helper macros and struct to keep track of many booleans. */ +/* This struct has 256 bits. */ +typedef struct +{ + uint32_t data[8]; +} retro_bits_t; + +#endif diff --git a/nxengine/libretro/libretro-common/include/streams/file_stream.h b/nxengine/libretro/libretro-common/include/streams/file_stream.h index 5a1784df..c2b319e8 100644 --- a/nxengine/libretro/libretro-common/include/streams/file_stream.h +++ b/nxengine/libretro/libretro-common/include/streams/file_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2016 The RetroArch team +/* Copyright (C) 2010-2017 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream.h). @@ -23,38 +23,48 @@ #ifndef __LIBRETRO_SDK_FILE_STREAM_H #define __LIBRETRO_SDK_FILE_STREAM_H +#include #include +#include #include #include -#include +#include +#include +#include #include -#ifdef __cplusplus -extern "C" { -#endif +#include + +#define FILESTREAM_REQUIRED_VFS_VERSION 1 + +RETRO_BEGIN_DECLS typedef struct RFILE RFILE; -enum -{ - RFILE_MODE_READ = 0, - RFILE_MODE_WRITE, - RFILE_MODE_READ_WRITE, +#define FILESTREAM_REQUIRED_VFS_VERSION 1 - /* There is no garantee these requests will be attended. */ - RFILE_HINT_UNBUFFERED = 1<<8, - RFILE_HINT_MMAP = 1<<9 /* requires RFILE_MODE_READ */ -}; +void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info); -RFILE *filestream_open(const char *path, unsigned mode, ssize_t len); +int64_t filestream_get_size(RFILE *stream); + +/** + * filestream_open: + * @path : path to file + * @mode : file mode to use when opening (read/write) + * @bufsize : optional buffer size (-1 or 0 to use default) + * + * Opens a file for reading or writing, depending on the requested mode. + * Returns a pointer to an RFILE if opened successfully, otherwise NULL. + **/ +RFILE *filestream_open(const char *path, unsigned mode, unsigned hints); ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence); -ssize_t filestream_read(RFILE *stream, void *data, size_t len); +ssize_t filestream_read(RFILE *stream, void *data, int64_t len); -ssize_t filestream_write(RFILE *stream, const void *data, size_t len); +ssize_t filestream_write(RFILE *stream, const void *data, int64_t len); ssize_t filestream_tell(RFILE *stream); @@ -64,12 +74,34 @@ int filestream_close(RFILE *stream); int filestream_read_file(const char *path, void **buf, ssize_t *len); +char *filestream_gets(RFILE *stream, char *s, size_t len); + +int filestream_getc(RFILE *stream); + +int filestream_eof(RFILE *stream); + bool filestream_write_file(const char *path, const void *data, ssize_t size); -int filestream_get_fd(RFILE *stream); +int filestream_putc(RFILE *stream, int c); -#ifdef __cplusplus -} -#endif +int filestream_vprintf(RFILE *stream, const char* format, va_list args); + +int filestream_printf(RFILE *stream, const char* format, ...); + +int filestream_error(RFILE *stream); + +int filestream_flush(RFILE *stream); + +int filestream_delete(const char *path); + +int filestream_rename(const char *old_path, const char *new_path); + +const char *filestream_get_path(RFILE *stream); + +bool filestream_exists(const char *path); + +char *filestream_getline(RFILE *stream); + +RETRO_END_DECLS #endif diff --git a/nxengine/libretro/libretro-common/include/vfs/vfs_implementation.h b/nxengine/libretro/libretro-common/include/vfs/vfs_implementation.h new file mode 100644 index 00000000..2b3f34e4 --- /dev/null +++ b/nxengine/libretro/libretro-common/include/vfs/vfs_implementation.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2010-2017 The RetroArch team +* +* --------------------------------------------------------------------------------------- +* The following license statement only applies to this file (vfs_implementation.h). +* --------------------------------------------------------------------------------------- +* +* Permission is hereby granted, free of charge, +* to any person obtaining a copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef __LIBRETRO_SDK_VFS_IMPLEMENTATION_H +#define __LIBRETRO_SDK_VFS_IMPLEMENTATION_H + +#include +#include + +/* Replace the following symbol with something appropriate + * to signify the file is being compiled for a front end instead of a core. + * This allows the same code to act as reference implementation + * for VFS and as fallbacks for when the front end does not provide VFS functionality. + */ + +#ifdef VFS_FRONTEND +typedef struct retro_vfs_file_handle libretro_vfs_implementation_file; +#else +typedef struct libretro_vfs_implementation_file libretro_vfs_implementation_file; +#endif + +libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints); + +int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream); + +int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream); + +int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream); + +int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream); + +int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int whence); + +int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void *s, uint64_t len); + +int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len); + +int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream); + +int retro_vfs_file_remove_impl(const char *path); + +int retro_vfs_file_rename_impl(const char *old_path, const char *new_path); + +const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream); + +#endif diff --git a/nxengine/libretro/libretro-common/streams/file_stream.c b/nxengine/libretro/libretro-common/streams/file_stream.c index 40d38149..0d3d8142 100644 --- a/nxengine/libretro/libretro-common/streams/file_stream.c +++ b/nxengine/libretro/libretro-common/streams/file_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2016 The RetroArch team +/* Copyright (C) 2010-2017 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (file_stream.c). @@ -23,419 +23,342 @@ #include #include #include +#include #include -#if defined(_WIN32) -# ifdef _MSC_VER -# define setmode _setmode -# endif -# ifdef _XBOX -# include -# define INVALID_FILE_ATTRIBUTES -1 -# else -# include -# include -# include -# include -# endif -#elif defined(VITA) -# include -# include - -#define PSP_O_RDONLY PSP2_O_RDONLY -#define PSP_O_RDWR PSP2_O_RDWR -#define PSP_O_CREAT PSP2_O_CREAT -#define PSP_O_WRONLY PSP2_O_WRONLY -#define PSP_O_TRUNC PSP2_O_TRUNC -#else -# if defined(PSP) -# include -# endif -# include -# include -# include -# include -#endif - -#ifdef __CELLOS_LV2__ -#include -#else -#include +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include -#include - -#if 1 -#define HAVE_BUFFERED_IO 1 -#endif +#include + +static const int64_t vfs_error_return_value = -1; + +static retro_vfs_get_path_t filestream_get_path_cb = NULL; +static retro_vfs_open_t filestream_open_cb = NULL; +static retro_vfs_close_t filestream_close_cb = NULL; +static retro_vfs_size_t filestream_size_cb = NULL; +static retro_vfs_tell_t filestream_tell_cb = NULL; +static retro_vfs_seek_t filestream_seek_cb = NULL; +static retro_vfs_read_t filestream_read_cb = NULL; +static retro_vfs_write_t filestream_write_cb = NULL; +static retro_vfs_flush_t filestream_flush_cb = NULL; +static retro_vfs_remove_t filestream_remove_cb = NULL; +static retro_vfs_rename_t filestream_rename_cb = NULL; struct RFILE { - unsigned hints; -#if defined(PSP) || defined(VITA) - SceUID fd; -#elif defined(__CELLOS_LV2__) - int fd; -#else -#if defined(HAVE_BUFFERED_IO) - FILE *fp; -#endif -#if defined(HAVE_MMAP) - uint8_t *mapped; - uint64_t mappos; - uint64_t mapsize; -#endif - int fd; -#endif + struct retro_vfs_file_handle *hfile; + bool error_flag; }; -int filestream_get_fd(RFILE *stream) +/* VFS Initialization */ + +void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info) { - if (!stream) - return -1; -#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) - return stream->fd; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - return fileno(stream->fp); -#endif - return stream->fd; -#endif + const struct retro_vfs_interface* vfs_iface; + + filestream_get_path_cb = NULL; + filestream_open_cb = NULL; + filestream_close_cb = NULL; + filestream_tell_cb = NULL; + filestream_size_cb = NULL; + filestream_seek_cb = NULL; + filestream_read_cb = NULL; + filestream_write_cb = NULL; + filestream_flush_cb = NULL; + filestream_remove_cb = NULL; + filestream_rename_cb = NULL; + + vfs_iface = vfs_info->iface; + + if (vfs_info->required_interface_version < FILESTREAM_REQUIRED_VFS_VERSION + || !vfs_iface) + return; + + filestream_get_path_cb = vfs_iface->get_path; + filestream_open_cb = vfs_iface->open; + filestream_close_cb = vfs_iface->close; + filestream_size_cb = vfs_iface->size; + filestream_tell_cb = vfs_iface->tell; + filestream_seek_cb = vfs_iface->seek; + filestream_read_cb = vfs_iface->read; + filestream_write_cb = vfs_iface->write; + filestream_flush_cb = vfs_iface->flush; + filestream_remove_cb = vfs_iface->remove; + filestream_rename_cb = vfs_iface->rename; } -RFILE *filestream_open(const char *path, unsigned mode, ssize_t len) +/* Callback wrappers */ +bool filestream_exists(const char *path) { - int flags = 0; - int mode_int = 0; - const char *mode_str = NULL; - RFILE *stream = (RFILE*)calloc(1, sizeof(*stream)); + RFILE *dummy = NULL; - if (!stream) - return NULL; + if (!path || !*path) + return false; + + dummy = filestream_open(path, + RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + + if (!dummy) + return false; - (void)mode_str; - (void)mode_int; - (void)flags; + filestream_close(dummy); + return true; +} - stream->hints = mode; +int64_t filestream_get_size(RFILE *stream) +{ + int64_t output; -#ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP && (stream->hints & 0xff) == RFILE_MODE_READ) - stream->hints |= RFILE_HINT_UNBUFFERED; + if (filestream_size_cb != NULL) + output = filestream_size_cb(stream->hfile); else -#endif - stream->hints &= ~RFILE_HINT_MMAP; + output = retro_vfs_file_size_impl((libretro_vfs_implementation_file*)stream->hfile); - switch (mode & 0xff) + if (output == vfs_error_return_value) + stream->error_flag = true; + + return output; +} + +/** + * filestream_open: + * @path : path to file + * @mode : file mode to use when opening (read/write) + * @hints : + * + * Opens a file for reading or writing, depending on the requested mode. + * Returns a pointer to an RFILE if opened successfully, otherwise NULL. + **/ +RFILE *filestream_open(const char *path, unsigned mode, unsigned hints) +{ + struct retro_vfs_file_handle *fp = NULL; + RFILE* output = NULL; + + if (filestream_open_cb != NULL) + fp = (struct retro_vfs_file_handle*) + filestream_open_cb(path, mode, hints); + else + fp = (struct retro_vfs_file_handle*) + retro_vfs_file_open_impl(path, mode, hints); + + if (!fp) + return NULL; + + output = (RFILE*)malloc(sizeof(RFILE)); + output->error_flag = false; + output->hfile = fp; + return output; +} + +char *filestream_gets(RFILE *stream, char *s, size_t len) +{ + int c = 0; + char *p = NULL; + if (!stream) + return NULL; + + /* get max bytes or up to a newline */ + + for (p = s, len--; len > 0; len--) { - case RFILE_MODE_READ: -#if defined(VITA) || defined(PSP) - mode_int = 0777; - flags = PSP_O_RDONLY; -#elif defined(__CELLOS_LV2__) - mode_int = 0777; - flags = CELL_FS_O_RDONLY; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - mode_str = "rb"; -#endif - /* No "else" here */ - flags = O_RDONLY; -#endif - break; - case RFILE_MODE_WRITE: -#if defined(VITA) || defined(PSP) - mode_int = 0777; - flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC; -#elif defined(__CELLOS_LV2__) - mode_int = 0777; - flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - mode_str = "wb"; -#endif - else - { - flags = O_WRONLY | O_CREAT | O_TRUNC; -#ifndef _WIN32 - flags |= S_IRUSR | S_IWUSR; -#endif - } -#endif + if ((c = filestream_getc(stream)) == EOF) break; - case RFILE_MODE_READ_WRITE: -#if defined(VITA) || defined(PSP) - mode_int = 0777; - flags = PSP_O_RDWR; -#elif defined(__CELLOS_LV2__) - mode_int = 0777; - flags = CELL_FS_O_RDWR; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - mode_str = "w+"; -#endif - else - { - flags = O_RDWR; -#ifdef _WIN32 - flags |= O_BINARY; -#endif - } -#endif + *p++ = c; + if (c == '\n') break; } + *p = 0; -#if defined(VITA) || defined(PSP) - stream->fd = sceIoOpen(path, flags, mode_int); -#elif defined(__CELLOS_LV2__) - cellFsOpen(path, flags, &stream->fd, NULL, 0); -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - { - stream->fp = fopen(path, mode_str); - if (!stream->fp) - goto error; - } + if (p == s || c == EOF) + return NULL; + return (p); +} + +int filestream_getc(RFILE *stream) +{ + char c = 0; + if (!stream) + return 0; + if(filestream_read(stream, &c, 1) == 1) + return (int)c; + return EOF; +} + +ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence) +{ + int64_t output; + + if (filestream_seek_cb != NULL) + output = filestream_seek_cb(stream->hfile, offset, whence); else -#endif - { - stream->fd = open(path, flags); - if (stream->fd == -1) - goto error; -#ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP) - { - stream->mappos = 0; - stream->mapped = NULL; - stream->mapsize = filestream_seek(stream, 0, SEEK_END); + output = retro_vfs_file_seek_impl((libretro_vfs_implementation_file*)stream->hfile, offset, whence); - if (stream->mapsize == (uint64_t)-1) - goto error; + if (output == vfs_error_return_value) + stream->error_flag = true; - filestream_rewind(stream); + return output; +} - stream->mapped = (uint8_t*)mmap((void*)0, stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0); +int filestream_eof(RFILE *stream) +{ + int64_t current_position = filestream_tell(stream); + int64_t end_position = filestream_get_size(stream); - if (stream->mapped == MAP_FAILED) - stream->hints &= ~RFILE_HINT_MMAP; - } -#endif - } -#endif + if (current_position >= end_position) + return 1; + return 0; +} -#if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) - if (stream->fd == -1) - goto error; -#endif - return stream; +ssize_t filestream_tell(RFILE *stream) +{ + ssize_t output; + + if (filestream_size_cb != NULL) + output = filestream_tell_cb(stream->hfile); + else + output = retro_vfs_file_tell_impl((libretro_vfs_implementation_file*)stream->hfile); -error: - filestream_close(stream); - return NULL; + if (output == vfs_error_return_value) + stream->error_flag = true; + + return output; } -ssize_t filestream_seek(RFILE *stream, ssize_t offset, int whence) +void filestream_rewind(RFILE *stream) { - int ret = 0; if (!stream) - return -1; + return; + filestream_seek(stream, 0L, SEEK_SET); + stream->error_flag = false; +} - (void)ret; +ssize_t filestream_read(RFILE *stream, void *s, int64_t len) +{ + int64_t output; -#if defined(VITA) || defined(PSP) - ret = sceIoLseek(stream->fd, (SceOff)offset, whence); - if (ret == -1) - return -1; - return 0; -#elif defined(__CELLOS_LV2__) - uint64_t pos = 0; - if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED) - return -1; - return 0; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - return fseek(stream->fp, (long)offset, whence); + if (filestream_read_cb != NULL) + output = filestream_read_cb(stream->hfile, s, len); else -#endif -#ifdef HAVE_MMAP - /* Need to check stream->mapped because this function is - * called in filestream_open() */ - if (stream->mapped && stream->hints & RFILE_HINT_MMAP) - { - /* fseek() returns error on under/overflow but allows cursor > EOF for - read-only file descriptors. */ - switch (whence) - { - case SEEK_SET: - if (offset < 0) - return -1; + output = retro_vfs_file_read_impl( + (libretro_vfs_implementation_file*)stream->hfile, s, len); - stream->mappos = offset; - break; + if (output == vfs_error_return_value) + stream->error_flag = true; - case SEEK_CUR: - if ((offset < 0 && stream->mappos + offset > stream->mappos) || - (offset > 0 && stream->mappos + offset < stream->mappos)) - return -1; + return output; +} - stream->mappos += offset; - break; +int filestream_flush(RFILE *stream) +{ + int output; - case SEEK_END: - if (stream->mapsize + offset < stream->mapsize) - return -1; + if (filestream_flush_cb != NULL) + output = filestream_flush_cb(stream->hfile); + else + output = retro_vfs_file_flush_impl((libretro_vfs_implementation_file*)stream->hfile); - stream->mappos = stream->mapsize + offset; + if (output == vfs_error_return_value) + stream->error_flag = true; - break; - } + return output; +} - return stream->mappos; - } - else -#endif - { - ret = lseek(stream->fd, offset, whence); - return ret < 0 ? -1 : ret; - } -#endif +int filestream_delete(const char *path) +{ + if (filestream_remove_cb != NULL) + return filestream_remove_cb(path); + + return retro_vfs_file_remove_impl(path); } -ssize_t filestream_tell(RFILE *stream) +int filestream_rename(const char *old_path, const char *new_path) { - if (!stream) - return -1; -#if defined(VITA) || defined(PSP) - return sceIoLseek(stream->fd, 0, SEEK_CUR); -#elif defined(__CELLOS_LV2__) - uint64_t pos = 0; - if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED) - return -1; - return 0; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - return ftell(stream->fp); - else -#endif -#ifdef HAVE_MMAP - /* Need to check stream->mapped because this function - * is called in filestream_open() */ - if (stream->mapped && stream->hints & RFILE_HINT_MMAP) - return stream->mappos; - else -#endif - return lseek(stream->fd, 0, SEEK_CUR); -#endif + if (filestream_rename_cb != NULL) + return filestream_rename_cb(old_path, new_path); + + return retro_vfs_file_rename_impl(old_path, new_path); } -void filestream_rewind(RFILE *stream) +const char *filestream_get_path(RFILE *stream) { - filestream_seek(stream, 0L, SEEK_SET); + if (filestream_get_path_cb != NULL) + return filestream_get_path_cb(stream->hfile); + + return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile); } -ssize_t filestream_read(RFILE *stream, void *s, size_t len) +ssize_t filestream_write(RFILE *stream, const void *s, int64_t len) { - if (!stream || !s) - return -1; -#if defined(VITA) || defined(PSP) - return sceIoRead(stream->fd, s, len); -#elif defined(__CELLOS_LV2__) - uint64_t bytes_written; - if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED) - return -1; - return bytes_written; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - return fread(s, 1, len, stream->fp); - else -#endif -#ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP) - { - if (stream->mappos > stream->mapsize) - return -1; + int64_t output; - if (stream->mappos + len > stream->mapsize) - len = stream->mapsize - stream->mappos; + if (filestream_write_cb != NULL) + output = filestream_write_cb(stream->hfile, s, len); + else + output = retro_vfs_file_write_impl((libretro_vfs_implementation_file*)stream->hfile, s, len); - memcpy(s, &stream->mapped[stream->mappos], len); - stream->mappos += len; + if (output == vfs_error_return_value) + stream->error_flag = true; - return len; - } - else -#endif - return read(stream->fd, s, len); -#endif + return output; } -ssize_t filestream_write(RFILE *stream, const void *s, size_t len) +int filestream_putc(RFILE *stream, int c) { + char c_char = (char)c; if (!stream) - return -1; -#if defined(VITA) || defined(PSP) - return sceIoWrite(stream->fd, s, len); -#elif defined(__CELLOS_LV2__) - uint64_t bytes_written; - if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED) - return -1; - return bytes_written; -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - return fwrite(s, 1, len, stream->fp); - else -#endif -#ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP) - return -1; - else -#endif - return write(stream->fd, s, len); -#endif + return EOF; + return filestream_write(stream, &c_char, 1); +} + +int filestream_vprintf(RFILE *stream, const char* format, va_list args) +{ + static char buffer[8 * 1024]; + int num_chars = vsprintf(buffer, format, args); + + if (num_chars < 0) + return -1; + else if (num_chars == 0) + return 0; + + return filestream_write(stream, buffer, num_chars); +} + +int filestream_printf(RFILE *stream, const char* format, ...) +{ + va_list vl; + int result; + va_start(vl, format); + result = filestream_vprintf(stream, format, vl); + va_end(vl); + return result; +} + +int filestream_error(RFILE *stream) +{ + if (stream && stream->error_flag) + return 1; + return 0; } int filestream_close(RFILE *stream) { - if (!stream) - return -1; - -#if defined(VITA) || defined(PSP) - if (stream->fd > 0) - sceIoClose(stream->fd); -#elif defined(__CELLOS_LV2__) - if (stream->fd > 0) - cellFsClose(stream->fd); -#else -#if defined(HAVE_BUFFERED_IO) - if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) - { - if (stream->fp) - fclose(stream->fp); - } + int output; + struct retro_vfs_file_handle* fp = stream->hfile; + + if (filestream_close_cb != NULL) + output = filestream_close_cb(fp); else -#endif -#ifdef HAVE_MMAP - if (stream->hints & RFILE_HINT_MMAP) - munmap(stream->mapped, stream->mapsize); -#endif + output = retro_vfs_file_close_impl((libretro_vfs_implementation_file*)fp); - if (stream->fd > 0) - close(stream->fd); -#endif - free(stream); + if (output == 0) + free(stream); - return 0; + return output; } /** @@ -451,42 +374,34 @@ int filestream_close(RFILE *stream) int filestream_read_file(const char *path, void **buf, ssize_t *len) { ssize_t ret = 0; - ssize_t content_buf_size = 0; + int64_t content_buf_size = 0; void *content_buf = NULL; - RFILE *file = filestream_open(path, RFILE_MODE_READ, -1); + RFILE *file = filestream_open(path, + RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) { -#if __STDC_VERSION__ >= 199901L - fprintf(stderr, "%s: Failed to open %s: %s\n", __FUNCTION__, path, strerror(errno)); -#else fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); -#endif goto error; } - if (filestream_seek(file, 0, SEEK_END) != 0) - goto error; + content_buf_size = filestream_get_size(file); - content_buf_size = filestream_tell(file); if (content_buf_size < 0) goto error; - filestream_rewind(file); - - content_buf = malloc(content_buf_size + 1); + content_buf = malloc((size_t)(content_buf_size + 1)); if (!content_buf) goto error; + if ((size_t)(content_buf_size + 1) != (content_buf_size + 1)) + goto error; - ret = filestream_read(file, content_buf, content_buf_size); + ret = filestream_read(file, content_buf, (int64_t)content_buf_size); if (ret < 0) { -#if __STDC_VERSION__ >= 199901L - fprintf(stderr, "%s: Failed to read %s: %s\n", __FUNCTION__, path, strerror(errno)); -#else fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno)); -#endif goto error; } @@ -496,7 +411,7 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len) /* Allow for easy reading of strings to be safe. * Will only work with sane character formatting (Unix). */ - ((char*)content_buf)[content_buf_size] = '\0'; + ((char*)content_buf)[ret] = '\0'; if (len) *len = ret; @@ -527,12 +442,52 @@ int filestream_read_file(const char *path, void **buf, ssize_t *len) bool filestream_write_file(const char *path, const void *data, ssize_t size) { ssize_t ret = 0; - RFILE *file = filestream_open(path, RFILE_MODE_WRITE, -1); + RFILE *file = filestream_open(path, + RETRO_VFS_FILE_ACCESS_WRITE, + RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) return false; ret = filestream_write(file, data, size); filestream_close(file); - return (ret == size); + if (ret != size) + return false; + + return true; +} + +char *filestream_getline(RFILE *stream) +{ + char* newline = (char*)malloc(9); + char* newline_tmp = NULL; + size_t cur_size = 8; + size_t idx = 0; + int in = filestream_getc(stream); + + if (!newline) + return NULL; + + while (in != EOF && in != '\n') + { + if (idx == cur_size) + { + cur_size *= 2; + newline_tmp = (char*)realloc(newline, cur_size + 1); + + if (!newline_tmp) + { + free(newline); + return NULL; + } + + newline = newline_tmp; + } + + newline[idx++] = in; + in = filestream_getc(stream); + } + + newline[idx] = '\0'; + return newline; } diff --git a/nxengine/libretro/libretro-common/vfs/vfs_implementation.c b/nxengine/libretro/libretro-common/vfs/vfs_implementation.c new file mode 100644 index 00000000..acf46fba --- /dev/null +++ b/nxengine/libretro/libretro-common/vfs/vfs_implementation.c @@ -0,0 +1,548 @@ +/* Copyright (C) 2010-2017 The RetroArch team +* +* --------------------------------------------------------------------------------------- +* The following license statement only applies to this file (vfs_implementation.c). +* --------------------------------------------------------------------------------------- +* +* Permission is hereby granted, free of charge, +* to any person obtaining a copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation the rights to +* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, +* and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(_WIN32) +# ifdef _MSC_VER +# define setmode _setmode +# endif +# ifdef _XBOX +# include +# define INVALID_FILE_ATTRIBUTES -1 +# else +# include +# include +# include +# include +# endif +#else +# if defined(PSP) +# include +# endif +# include +# include +# if !defined(VITA) +# include +# endif +# include +#endif + +#ifdef __CELLOS_LV2__ +#include +#define O_RDONLY CELL_FS_O_RDONLY +#define O_WRONLY CELL_FS_O_WRONLY +#define O_CREAT CELL_FS_O_CREAT +#define O_TRUNC CELL_FS_O_TRUNC +#define O_RDWR CELL_FS_O_RDWR +#else +#include +#endif + +/* Assume W-functions do not work below Win2K and Xbox platforms */ +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX) + +#ifndef LEGACY_WIN32 +#define LEGACY_WIN32 +#endif + +#endif + +#define MODE_STR_READ "r" +#define MODE_STR_READ_UNBUF "rb" +#define MODE_STR_WRITE_UNBUF "wb" +#define MODE_STR_WRITE_PLUS "w+" + +#ifdef RARCH_INTERNAL +#ifndef VFS_FRONTEND +#define VFS_FRONTEND +#endif +#endif + +#include +#include +#include +#include +#include + +#define RFILE_HINT_UNBUFFERED (1 << 8) + +#ifdef VFS_FRONTEND +struct retro_vfs_file_handle +#else +struct libretro_vfs_implementation_file +#endif +{ + int fd; + unsigned hints; + int64_t size; + char *buf; + FILE *fp; + char* orig_path; +#if defined(HAVE_MMAP) + uint64_t mappos; + uint64_t mapsize; + uint8_t *mapped; +#endif +}; + +int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence) +{ + if (!stream) + goto error; + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + return fseek(stream->fp, (long)offset, whence); + +#ifdef HAVE_MMAP + /* Need to check stream->mapped because this function is + * called in filestream_open() */ + if (stream->mapped && stream->hints & + RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS) + { + /* fseek() returns error on under/overflow but + * allows cursor > EOF for + read-only file descriptors. */ + switch (whence) + { + case SEEK_SET: + if (offset < 0) + goto error; + + stream->mappos = offset; + break; + + case SEEK_CUR: + if ((offset < 0 && stream->mappos + offset > stream->mappos) || + (offset > 0 && stream->mappos + offset < stream->mappos)) + goto error; + + stream->mappos += offset; + break; + + case SEEK_END: + if (stream->mapsize + offset < stream->mapsize) + goto error; + + stream->mappos = stream->mapsize + offset; + break; + } + return stream->mappos; + } +#endif + + if (lseek(stream->fd, offset, whence) < 0) + goto error; + + return 0; + +error: + return -1; +} + +/** + * retro_vfs_file_open_impl: + * @path : path to file + * @mode : file mode to use when opening (read/write) + * @hints : + * + * Opens a file for reading or writing, depending on the requested mode. + * Returns a pointer to an RFILE if opened successfully, otherwise NULL. + **/ + +libretro_vfs_implementation_file *retro_vfs_file_open_impl(const char *path, unsigned mode, unsigned hints) +{ + int flags = 0; + const char *mode_str = NULL; + libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)calloc(1, sizeof(*stream)); + +#ifdef VFS_FRONTEND + const char *dumb_prefix = "vfsonly://"; + + if (!memcmp(path, dumb_prefix, strlen(dumb_prefix))) + path += strlen(dumb_prefix); +#endif + + if (!stream) + return NULL; + + (void)flags; + + stream->hints = hints; + stream->orig_path = strdup(path); + +#ifdef HAVE_MMAP + if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS && mode == RETRO_VFS_FILE_ACCESS_READ) + stream->hints |= RFILE_HINT_UNBUFFERED; + else +#endif + stream->hints &= ~RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS; + + switch (mode) + { + case RETRO_VFS_FILE_ACCESS_READ: + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + mode_str = MODE_STR_READ_UNBUF; + /* No "else" here */ + flags = O_RDONLY; + break; + case RETRO_VFS_FILE_ACCESS_WRITE: + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + mode_str = MODE_STR_WRITE_UNBUF; + else + { + flags = O_WRONLY | O_CREAT | O_TRUNC; +#ifndef _WIN32 + flags |= S_IRUSR | S_IWUSR; +#endif + } + break; + case RETRO_VFS_FILE_ACCESS_READ_WRITE: + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + mode_str = MODE_STR_WRITE_PLUS; + else + { + flags = O_RDWR; +#ifdef _WIN32 + flags |= O_BINARY; +#endif + } + break; + /* TODO/FIXME - implement */ + case RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING: + break; + } + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0 && mode_str) + { + stream->fp = fopen_utf8(path, mode_str); + + if (!stream->fp) + goto error; + + /* Regarding setvbuf: + * + * https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html + * + * If the size argument is not zero but buf is NULL, a buffer of the given size will be allocated immediately, and + * released on close. This is an extension to ANSI C. + * + * Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it. + */ + /* TODO: this is only useful for a few platforms, find which and add ifdef */ + stream->buf = (char*)calloc(1, 0x4000); + setvbuf(stream->fp, stream->buf, _IOFBF, 0x4000); + } + else + { +#if defined(_WIN32) && !defined(_XBOX) +#if defined(LEGACY_WIN32) + char *path_local = utf8_to_local_string_alloc(path); + stream->fd = open(path_local, flags, 0); + if (path_local) + free(path_local); +#else + wchar_t * path_wide = utf8_to_utf16_string_alloc(path); + stream->fd = _wopen(path_wide, flags, 0); + if (path_wide) + free(path_wide); +#endif +#else + stream->fd = open(path, flags, 0); +#endif + + if (stream->fd == -1) + goto error; + +#ifdef HAVE_MMAP + if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS) + { + stream->mappos = 0; + stream->mapped = NULL; + stream->mapsize = retro_vfs_file_seek_internal(stream, 0, SEEK_END); + + if (stream->mapsize == (uint64_t)-1) + goto error; + + retro_vfs_file_seek_internal(stream, 0, SEEK_SET); + + stream->mapped = (uint8_t*)mmap((void*)0, + stream->mapsize, PROT_READ, MAP_SHARED, stream->fd, 0); + + if (stream->mapped == MAP_FAILED) + stream->hints &= ~RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS; + } +#endif + } + + retro_vfs_file_seek_internal(stream, 0, SEEK_SET); + retro_vfs_file_seek_internal(stream, 0, SEEK_END); + + stream->size = retro_vfs_file_tell_impl(stream); + + retro_vfs_file_seek_internal(stream, 0, SEEK_SET); + + return stream; + +error: + retro_vfs_file_close_impl(stream); + return NULL; +} + +int retro_vfs_file_close_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream) + return -1; + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + { + if (stream->fp) + fclose(stream->fp); + } + else + { +#ifdef HAVE_MMAP + if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS) + munmap(stream->mapped, stream->mapsize); +#endif + } + + if (stream->fd > 0) + close(stream->fd); + if (stream->buf) + free(stream->buf); + if (stream->orig_path) + free(stream->orig_path); + free(stream); + + return 0; +} + +int retro_vfs_file_error_impl(libretro_vfs_implementation_file *stream) +{ + return ferror(stream->fp); +} + +int64_t retro_vfs_file_size_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream) + return 0; + return stream->size; +} + +int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream) + return -1; + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + return ftell(stream->fp); + +#ifdef HAVE_MMAP + /* Need to check stream->mapped because this function + * is called in filestream_open() */ + if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS) + return stream->mappos; +#endif + if (lseek(stream->fd, 0, SEEK_CUR) < 0) + return -1; + + return 0; +} + +int64_t retro_vfs_file_seek_impl(libretro_vfs_implementation_file *stream, int64_t offset, int whence) +{ + return retro_vfs_file_seek_internal(stream, offset, whence); +} + +int64_t retro_vfs_file_read_impl(libretro_vfs_implementation_file *stream, void *s, uint64_t len) +{ + if (!stream || !s) + goto error; + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + return fread(s, 1, (size_t)len, stream->fp); + +#ifdef HAVE_MMAP + if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS) + { + if (stream->mappos > stream->mapsize) + goto error; + + if (stream->mappos + len > stream->mapsize) + len = stream->mapsize - stream->mappos; + + memcpy(s, &stream->mapped[stream->mappos], len); + stream->mappos += len; + + return len; + } +#endif + + return read(stream->fd, s, (size_t)len); + +error: + return -1; +} + +int64_t retro_vfs_file_write_impl(libretro_vfs_implementation_file *stream, const void *s, uint64_t len) +{ + if (!stream) + goto error; + + if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0) + return fwrite(s, 1, (size_t)len, stream->fp); + +#ifdef HAVE_MMAP + if (stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS) + goto error; +#endif + return write(stream->fd, s, (size_t)len); + +error: + return -1; +} + +int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream) +{ + if (!stream) + return -1; + return fflush(stream->fp); +} + +int retro_vfs_file_remove_impl(const char *path) +{ + char *path_local = NULL; + wchar_t *path_wide = NULL; + + if (!path || !*path) + return false; + + (void)path_local; + (void)path_wide; + +#if defined(_WIN32) && !defined(_XBOX) +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 + path_local = utf8_to_local_string_alloc(path); + + if (path_local) + { + int ret = remove(path_local); + free(path_local); + + if (ret == 0) + return true; + } +#else + path_wide = utf8_to_utf16_string_alloc(path); + + if (path_wide) + { + int ret = _wremove(path_wide); + free(path_wide); + + if (ret == 0) + return true; + } +#endif +#else + if (remove(path) == 0) + return true; +#endif + return false; +} + +int retro_vfs_file_rename_impl(const char *old_path, const char *new_path) +{ + char *old_path_local = NULL; + char *new_path_local = NULL; + wchar_t *old_path_wide = NULL; + wchar_t *new_path_wide = NULL; + + if (!old_path || !*old_path || !new_path || !*new_path) + return -1; + + (void)old_path_local; + (void)new_path_local; + (void)old_path_wide; + (void)new_path_wide; + +#if defined(_WIN32) && !defined(_XBOX) +#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 + old_path_local = utf8_to_local_string_alloc(old_path); + new_path_local = utf8_to_local_string_alloc(new_path); + + if (old_path_local) + { + if (new_path_local) + { + int ret = rename(old_path_local, new_path_local); + free(old_path_local); + free(new_path_local); + return ret; + } + + free(old_path_local); + } + + if (new_path_local) + free(new_path_local); +#else + old_path_wide = utf8_to_utf16_string_alloc(old_path); + new_path_wide = utf8_to_utf16_string_alloc(new_path); + + if (old_path_wide) + { + if (new_path_wide) + { + int ret = _wrename(old_path_wide, new_path_wide); + free(old_path_wide); + free(new_path_wide); + return ret; + } + + free(old_path_wide); + } + + if (new_path_wide) + free(new_path_wide); +#endif + return -1; +#else + return rename(old_path, new_path); +#endif +} + +const char *retro_vfs_file_get_path_impl(libretro_vfs_implementation_file *stream) +{ + /* should never happen, do something noisy so caller can be fixed */ + if (!stream) + abort(); + return stream->orig_path; +} diff --git a/nxengine/libretro/libretro.cpp b/nxengine/libretro/libretro.cpp index 221bcb7f..695a0233 100644 --- a/nxengine/libretro/libretro.cpp +++ b/nxengine/libretro/libretro.cpp @@ -6,7 +6,9 @@ #include #include -#include "libretro.h" +#include +#include + #include "libretro_shared.h" #include "../common/misc.fdh" #include "../graphics/graphics.h" @@ -41,7 +43,13 @@ unsigned retro_get_tick(void) void retro_set_environment(retro_environment_t cb) { + struct retro_vfs_interface_info vfs_iface_info; environ_cb = cb; + + vfs_iface_info.required_interface_version = 1; + vfs_iface_info.iface = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_iface_info)) + filestream_vfs_init(&vfs_iface_info); } unsigned retro_api_version(void) diff --git a/nxengine/niku.cpp b/nxengine/niku.cpp index 0ecfe1c0..626bb286 100644 --- a/nxengine/niku.cpp +++ b/nxengine/niku.cpp @@ -27,7 +27,7 @@ bool niku_load(uint32_t *value_out) retro_create_path_string(fname_tmp, sizeof(fname_tmp), g_dir, fname); - fp = filestream_open(fname_tmp, RFILE_MODE_READ, -1); + fp = filestream_open(fname_tmp, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fp) { #ifdef DEBUG @@ -110,7 +110,8 @@ bool niku_save(uint32_t value) retro_create_path_string(fname_tmp, sizeof(fname_tmp), g_dir, fname); - fp = filestream_open(fname_tmp, RFILE_MODE_WRITE, -1); + fp = filestream_open(fname_tmp, RETRO_VFS_FILE_ACCESS_WRITE, + RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fp) { NX_ERR("niku_save: failed to open '%s'", fname_tmp); diff --git a/nxengine/settings.cpp b/nxengine/settings.cpp index 9b9507c1..3736c4c4 100644 --- a/nxengine/settings.cpp +++ b/nxengine/settings.cpp @@ -69,7 +69,8 @@ static bool tryload(Settings *setfile) retro_create_path_string(setfilename_tmp, sizeof(setfilename_tmp), g_dir, setfilename); - fp = filestream_open(setfilename_tmp, RFILE_MODE_READ, -1); + fp = filestream_open(setfilename_tmp, RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fp) { NX_ERR("Couldn't open file %s.\n", setfilename_tmp); @@ -102,7 +103,8 @@ bool settings_save(Settings *setfile) retro_create_path_string(setfilename_tmp, sizeof(setfilename_tmp), g_dir, setfilename); - fp = filestream_open(setfilename_tmp, RFILE_MODE_WRITE, -1); + fp = filestream_open(setfilename_tmp, RETRO_VFS_FILE_ACCESS_WRITE, + RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!fp) { NX_ERR("Couldn't open file %s.\n", setfilename_tmp);