Add bitmask input code
authortwinaphex <libretro@gmail.com>
Mon, 24 Jun 2019 20:33:40 +0000 (22:33 +0200)
committertwinaphex <libretro@gmail.com>
Mon, 24 Jun 2019 20:33:40 +0000 (22:33 +0200)
frontend/libretro.c
frontend/libretro.h

index ccf1433..9971a4f 100644 (file)
@@ -74,6 +74,7 @@ static bool duping_enable;
 static bool found_bios;
 static bool display_internal_fps = false;
 static unsigned frame_count = 0;
+static bool libretro_supports_bitmasks = false;
 
 static int plugins_opened;
 static int is_pal_mode;
@@ -1701,15 +1702,13 @@ static void update_variables(bool in_flight)
 }
 
 // Taken from beetle-psx-libretro
-static uint16_t get_analog_button(retro_input_state_t input_state_cb, int player_index, int id)
+static uint16_t get_analog_button(int16_t ret, retro_input_state_t input_state_cb, int player_index, int id)
 {
-       uint16_t button;
-
        // NOTE: Analog buttons were added Nov 2017. Not all front-ends support this
        // feature (or pre-date it) so we need to handle this in a graceful way.
 
        // First, try and get an analog value using the new libretro API constant
-       button = input_state_cb(player_index,
+       uint16_t button = input_state_cb(player_index,
                                                                        RETRO_DEVICE_ANALOG,
                                                                        RETRO_DEVICE_INDEX_ANALOG_BUTTON,
                                                                        id);
@@ -1723,10 +1722,7 @@ static uint16_t get_analog_button(retro_input_state_t input_state_cb, int player
 
                // NOTE: If we're really just not holding the button, we're still going to get zero.
 
-               button = input_state_cb(player_index,
-                                                                               RETRO_DEVICE_JOYPAD,
-                                                                               0,
-                                                                               id) ? 255 : 0;
+               button = (ret & (1 << id)) ? 255 : 0;
        }
 
        return button;
@@ -1766,9 +1762,9 @@ void retro_run(void)
 
                        environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
                }
-       } else {
-               frame_count = 0;
        }
+   else
+               frame_count = 0;
 
        input_poll_cb();
 
@@ -1783,48 +1779,54 @@ void retro_run(void)
        float negcon_twist_amplitude;
        int negcon_i_rs;
        int negcon_ii_rs;
-       for(i = 0; i < PORTS_NUMBER; i++) {
+       for(i = 0; i < PORTS_NUMBER; i++)
+   {
+      int16_t ret    = 0;
                in_keystate[i] = 0;
 
                if (in_type[i] == PSE_PAD_TYPE_NONE)
                        continue;
+      
+      if (libretro_supports_bitmasks)
+         ret = input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
+      else
+      {
+         unsigned i;
+         for (i = 0; i < RETRO_DEVICE_ID_JOYPAD_R3+1; i++)
+         {
+            if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, i))
+               ret |= (1 << i);
+         }
+      }
 
                if (in_type[i] == PSE_PAD_TYPE_NEGCON)
                {
                        // Query digital inputs
                        //
                        // > Pad-Up
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP)){
+                       if (ret & (1 < RETRO_DEVICE_ID_JOYPAD_UP))
                                in_keystate[i] |= (1 << DKEY_UP);
-                       }
                        // > Pad-Right
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT))
                                in_keystate[i] |= (1 << DKEY_RIGHT);
-                       }
                        // > Pad-Down
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN))
                                in_keystate[i] |= (1 << DKEY_DOWN);
-                       }
                        // > Pad-Left
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT))
                                in_keystate[i] |= (1 << DKEY_LEFT);
-                       }
                        // > Start
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_START))
                                in_keystate[i] |= (1 << DKEY_START);
-                       }
                        // > neGcon A
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_A))
                                in_keystate[i] |= (1 << DKEY_CIRCLE);
-                       }
                        // > neGcon B
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_X))
                                in_keystate[i] |= (1 << DKEY_TRIANGLE);
-                       }
                        // > neGcon R shoulder (digital)
-                       if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)){
+                       if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_R))
                                in_keystate[i] |= (1 << DKEY_R1);
-                       }
                        // Query analog inputs
                        //
                        // From studying 'libpcsxcore/plugins.c' and 'frontend/plugin.c':
@@ -1838,24 +1840,23 @@ void retro_run(void)
                        // > NeGcon twist
                        // >> Get raw analog stick value and account for deadzone
                        lsx = input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
-                       if (lsx > negcon_deadzone){
+                       if (lsx > negcon_deadzone)
                                lsx = lsx - negcon_deadzone;
-                       } else if (lsx < -negcon_deadzone){
+                       else if (lsx < -negcon_deadzone)
                                lsx = lsx + negcon_deadzone;
-                       } else {
+                       else
                                lsx = 0;
-                       }
                        // >> Convert to an 'amplitude' [-1.0,1.0] and adjust response
                        negcon_twist_amplitude = (float)lsx / (float)(NEGCON_RANGE - negcon_deadzone);
-                       if (negcon_linearity == 2){
-                               if (negcon_twist_amplitude < 0.0){
+                       if (negcon_linearity == 2)
+         {
+                               if (negcon_twist_amplitude < 0.0)
                                        negcon_twist_amplitude = -(negcon_twist_amplitude * negcon_twist_amplitude);
-                               } else {
+            else
                                        negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude;
-                               }
-                       } else if (negcon_linearity == 3){
-                               negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude * negcon_twist_amplitude;
                        }
+         else if (negcon_linearity == 3)
+                               negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude * negcon_twist_amplitude;
                        // >> Convert to final 'in_analog' integer value [0,255]
                        in_analog_right[i][0] = MAX(MIN((int)(negcon_twist_amplitude * 128.0f) + 128, 255), 0);
                        // > NeGcon I + II
@@ -1870,48 +1871,45 @@ void retro_run(void)
                                // (Note: have never encountered a gamepad with significant differences
                                // in deadzone between left/right analog sticks, so use the regular 'twist'
                                // deadzone here)
-                               if (rsy > negcon_deadzone){
+                               if (rsy > negcon_deadzone)
                                        rsy = rsy - negcon_deadzone;
-                               } else {
+            else
                                        rsy = 0;
-                               }
                                // Convert to 'in_analog' integer value [0,255]
                                negcon_ii_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255);
                        } else {
-                               if (rsy < -negcon_deadzone){
+                               if (rsy < -negcon_deadzone)
                                        rsy = -1 * (rsy + negcon_deadzone);
-                               } else {
+            else
                                        rsy = 0;
-                               }
                                negcon_i_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255);
                        }
                        // >> NeGcon I
                        in_analog_right[i][1] = MAX(
                                MAX(
-                                       get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_R2),
-                                       get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_B)
+                                       get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_R2),
+                                       get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_B)
                                ),
                                negcon_i_rs
                        );
                        // >> NeGcon II
                        in_analog_left[i][0] = MAX(
                                MAX(
-                                       get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L2),
-                                       get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_Y)
+                                       get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L2),
+                                       get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_Y)
                                ),
                                negcon_ii_rs
                        );
                        // > NeGcon L
-                       in_analog_left[i][1] = get_analog_button(input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L);
+                       in_analog_left[i][1] = get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L);
                }
                else
                {
                        // Query digital inputs
-                       for (j = 0; j < RETRO_PSX_MAP_LEN; j++){
-                               if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, j)){
+                       for (j = 0; j < RETRO_PSX_MAP_LEN; j++)
+                               if (ret & (1 << j))
                                        in_keystate[i] |= retro_psx_map[j];
-                               }
-                       }
+
                        // Query analog inputs
                        if (in_type[i] == PSE_PAD_TYPE_ANALOGJOY || in_type[i] == PSE_PAD_TYPE_ANALOGPAD)
                        {
@@ -2159,6 +2157,9 @@ void retro_init(void)
        SaveFuncs.seek = save_seek;
        SaveFuncs.close = save_close;
 
+   if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
+      libretro_supports_bitmasks = true;
+
        update_variables(false);
        check_system_specs();
 }
@@ -2176,6 +2177,7 @@ void retro_deinit(void)
 #ifdef VITA
   deinit_vita_mmap();
 #endif
+   libretro_supports_bitmasks = false;
 }
 
 #ifdef VITA
index 8456415..8daec83 100755 (executable)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2016 The RetroArch team
+/* Copyright (C) 2010-2018 The RetroArch team
  *
  * ---------------------------------------------------------------------------------------
  * The following license statement only applies to this libretro API header (libretro.h).
@@ -32,7 +32,7 @@ extern "C" {
 #endif
 
 #ifndef __cplusplus
-#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
+#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3)
 /* Hack applied for MSVC when compiling in C89 mode
  * as it isn't C99-compliant. */
 #define bool unsigned char
@@ -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,52 @@ 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 and
+ * -0x8000 being out of bounds.
+ * 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 [-0x7fff, 0x7fff],
+ * although some devices may return -0x8000.
+ * 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 +157,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
@@ -192,12 +202,14 @@ extern "C" {
 #define RETRO_DEVICE_ID_JOYPAD_L3      14
 #define RETRO_DEVICE_ID_JOYPAD_R3      15
 
+#define RETRO_DEVICE_ID_JOYPAD_MASK    256
+
 /* Index / Id values for ANALOG device. */
-#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
+#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
@@ -209,20 +221,36 @@ 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
 #define RETRO_DEVICE_ID_POINTER_Y         1
 #define RETRO_DEVICE_ID_POINTER_PRESSED   2
+#define RETRO_DEVICE_ID_POINTER_COUNT     3
 
 /* Returned from retro_get_region(). */
 #define RETRO_REGION_NTSC  0
@@ -231,28 +259,33 @@ extern "C" {
 /* Id values for LANGUAGE */
 enum retro_language
 {
-   RETRO_LANGUAGE_ENGLISH             =  0,
-   RETRO_LANGUAGE_JAPANESE            =  1,
-   RETRO_LANGUAGE_FRENCH              =  2,
-   RETRO_LANGUAGE_SPANISH             =  3,
-   RETRO_LANGUAGE_GERMAN              =  4,
-   RETRO_LANGUAGE_ITALIAN             =  5,
-   RETRO_LANGUAGE_DUTCH               =  6,
-   RETRO_LANGUAGE_PORTUGUESE          =  7,
-   RETRO_LANGUAGE_RUSSIAN             =  8,
-   RETRO_LANGUAGE_KOREAN              =  9,
-   RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10,
-   RETRO_LANGUAGE_CHINESE_SIMPLIFIED  = 11,
-   RETRO_LANGUAGE_ESPERANTO           = 12,
-   RETRO_LANGUAGE_POLISH              = 13,
+   RETRO_LANGUAGE_ENGLISH             = 0,
+   RETRO_LANGUAGE_JAPANESE            = 1,
+   RETRO_LANGUAGE_FRENCH              = 2,
+   RETRO_LANGUAGE_SPANISH             = 3,
+   RETRO_LANGUAGE_GERMAN              = 4,
+   RETRO_LANGUAGE_ITALIAN             = 5,
+   RETRO_LANGUAGE_DUTCH               = 6,
+   RETRO_LANGUAGE_PORTUGUESE_BRAZIL   = 7,
+   RETRO_LANGUAGE_PORTUGUESE_PORTUGAL = 8,
+   RETRO_LANGUAGE_RUSSIAN             = 9,
+   RETRO_LANGUAGE_KOREAN              = 10,
+   RETRO_LANGUAGE_CHINESE_TRADITIONAL = 11,
+   RETRO_LANGUAGE_CHINESE_SIMPLIFIED  = 12,
+   RETRO_LANGUAGE_ESPERANTO           = 13,
+   RETRO_LANGUAGE_POLISH              = 14,
+   RETRO_LANGUAGE_VIETNAMESE          = 15,
+   RETRO_LANGUAGE_ARABIC              = 16,
+   RETRO_LANGUAGE_GREEK               = 17,
+   RETRO_LANGUAGE_TURKISH             = 18,
    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
@@ -350,6 +383,10 @@ enum retro_key
    RETROK_x              = 120,
    RETROK_y              = 121,
    RETROK_z              = 122,
+   RETROK_LEFTBRACE      = 123,
+   RETROK_BAR            = 124,
+   RETROK_RIGHTBRACE     = 125,
+   RETROK_TILDE          = 126,
    RETROK_DELETE         = 127,
 
    RETROK_KP0            = 256,
@@ -420,6 +457,7 @@ enum retro_key
    RETROK_POWER          = 320,
    RETROK_EURO           = 321,
    RETROK_UNDO           = 322,
+   RETROK_OEM_102        = 323,
 
    RETROK_LAST,
 
@@ -442,7 +480,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. */
@@ -451,12 +489,14 @@ enum retro_mod
 /* Environment commands. */
 #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, 
+                                            * NOTE: As of 2019 this callback is considered deprecated in favor of
+                                            * using core options to manage overscan in a more nuanced, core-specific way.
+                                            *
+                                            * Boolean value whether or not the implementation should use overscan,
                                             * or crop away overscan.
                                             */
 #define RETRO_ENVIRONMENT_GET_CAN_DUPE  3  /* bool * --
@@ -464,15 +504,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) --
@@ -500,15 +540,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
@@ -516,19 +556,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
@@ -537,52 +577,55 @@ 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 
-                                            * retro_set_environment).
-                                            *
-                                            * 'data' points to an array of retro_variable structs 
+                                            * This should be called the first time as early as
+                                            * possible (ideally in retro_set_environment).
+                                            * Afterward it may be called again for the core to communicate
+                                            * updated options to the frontend, but the number of core
+                                            * options must not change from the number in the initial call.
+                                           *
+                                            * '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.
@@ -590,11 +633,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
@@ -605,72 +648,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_FRAME_TIME_CALLBACK 21
+                                           /* const struct retro_frame_time_callback * --
+                                            * 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,
+                                            * slow-motion, frame stepping, etc.
+                                            * In this case the delta time will use the reference value
+                                            * in frame_time_callback..
+                                            */
 #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 
-                                            * invocation of retro_run().
-                                            * 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 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().
@@ -679,56 +722,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.
                                             */
@@ -736,7 +779,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.
@@ -745,76 +788,77 @@ 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, 
-                                            * high scores, etc, if the libretro core
+                                            * Returns the "save" directory of the frontend, unless there is no
+                                            * save directory available. The save directory should be used to
+                                            * store SRAM, memory cards, high scores, etc, if the libretro core
                                             * cannot use the regular memory interface (retro_get_memory_data()).
                                             *
-                                            * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for 
-                                            * similar things before.
-                                            * They should still check GET_SYSTEM_DIRECTORY if they want to 
-                                            * be backwards compatible.
-                                            * The path here can be NULL. It should only be non-NULL if the 
-                                            * frontend user has set a specific save path.
+                                            * If the frontend cannot designate a save directory, it will return
+                                            * NULL to indicate that the core should attempt to operate without a
+                                            * save directory set.
+                                            *
+                                            * NOTE: early libretro cores used the system directory for save
+                                            * files. Cores that need to be backwards-compatible can still check
+                                            * GET_SYSTEM_DIRECTORY.
                                             */
 #define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32
                                            /* const struct retro_system_av_info * --
-                                            * Sets a new av_info structure. This can only be called from 
+                                            * 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
@@ -822,68 +866,81 @@ 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 subclasses are recognized in calls to
                                             * retro_set_controller_port_device().
                                             *
-                                            * Some emulators such as Super Nintendo
-                                            * support multiple lightgun types which must be specifically 
-                                            * selected from.
-                                            * It is therefore sometimes necessary for a frontend to be able 
-                                            * to tell the core about a special kind of input device which is 
-                                            * not covered by the libretro input API.
+                                            * Some emulators such as Super Nintendo support multiple lightgun
+                                            * types which must be specifically selected from. It is therefore
+                                            * sometimes necessary for a frontend to be able to tell the core
+                                            * about a special kind of input device which is not specifcally
+                                            * provided by the Libretro API.
                                             *
-                                            * In order for a frontend to understand the workings of an input device,
-                                            * it must be a specialized type
-                                            * of the generic device types already defined in the libretro API.
+                                            * In order for a frontend to understand the workings of those devices,
+                                            * they must be defined as a specialized subclass of the generic device
+                                            * types already defined in the libretro API.
                                             *
-                                            * Which devices are supported can vary per input port.
-                                            * The core must pass an array of const struct retro_controller_info which 
-                                            * is terminated with a blanked out struct. Each element of the struct 
-                                            * corresponds to an ascending port index to 
-                                            * retro_set_controller_port_device().
-                                            * Even if special device types are set in the libretro core, 
+                                            * The core must pass an array of const struct retro_controller_info which
+                                            * is terminated with a blanked out struct. Each element of the
+                                            * retro_controller_info struct corresponds to the ascending port index
+                                            * that is passed to retro_set_controller_port_device() when that function
+                                            * is called to indicate to the core that the frontend has changed the
+                                            * active device subclass. SEE ALSO: retro_set_controller_port_device()
+                                            *
+                                            * The ascending input port indexes provided by the core in the struct
+                                            * are generally presented by frontends as ascending User # or Player #,
+                                            * such as Player 1, Player 2, Player 3, etc. Which device subclasses are
+                                            * supported can vary per input port.
+                                            *
+                                            * The first inner element of each entry in the retro_controller_info array
+                                            * is a retro_controller_description struct that specifies the names and
+                                            * codes of all device subclasses that are available for the corresponding
+                                            * User or Player, beginning with the generic Libretro device that the
+                                            * subclasses are derived from. The second inner element of each entry is the
+                                            * total number of subclasses that are listed in the retro_controller_description.
+                                            *
+                                            * NOTE: Even if special device types are set in the libretro core,
                                             * libretro should only poll input based on the base input device types.
                                             */
 #define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL)
                                            /* const struct retro_memory_map * --
-                                            * This environment call lets a libretro core tell the frontend 
+                                            * 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
@@ -921,11 +978,315 @@ enum retro_mod
                                             * A frontend must make sure that the pointer obtained from this function is
                                             * writeable (and readable).
                                             */
+#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* const struct retro_hw_render_interface ** --
+                                            * Returns an API specific rendering interface for accessing API specific data.
+                                            * Not all HW rendering APIs support or need this.
+                                            * The contents of the returned pointer is specific to the rendering API
+                                            * being used. See the various headers like libretro_vulkan.h, etc.
+                                            *
+                                            * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
+                                            * Similarly, after context_destroyed callback returns,
+                                            * the contents of the HW_RENDER_INTERFACE are invalidated.
+                                            */
+#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* const bool * --
+                                            * If true, the libretro implementation supports achievements
+                                            * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
+                                            * or via retro_get_memory_data/retro_get_memory_size.
+                                            *
+                                            * This must be called before the first call to retro_run.
+                                            */
+#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* const struct retro_hw_render_context_negotiation_interface * --
+                                            * Sets an interface which lets the libretro core negotiate with frontend how a context is created.
+                                            * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
+                                            * This interface will be used when the frontend is trying to create a HW rendering context,
+                                            * so it will be used after SET_HW_RENDER, but before the context_reset callback.
+                                            */
+#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
+                                           /* uint64_t * --
+                                            * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
+                                            * recognize or support. Should be set in either retro_init or retro_load_game, but not both.
+                                            */
+#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* N/A (null) * --
+                                            * The frontend will try to use a 'shared' hardware context (mostly applicable
+                                            * to OpenGL) when a hardware context is being set up.
+                                            *
+                                            * Returns true if the frontend supports shared hardware contexts and false
+                                            * if the frontend does not support shared hardware contexts.
+                                            *
+                                            * This will do nothing on its own until SET_HW_RENDER env callbacks are
+                                            * being used.
+                                            */
+#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* struct retro_vfs_interface_info * --
+                                            * Gets access to the VFS interface.
+                                            * VFS presence needs to be queried prior to load_game or any
+                                            * get_system/save/other_directory being called to let front end know
+                                            * core supports VFS before it starts handing out paths.
+                                            * It is recomended to do so in retro_set_environment
+                                            */
+#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* struct retro_led_interface * --
+                                            * Gets an interface which is used by a libretro core to set
+                                            * state of LEDs.
+                                            */
+#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* int * --
+                                            * Tells the core if the frontend wants audio or video.
+                                            * If disabled, the frontend will discard the audio or video,
+                                            * so the core may decide to skip generating a frame or generating audio.
+                                            * This is mainly used for increasing performance.
+                                            * Bit 0 (value 1): Enable Video
+                                            * Bit 1 (value 2): Enable Audio
+                                            * Bit 2 (value 4): Use Fast Savestates.
+                                            * Bit 3 (value 8): Hard Disable Audio
+                                            * Other bits are reserved for future use and will default to zero.
+                                            * If video is disabled:
+                                            * * The frontend wants the core to not generate any video,
+                                            *   including presenting frames via hardware acceleration.
+                                            * * The frontend's video frame callback will do nothing.
+                                            * * After running the frame, the video output of the next frame should be
+                                            *   no different than if video was enabled, and saving and loading state
+                                            *   should have no issues.
+                                            * If audio is disabled:
+                                            * * The frontend wants the core to not generate any audio.
+                                            * * The frontend's audio callbacks will do nothing.
+                                            * * After running the frame, the audio output of the next frame should be
+                                            *   no different than if audio was enabled, and saving and loading state
+                                            *   should have no issues.
+                                            * Fast Savestates:
+                                            * * Guaranteed to be created by the same binary that will load them.
+                                            * * Will not be written to or read from the disk.
+                                            * * Suggest that the core assumes loading state will succeed.
+                                            * * Suggest that the core updates its memory buffers in-place if possible.
+                                            * * Suggest that the core skips clearing memory.
+                                            * * Suggest that the core skips resetting the system.
+                                            * * Suggest that the core may skip validation steps.
+                                            * Hard Disable Audio:
+                                            * * Used for a secondary core when running ahead.
+                                            * * Indicates that the frontend will never need audio from the core.
+                                            * * Suggests that the core may stop synthesizing audio, but this should not
+                                            *   compromise emulation accuracy.
+                                            * * Audio output for the next frame does not matter, and the frontend will
+                                            *   never need an accurate audio state in the future.
+                                            * * State will never be saved when using Hard Disable Audio.
+                                            */
+#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                           /* struct retro_midi_interface ** --
+                                            * Returns a MIDI interface that can be used for raw data I/O.
+                                            */
+
+#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                            /* bool * --
+                                            * Boolean value that indicates whether or not the frontend is in
+                                            * fastforwarding mode.
+                                            */
+
+#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                            /* float * --
+                                            * Float value that lets us know what target refresh rate 
+                                            * is curently in use by the frontend.
+                                            *
+                                            * The core can use the returned value to set an ideal 
+                                            * refresh rate/framerate.
+                                            */
+
+#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+                                            /* bool * --
+                                            * Boolean value that indicates whether or not the frontend supports
+                                            * input bitmasks being returned by retro_input_state_t. The advantage
+                                            * of this is that retro_input_state_t has to be only called once to 
+                                            * grab all button states instead of multiple times.
+                                            *
+                                            * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
+                                            * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD).
+                                            * It will return a bitmask of all the digital buttons.
+                                            */
+
+/* VFS functionality */
+
+/* File paths:
+ * File paths passed as parameters when using this API shall be well formed UNIX-style,
+ * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator.
+ * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead).
+ * Other than the directory separator, cores shall not make assumptions about path format:
+ * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths.
+ * Cores may replace the basename or remove path components from the end, and/or add new components;
+ * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end.
+ * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much.
+ * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable).
+ * Cores are allowed to try using them, but must remain functional if the front rejects such requests.
+ * Cores are encouraged to use the libretro-common filestream functions for file I/O,
+ * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate
+ * and provide platform-specific fallbacks in cases where front ends do not support VFS. */
+
+/* Opaque file handle
+ * Introduced in VFS API v1 */
+struct retro_vfs_file_handle;
+
+/* Opaque directory handle
+ * Introduced in VFS API v3 */
+struct retro_vfs_dir_handle;
+
+/* File open flags
+ * Introduced in VFS API v1 */
+#define RETRO_VFS_FILE_ACCESS_READ            (1 << 0) /* Read only mode */
+#define RETRO_VFS_FILE_ACCESS_WRITE           (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */
+#define RETRO_VFS_FILE_ACCESS_READ_WRITE      (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/
+#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */
+
+/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use,
+   and how they react to unlikely external interference (for example someone else writing to that file,
+   or the file's server going down), behavior will not change. */
+#define RETRO_VFS_FILE_ACCESS_HINT_NONE              (0)
+/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */
+#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS   (1 << 0)
+
+/* Seek positions */
+#define RETRO_VFS_SEEK_POSITION_START    0
+#define RETRO_VFS_SEEK_POSITION_CURRENT  1
+#define RETRO_VFS_SEEK_POSITION_END      2
+
+/* stat() result flags
+ * Introduced in VFS API v3 */
+#define RETRO_VFS_STAT_IS_VALID               (1 << 0)
+#define RETRO_VFS_STAT_IS_DIRECTORY           (1 << 1)
+#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL   (1 << 2)
+
+/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle
+ * Introduced in VFS API v1 */
+typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream);
+
+/* Open a file for reading or writing. If path points to a directory, this will
+ * fail. Returns the opaque file handle, or NULL for error.
+ * Introduced in VFS API v1 */
+typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints);
+
+/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure.
+ * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream);
+
+/* Return the size of the file in bytes, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream);
+
+/* Truncate file to specified size. Returns 0 on success or -1 on error
+ * Introduced in VFS API v2 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length);
+
+/* Get the current read / write position for the file. Returns -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream);
+
+/* Set the current read/write position for the file. Returns the new position, -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position);
+
+/* Read data from a file. Returns the number of bytes read, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len);
+
+/* Write data to a file. Returns the number of bytes written, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len);
+
+/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure.
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream);
+
+/* Delete the specified file. Returns 0 on success, -1 on failure
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path);
+
+/* Rename the specified file. Returns 0 on success, -1 on failure
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path);
+
+/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid.
+ * Additionally stores file size in given variable, unless NULL is given.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size);
+
+/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir);
+
+/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error.
+ * Support for the include_hidden argument may vary depending on the platform.
+ * Introduced in VFS API v3 */
+typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden);
+
+/* Read the directory entry at the current position, and move the read pointer to the next position.
+ * Returns true on success, false if already on the last entry.
+ * Introduced in VFS API v3 */
+typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Get the name of the last entry read. Returns a string on success, or NULL for error.
+ * The returned string pointer is valid until the next call to readdir or closedir.
+ * Introduced in VFS API v3 */
+typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error).
+ * Introduced in VFS API v3 */
+typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure.
+ * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream);
+
+struct retro_vfs_interface
+{
+   /* VFS API v1 */
+       retro_vfs_get_path_t get_path;
+       retro_vfs_open_t open;
+       retro_vfs_close_t close;
+       retro_vfs_size_t size;
+       retro_vfs_tell_t tell;
+       retro_vfs_seek_t seek;
+       retro_vfs_read_t read;
+       retro_vfs_write_t write;
+       retro_vfs_flush_t flush;
+       retro_vfs_remove_t remove;
+       retro_vfs_rename_t rename;
+   /* VFS API v2 */
+   retro_vfs_truncate_t truncate;
+   /* VFS API v3 */
+   retro_vfs_stat_t stat;
+   retro_vfs_mkdir_t mkdir;
+   retro_vfs_opendir_t opendir;
+   retro_vfs_readdir_t readdir;
+   retro_vfs_dirent_get_name_t dirent_get_name;
+   retro_vfs_dirent_is_dir_t dirent_is_dir;
+   retro_vfs_closedir_t closedir;
+};
+
+struct retro_vfs_interface_info
+{
+   /* Set by core: should this be higher than the version the front end supports,
+    * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call
+    * Introduced in VFS API v1 */
+   uint32_t required_interface_version;
+
+   /* Frontend writes interface pointer here. The frontend also sets the actual
+    * version, must be at least required_interface_version.
+    * Introduced in VFS API v1 */
+   struct retro_vfs_interface *iface;
+};
 
 enum retro_hw_render_interface_type
 {
-   RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
-   RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
+       RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
+       RETRO_HW_RENDER_INTERFACE_D3D9   = 1,
+       RETRO_HW_RENDER_INTERFACE_D3D10  = 2,
+       RETRO_HW_RENDER_INTERFACE_D3D11  = 3,
+       RETRO_HW_RENDER_INTERFACE_D3D12  = 4,
+   RETRO_HW_RENDER_INTERFACE_GSKIT_PS2  = 5,
+   RETRO_HW_RENDER_INTERFACE_DUMMY  = INT_MAX
 };
 
 /* Base struct. All retro_hw_render_interface_* types
@@ -935,81 +1296,147 @@ struct retro_hw_render_interface
    enum retro_hw_render_interface_type interface_type;
    unsigned interface_version;
 };
-#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
-                                           /* const struct retro_hw_render_interface ** --
-                                            * Returns an API specific rendering interface for accessing API specific data.
-                                            * Not all HW rendering APIs support or need this.
-                                            * The contents of the returned pointer is specific to the rendering API
-                                            * being used. See the various headers like libretro_vulkan.h, etc.
-                                            *
-                                            * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
-                                            * Similarly, after context_destroyed callback returns,
-                                            * the contents of the HW_RENDER_INTERFACE are invalidated.
-                                            */
 
-#define RETRO_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. */
-#define RETRO_MEMDESC_ALIGN_4   (2 << 16)
-#define RETRO_MEMDESC_ALIGN_8   (3 << 16)
-#define RETRO_MEMDESC_MINSIZE_2 (1 << 24)  /* All memory in this region is accessed at least 2 bytes at the time. */
-#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
-#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
+typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state);
+struct retro_led_interface
+{
+    retro_set_led_state_t set_led_state;
+};
+
+/* Retrieves the current state of the MIDI input.
+ * Returns true if it's enabled, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void);
+
+/* Retrieves the current state of the MIDI output.
+ * Returns true if it's enabled, false otherwise */
+typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void);
+
+/* Reads next byte from the input stream.
+ * Returns true if byte is read, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte);
+
+/* Writes byte to the output stream.
+ * 'delta_time' is in microseconds and represent time elapsed since previous write.
+ * Returns true if byte is written, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time);
+
+/* Flushes previously written data.
+ * Returns true if successful, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void);
+
+struct retro_midi_interface
+{
+   retro_midi_input_enabled_t input_enabled;
+   retro_midi_output_enabled_t output_enabled;
+   retro_midi_read_t read;
+   retro_midi_write_t write;
+   retro_midi_flush_t flush;
+};
+
+enum retro_hw_render_context_negotiation_interface_type
+{
+   RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0,
+   RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX
+};
+
+/* Base struct. All retro_hw_render_context_negotiation_interface_* types
+ * contain at least these fields. */
+struct retro_hw_render_context_negotiation_interface
+{
+   enum retro_hw_render_context_negotiation_interface_type interface_type;
+   unsigned interface_version;
+};
+
+/* Serialized state is incomplete in some way. Set if serialization is
+ * usable in typical end-user cases but should not be relied upon to
+ * implement frame-sensitive frontend features such as netplay or
+ * rerecording. */
+#define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0)
+/* The core must spend some time initializing before serialization is
+ * supported. retro_serialize() will initially fail; retro_unserialize()
+ * and retro_serialize_size() may or may not work correctly either. */
+#define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1)
+/* Serialization size may change within a session. */
+#define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2)
+/* Set by the frontend to acknowledge that it supports variable-sized
+ * states. */
+#define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3)
+/* Serialized state can only be loaded during the same session. */
+#define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4)
+/* Serialized state cannot be loaded on an architecture with a different
+ * endianness from the one it was saved on. */
+#define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5)
+/* Serialized state cannot be loaded on a different platform from the one it
+ * was saved on for reasons other than endianness, such as word size
+ * dependence */
+#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6)
+
+#define RETRO_MEMDESC_CONST      (1 << 0)   /* The frontend will never change this memory area once retro_load_game has returned. */
+#define RETRO_MEMDESC_BIGENDIAN  (1 << 1)   /* The memory area contains big endian data. Default is little endian. */
+#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2)   /* The memory area is system RAM.  This is main RAM of the gaming system. */
+#define RETRO_MEMDESC_SAVE_RAM   (1 << 3)   /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */
+#define RETRO_MEMDESC_VIDEO_RAM  (1 << 4)   /* The memory area is video RAM (VRAM) */
+#define RETRO_MEMDESC_ALIGN_2    (1 << 16)  /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */
+#define RETRO_MEMDESC_ALIGN_4    (2 << 16)
+#define RETRO_MEMDESC_ALIGN_8    (3 << 16)
+#define RETRO_MEMDESC_MINSIZE_2  (1 << 24)  /* All memory in this region is accessed at least 2 bytes at the time. */
+#define RETRO_MEMDESC_MINSIZE_4  (2 << 24)
+#define RETRO_MEMDESC_MINSIZE_8  (3 << 24)
 struct retro_memory_descriptor
 {
    uint64_t flags;
 
    /* Pointer to the start of the relevant ROM or RAM chip.
-    * It's strongly recommended to use 'offset' if possible, rather than 
+    * 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_-, 
+    * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */
+
+   /* The address space name must consist of only a-zA-Z0-9_-,
     * should be as short as feasible (maximum length is 8 plus the NUL),
-    * and may not be any other address space plus one or more 0-9A-F 
+    * 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.
@@ -1023,27 +1450,58 @@ 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 
-    * there is no namespace 'AR')
-    * blank+'B' - not valid, because it's ambigous which address space B1234 
-    * would refer to.
-    * The length can't be used for that purpose; the frontend may want 
+    * 'ARB'+blank - valid (the B can't be part of the address either, because
+    *                      there is no namespace 'AR')
+    * blank+'B' - not valid, because it's ambigous which address space B1234
+    *             would refer to.
+    * The length can't be used for that purpose; the frontend may want
     * to append arbitrary data to an address, without a separator. */
    const char *addrspace;
+
+   /* TODO: When finalizing this one, add a description field, which should be
+    * "WRAM" or something roughly equally long. */
+
+   /* TODO: When finalizing this one, replace 'select' with 'limit', which tells
+    * which bits can vary and still refer to the same address (limit = ~select).
+    * TODO: limit? range? vary? something else? */
+
+   /* TODO: When finalizing this one, if 'len' is above what 'select' (or
+    * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len'
+    * and 'select' != 0, and the mappings don't tell how the system switches the
+    * banks. */
+
+   /* TODO: When finalizing this one, fix the 'len' bit removal order.
+    * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00.
+    * Algorithm: Take bits highest to lowest, but if it goes above len, clear
+    * the most recent addition and continue on the next bit.
+    * TODO: Can the above be optimized? Is "remove the lowest bit set in both
+    * pointer and 'len'" equivalent? */
+
+   /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing
+    * the emulated memory in 32-bit chunks, native endian. But that's nothing
+    * compared to Darek Mihocka <http://www.emulators.com/docs/nx07_vm101.htm>
+    * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE
+    * RAM backwards! I'll want to represent both of those, via some flags.
+    *
+    * I suspect MAME either didn't think of that idea, or don't want the #ifdef.
+    * Not sure which, nor do I really care. */
+
+   /* TODO: Some of those flags are unused and/or don't really make sense. Clean
+    * them up. */
 };
 
-/* The frontend may use the largest value of 'start'+'select' in a 
+/* 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
@@ -1052,7 +1510,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
@@ -1078,13 +1536,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). */
@@ -1102,8 +1560,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;
 };
@@ -1122,11 +1580,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;
@@ -1144,38 +1602,38 @@ 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;
 };
 
-typedef void (*retro_proc_address_t)(void);
+typedef void (RETRO_CALLCONV *retro_proc_address_t)(void);
 
 /* libretro API extension functions:
  * (None here so far).
  *
  * Get a symbol from a libretro core.
- * Cores should only return symbols which are actual 
+ * 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.
  */
-typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym);
+typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym);
 
 struct retro_get_proc_address_interface
 {
@@ -1193,7 +1651,7 @@ enum retro_log_level
 };
 
 /* Logging function. Takes log level argument as well. */
-typedef void (*retro_log_printf_t)(enum retro_log_level level,
+typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level,
       const char *fmt, ...);
 
 struct retro_log_callback
@@ -1224,6 +1682,8 @@ struct retro_log_callback
 #define RETRO_SIMD_VFPV4    (1 << 17)
 #define RETRO_SIMD_POPCNT   (1 << 18)
 #define RETRO_SIMD_MOVBE    (1 << 19)
+#define RETRO_SIMD_CMOV     (1 << 20)
+#define RETRO_SIMD_ASIMD    (1 << 21)
 
 typedef uint64_t retro_perf_tick_t;
 typedef int64_t retro_time_t;
@@ -1241,34 +1701,34 @@ struct retro_perf_counter
 /* Returns current time in microseconds.
  * Tries to use the most accurate timer available.
  */
-typedef retro_time_t (*retro_perf_get_time_usec_t)(void);
+typedef retro_time_t (RETRO_CALLCONV *retro_perf_get_time_usec_t)(void);
 
 /* A simple counter. Usually nanoseconds, but can also be CPU cycles.
- * 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_perf_get_counter_t)(void);
+typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void);
 
 /* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */
-typedef uint64_t (*retro_get_cpu_features_t)(void);
+typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_t)(void);
 
 /* Asks frontend to log and/or display the state of performance counters.
  * Performance counters can always be poked into manually as well.
  */
-typedef void (*retro_perf_log_t)(void);
+typedef void (RETRO_CALLCONV *retro_perf_log_t)(void);
 
 /* Register a performance counter.
- * 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_perf_register_t)(struct retro_perf_counter *counter);
+typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter);
 
 /* Starts a registered counter. */
-typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter);
+typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter);
 
 /* Stops a registered counter. */
-typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter);
+typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *counter);
 
 /* For convenience it can be useful to wrap register, start and stop in macros.
  * E.g.:
@@ -1331,10 +1791,10 @@ enum retro_sensor_action
 #define RETRO_SENSOR_ACCELEROMETER_Y 1
 #define RETRO_SENSOR_ACCELEROMETER_Z 2
 
-typedef bool (*retro_set_sensor_state_t)(unsigned port, 
+typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
       enum retro_sensor_action action, unsigned rate);
 
-typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id);
+typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id);
 
 struct retro_sensor_interface
 {
@@ -1351,76 +1811,80 @@ enum retro_camera_buffer
 };
 
 /* Starts the camera driver. Can only be called in retro_run(). */
-typedef bool (*retro_camera_start_t)(void);
+typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void);
 
 /* Stops the camera driver. Can only be called in retro_run(). */
-typedef void (*retro_camera_stop_t)(void);
+typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void);
 
-/* Callback which signals when the camera driver is initialized 
+/* Callback which signals when the camera driver is initialized
  * and/or deinitialized.
  * retro_camera_start_t can be called in initialized callback.
  */
-typedef void (*retro_camera_lifetime_status_t)(void);
+typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void);
 
 /* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer.
  * Width, height and pitch are similar to retro_video_refresh_t.
  * First pixel is top-left origin.
  */
-typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, 
+typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer,
       unsigned width, unsigned height, size_t pitch);
 
 /* 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_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;
 
-   unsigned width; /* Desired resolution for camera. Is only used as a hint. */
+   /* Desired resolution for camera. Is only used as a hint. */
+   unsigned width;
    unsigned height;
-   retro_camera_start_t start; /* Set by frontend. */
-   retro_camera_stop_t stop; /* Set by frontend. */
+
+   /* Set by frontend. */
+   retro_camera_start_t start;
+   retro_camera_stop_t stop;
 
    /* Set by libretro core if raw framebuffer callbacks will be used. */
    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,
@@ -1429,28 +1893,28 @@ struct retro_camera_callback
  * interval_ms is the interval expressed in milliseconds.
  * interval_distance is the distance interval expressed in meters.
  */
-typedef void (*retro_location_set_interval_t)(unsigned interval_ms,
+typedef void (RETRO_CALLCONV *retro_location_set_interval_t)(unsigned interval_ms,
       unsigned interval_distance);
 
 /* Start location services. The device will start listening for changes to the
- * current location at regular intervals (which are defined with 
+ * current location at regular intervals (which are defined with
  * retro_location_set_interval_t). */
-typedef bool (*retro_location_start_t)(void);
+typedef bool (RETRO_CALLCONV *retro_location_start_t)(void);
 
-/* Stop location services. The device will stop listening for changes 
+/* Stop location services. The device will stop listening for changes
  * to the current location. */
-typedef void (*retro_location_stop_t)(void);
+typedef void (RETRO_CALLCONV *retro_location_stop_t)(void);
 
-/* Get the position of the current location. Will set parameters to 
+/* Get the position of the current location. Will set parameters to
  * 0 if no new  location update has happened since the last time. */
-typedef bool (*retro_location_get_position_t)(double *lat, double *lon,
+typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon,
       double *horiz_accuracy, double *vert_accuracy);
 
-/* 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.
  */
-typedef void (*retro_location_lifetime_status_t)(void);
+typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void);
 
 struct retro_location_callback
 {
@@ -1471,14 +1935,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_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
@@ -1487,16 +1951,16 @@ struct retro_rumble_interface
 };
 
 /* Notifies libretro that audio data should be written. */
-typedef void (*retro_audio_callback_t)(void);
+typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void);
 
-/* True: Audio driver in frontend is active, and callback is 
+/* True: Audio driver in frontend is active, and callback is
  * expected to be called regularily.
- * 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).
  */
-typedef void (*retro_audio_set_state_callback_t)(bool enabled);
+typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled);
 
 struct retro_audio_callback
 {
@@ -1504,21 +1968,21 @@ 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. */
 typedef int64_t retro_usec_t;
-typedef void (*retro_frame_time_callback_t)(retro_usec_t usec);
+typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec);
 struct retro_frame_time_callback
 {
    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;
 };
@@ -1534,24 +1998,24 @@ 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_hw_context_reset_t)(void);
+typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void);
 
 /* Gets current framebuffer which is to be rendered to.
  * Could change every frame potentially.
  */
-typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
+typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void);
 
 /* Get a symbol from HW context. */
-typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
+typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym);
 
 enum retro_hw_context_type
 {
    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/
@@ -1566,6 +2030,10 @@ enum retro_hw_context_type
    /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
    RETRO_HW_CONTEXT_VULKAN           = 6,
 
+   /* Direct3D, set version_major to select the type of interface
+    * returned by RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
+   RETRO_HW_CONTEXT_DIRECT3D         = 7,
+
    RETRO_HW_CONTEXT_DUMMY = INT_MAX
 };
 
@@ -1577,10 +2045,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
@@ -1593,7 +2061,8 @@ struct retro_hw_render_callback
     * be providing preallocated framebuffers. */
    retro_hw_get_current_framebuffer_t get_current_framebuffer;
 
-   /* Set by frontend. */
+   /* Set by frontend.
+    * Can return all relevant functions, including glClear on Windows. */
    retro_hw_get_proc_address_t get_proc_address;
 
    /* Set if render buffers should have depth component attached.
@@ -1604,48 +2073,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.
     */
 
@@ -1653,7 +2122,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.
@@ -1661,16 +2130,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_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
@@ -1679,39 +2148,39 @@ 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).
  */
 
 /* If ejected is true, "ejects" the virtual disk tray.
  * When ejected, the disk image index can be set.
  */
-typedef bool (*retro_set_eject_state_t)(bool ejected);
+typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected);
 
 /* Gets current eject state. The initial state is 'not ejected'. */
-typedef bool (*retro_get_eject_state_t)(void);
+typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void);
 
 /* Gets current disk index. First disk is index 0.
  * If return value is >= get_num_images(), no disk is currently inserted.
  */
-typedef unsigned (*retro_get_image_index_t)(void);
+typedef unsigned (RETRO_CALLCONV *retro_get_image_index_t)(void);
 
 /* Sets image index. Can only be called when disk is ejected.
- * 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_set_image_index_t)(unsigned index);
+typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index);
 
 /* Gets total number of images which are available to use. */
-typedef unsigned (*retro_get_num_images_t)(void);
+typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void);
 
 struct retro_game_info;
 
@@ -1719,22 +2188,22 @@ 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.
  */
-typedef bool (*retro_replace_image_index_t)(unsigned index,
+typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
       const struct retro_game_info *info);
 
 /* 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_add_image_index_t)(void);
+typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
 
 struct retro_disk_control_callback
 {
@@ -1763,7 +2232,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. */
@@ -1793,43 +2262,52 @@ 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 
-    * in retro_game_info::path.
-    * ::data and ::size are both invalid.
+   /* Libretro cores that need to have direct access to their content
+    * files, including cores which use the path of the content files to
+    * determine the paths of other files, should set need_fullpath to true.
+    *
+    * Cores should strive for setting need_fullpath to false,
+    * as it allows the frontend to perform patching, etc.
     *
-    * If false, ::data and ::size are guaranteed to be valid, but ::path 
-    * might not be valid.
+    * If need_fullpath is true and retro_load_game() is called:
+    *    - retro_game_info::path is guaranteed to have a valid path
+    *    - retro_game_info::data and retro_game_info::size are invalid
     *
-    * 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 
-    * the frontend to perform patching, etc. */
-   bool        need_fullpath;                                       
+    * If need_fullpath is false and retro_load_game() is called:
+    *    - retro_game_info::path may be NULL
+    *    - retro_game_info::data and retro_game_info::size are guaranteed
+    *      to be valid
+    *
+    * See also:
+    *    - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY
+    *    - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY
+    */
+   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
@@ -1861,14 +2339,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;
 };
@@ -1876,12 +2354,14 @@ struct retro_variable
 struct retro_game_info
 {
    const char *path;       /* Path to game, UTF-8 encoded.
-                            * Usually used as a reference.
-                            * May be NULL if rom was loaded from stdin
-                            * or similar. 
-                            * retro_system_info::need_fullpath guaranteed 
+                            * Sometimes used as a reference for building other paths.
+                            * May be NULL if game was loaded from stdin or similar,
+                            * but in this case some cores will be unable to load `data`.
+                            * So, it is preferable to fabricate something here instead
+                            * 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. */
@@ -1919,29 +2399,29 @@ 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_environment_t)(unsigned cmd, void *data);
+typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data);
 
-/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian 
+/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian
  * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT).
  *
  * 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_video_refresh_t)(const void *data, unsigned width,
+typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width,
       unsigned height, size_t pitch);
 
-/* 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.
  */
-typedef void (*retro_audio_sample_t)(int16_t left, int16_t right);
+typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right);
 
 /* Renders multiple audio frames in one go.
  *
@@ -1949,26 +2429,26 @@ typedef void (*retro_audio_sample_t)(int16_t left, int16_t right);
  * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames.
  * Only one of the audio callbacks must ever be used.
  */
-typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data,
+typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data,
       size_t frames);
 
 /* Polls input. */
-typedef void (*retro_input_poll_t)(void);
+typedef void (RETRO_CALLCONV *retro_input_poll_t)(void);
 
-/* Queries for input for player 'port'. device will be masked with 
+/* Queries for input for player 'port'. device will be masked with
  * RETRO_DEVICE_MASK.
  *
- * 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_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);
@@ -1985,27 +2465,33 @@ 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 
- * core can change its behavior depending on device type. */
+ * 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.
+ *
+ * As part of the core's implementation of retro_set_controller_port_device,
+ * the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the
+ * frontend if the descriptions for any controls have changed as a
+ * result of changing the device type.
+ */
 RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device);
 
 /* Resets the current game. */
@@ -2013,18 +2499,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);
@@ -2037,7 +2523,9 @@ RETRO_API bool retro_unserialize(const void *data, size_t size);
 RETRO_API void retro_cheat_reset(void);
 RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
 
-/* Loads a game. */
+/* Loads a game.
+ * Return true to indicate successful loading and false to indicate load failure.
+ */
 RETRO_API bool retro_load_game(const struct retro_game_info *game);
 
 /* Loads a "special" kind of game. Should not be used,
@@ -2047,7 +2535,7 @@ RETRO_API bool retro_load_game_special(
   const struct retro_game_info *info, size_t num_info
 );
 
-/* Unloads a currently loaded game. */
+/* Unloads the currently loaded game. Called before retro_deinit(void). */
 RETRO_API void retro_unload_game(void);
 
 /* Gets region of game. */