diff --git a/.github/workflows/rolling-release.yml b/.github/workflows/rolling-release.yml index 83f8e453a..493bca090 100644 --- a/.github/workflows/rolling-release.yml +++ b/.github/workflows/rolling-release.yml @@ -62,7 +62,6 @@ jobs: del /Q bin\x64\*.iobj del /Q bin\x64\*.ipdb del /Q bin\x64\common-tests* - del /Q bin\x64\duckstation-libretro-* rename bin\x64\updater-x64-ReleaseLTCG.exe updater.exe - name: Create x64 release archive @@ -76,6 +75,35 @@ jobs: name: "windows" path: "duckstation-windows-x64-release.zip" + + windows-arm64-build: + runs-on: windows-2019 + steps: + - uses: actions/checkout@v2.3.1 + with: + fetch-depth: 0 + submodules: true + + - name: Tag as preview build + if: github.ref == 'refs/heads/master' + shell: cmd + run: | + echo #pragma once > src/scmversion/tag.h + echo #define SCM_RELEASE_ASSET "duckstation-windows-x64-release.zip" >> src/scmversion/tag.h + echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h + echo #define SCM_RELEASE_TAG "preview" >> src/scmversion/tag.h + + + - name: Tag as dev build + if: github.ref == 'refs/heads/dev' + shell: cmd + run: | + echo #pragma once > src/scmversion/tag.h + echo #define SCM_RELEASE_ASSET "duckstation-windows-x64-release.zip" >> src/scmversion/tag.h + echo #define SCM_RELEASE_TAGS {"latest", "preview"} >> src/scmversion/tag.h + echo #define SCM_RELEASE_TAG "latest" >> src/scmversion/tag.h + + - name: Compile arm64 release build shell: cmd run: | @@ -91,7 +119,6 @@ jobs: del /Q bin\ARM64\*.iobj del /Q bin\ARM64\*.ipdb del /Q bin\ARM64\common-tests* - del /Q bin\ARM64\duckstation-libretro-* rename bin\ARM64\updater-ARM64-ReleaseLTCG.exe updater.exe - name: Create arm64 release archive @@ -102,39 +129,10 @@ jobs: - name: Upload arm64 release artifact uses: actions/upload-artifact@v1 with: - name: "windows" + name: "windows-arm64" path: "duckstation-windows-arm64-release.zip" - windows-libretro-build: - runs-on: windows-2019 - steps: - - uses: actions/checkout@v2.3.1 - with: - fetch-depth: 0 - - - name: Compile release build - shell: cmd - run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - mkdir build - cd build - cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON -DCMAKE_C_COMPILER:FILEPATH="%VCToolsInstallDir%\bin\HostX64\x64\cl.exe" -DCMAKE_CXX_COMPILER:FILEPATH="%VCToolsInstallDir%\bin\HostX64\x64\cl.exe" .. - ninja - - - name: Create libretro core archive - shell: cmd - run: | - cd build - "C:\Program Files\7-Zip\7z.exe" a -r duckstation_libretro.dll.zip ./duckstation_libretro.dll - - - name: Upload release artifact - uses: actions/upload-artifact@v1 - with: - name: "windows-libretro-x64" - path: "build/duckstation_libretro.dll.zip" - - linux-build: runs-on: ubuntu-18.04 steps: @@ -182,95 +180,6 @@ jobs: path: "build/duckstation-qt-x64.AppImage.zsync" - linux-libretro-build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2.3.1 - with: - fetch-depth: 0 - - - name: Install packages - shell: bash - run: | - sudo apt-get update - sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf - - - name: Compile and zip Linux x64 libretro core - shell: bash - run: | - mkdir build-libretro-linux-x64 - cd build-libretro-linux-x64 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON .. - cmake --build . --parallel 2 - zip -j duckstation_libretro_x64.so.zip duckstation_libretro.so - - - name: Upload Linux x64 libretro core - uses: actions/upload-artifact@v1 - with: - name: "linux-libretro" - path: "build-libretro-linux-x64/duckstation_libretro_x64.so.zip" - - - name: Compile and zip Linux armv7 libretro core - shell: bash - run: | - mkdir build-libretro-linux-armv7 - cd build-libretro-linux-armv7 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeModules/armv7-cross-toolchain.cmake .. - cmake --build . --parallel 2 - zip -j duckstation_libretro_linux_armv7.so.zip duckstation_libretro.so - - - name: Upload Linux AArch64 libretro core - uses: actions/upload-artifact@v1 - with: - name: "linux-libretro" - path: "build-libretro-linux-armv7/duckstation_libretro_linux_armv7.so.zip" - - - name: Compile and zip Linux AArch64 libretro core - shell: bash - run: | - mkdir build-libretro-linux-aarch64 - cd build-libretro-linux-aarch64 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeModules/aarch64-cross-toolchain.cmake .. - cmake --build . --parallel 2 - zip -j duckstation_libretro_linux_aarch64.so.zip duckstation_libretro.so - - - name: Upload Linux AArch64 libretro core - uses: actions/upload-artifact@v1 - with: - name: "linux-libretro" - path: "build-libretro-linux-aarch64/duckstation_libretro_linux_aarch64.so.zip" - - - name: Compile and zip Android armv7 libretro core - shell: bash - run: | - mkdir build-libretro-android-armv7 - cd build-libretro-android-armv7 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON -DANDROID_ABI=armeabi-v7a -DANDROID_ARM_NEON=ON -DCMAKE_TOOLCHAIN_FILE=${ANDROID_SDK_ROOT}/ndk-bundle/build/cmake/android.toolchain.cmake .. - cmake --build . --parallel 2 - zip -j duckstation_libretro_android_armv7.so.zip duckstation_libretro_android.so - - - name: Upload Android armv7 libretro core - uses: actions/upload-artifact@v1 - with: - name: "linux-libretro" - path: "build-libretro-android-armv7/duckstation_libretro_android_armv7.so.zip" - - - name: Compile and zip Android AArch64 libretro core - shell: bash - run: | - mkdir build-libretro-android-aarch64 - cd build-libretro-android-aarch64 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON -DANDROID_ABI=arm64-v8a -DCMAKE_TOOLCHAIN_FILE=${ANDROID_SDK_ROOT}/ndk-bundle/build/cmake/android.toolchain.cmake .. - cmake --build . --parallel 2 - zip -j duckstation_libretro_android_aarch64.so.zip duckstation_libretro_android.so - - - name: Upload Android AArch64 libretro core - uses: actions/upload-artifact@v1 - with: - name: "linux-libretro" - path: "build-libretro-android-aarch64/duckstation_libretro_android_aarch64.so.zip" - - android-build: runs-on: ubuntu-20.04 steps: @@ -342,25 +251,9 @@ jobs: name: "macos-x64" path: "build/bin/duckstation-mac-release.zip" - - name: Compile libretro core and zip - shell: bash - run: | - mkdir build-libretro - cd build-libretro - export MACOSX_DEPLOYMENT_TARGET=10.14 - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON .. - cmake --build . --parallel 2 - zip -j duckstation_libretro_mac.dylib.zip duckstation_libretro.dylib - - - name: Upload macOS libretro core - uses: actions/upload-artifact@v1 - with: - name: "macos-x64" - path: "build-libretro/duckstation_libretro_mac.dylib.zip" - create-release: - needs: [windows-build, windows-libretro-build, linux-build, linux-libretro-build, android-build, macos-build] + needs: [windows-build, windows-arm64-build, linux-build, android-build, macos-build] runs-on: "ubuntu-latest" if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev' steps: @@ -369,10 +262,10 @@ jobs: with: name: "windows" - - name: Download Windows libretro x64 Artifact + - name: Download Windows ARM64 Artifact uses: actions/download-artifact@v1 with: - name: "windows-libretro-x64" + name: "windows-arm64" - name: Download SDL AppImage Artifact uses: actions/download-artifact@v1 @@ -394,11 +287,6 @@ jobs: with: name: "linux-x64-appimage-qt-zsync" - - name: Download Linux libretro core - uses: actions/download-artifact@v1 - with: - name: "linux-libretro" - - name: Download Android APK uses: actions/download-artifact@v1 with: @@ -419,20 +307,12 @@ jobs: title: "Latest Preview Build" files: | windows/duckstation-windows-x64-release.zip - windows/duckstation-windows-arm64-release.zip - windows-libretro-x64/duckstation_libretro.dll.zip + windows-arm64/duckstation-windows-arm64-release.zip linux-x64-appimage-sdl/duckstation-sdl-x64.AppImage linux-x64-appimage-sdl-zsync/duckstation-sdl-x64.AppImage.zsync linux-x64-appimage-qt/duckstation-qt-x64.AppImage linux-x64-appimage-qt-zsync/duckstation-qt-x64.AppImage.zsync - linux-libretro/duckstation_libretro_x64.so.zip - linux-libretro/duckstation_libretro_linux_armv7.so.zip - linux-libretro/duckstation_libretro_linux_aarch64.so.zip - linux-libretro/duckstation_libretro_android_armv7.so.zip - linux-libretro/duckstation_libretro_android_aarch64.so.zip android/duckstation-android.apk - macos-x64/duckstation-mac-release.zip - macos-x64/duckstation_libretro_mac.dylib.zip - name: Create dev release if: github.ref == 'refs/heads/dev' @@ -444,18 +324,11 @@ jobs: title: "Latest Development Build" files: | windows/duckstation-windows-x64-release.zip - windows/duckstation-windows-arm64-release.zip - windows-libretro-x64/duckstation_libretro.dll.zip + windows-arm64/duckstation-windows-arm64-release.zip linux-x64-appimage-sdl/duckstation-sdl-x64.AppImage linux-x64-appimage-sdl-zsync/duckstation-sdl-x64.AppImage.zsync linux-x64-appimage-qt/duckstation-qt-x64.AppImage linux-x64-appimage-qt-zsync/duckstation-qt-x64.AppImage.zsync - linux-libretro/duckstation_libretro_x64.so.zip - linux-libretro/duckstation_libretro_linux_armv7.so.zip - linux-libretro/duckstation_libretro_linux_aarch64.so.zip - linux-libretro/duckstation_libretro_android_armv7.so.zip - linux-libretro/duckstation_libretro_android_aarch64.so.zip android/duckstation-android.apk macos-x64/duckstation-mac-release.zip - macos-x64/duckstation_libretro_mac.dylib.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index e38dce565..542f0bd8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,6 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14.0" CACHE STRING "") if(NOT ANDROID) option(BUILD_SDL_FRONTEND "Build the SDL frontend" ON) option(BUILD_QT_FRONTEND "Build the Qt frontend" ON) - option(BUILD_LIBRETRO_CORE "Build a libretro core" OFF) option(ENABLE_DISCORD_PRESENCE "Build with Discord Rich Presence support" ON) option(USE_SDL2 "Link with SDL2 for controller support" ON) endif() @@ -42,8 +41,7 @@ if(USE_WAYLAND) set(USE_EGL ON) endif() -# When we're building for libretro, everything else is invalid because of PIC. -if(ANDROID OR BUILD_LIBRETRO_CORE) +if(ANDROID) if(BUILD_SDL_FRONTEND) message(WARNING "Building for Android or libretro core, disabling SDL frontend") set(BUILD_SDL_FRONTEND OFF) @@ -66,14 +64,9 @@ if(ANDROID OR BUILD_LIBRETRO_CORE) if(USE_WAYLAND) set(USE_WAYLAND OFF) endif() - if(BUILD_LIBRETRO_CORE AND USE_EGL) + if(USE_EGL) set(USE_EGL OFF) endif() - - # Force PIC when compiling a libretro core. - if(BUILD_LIBRETRO_CORE) - set(CMAKE_POSITION_INDEPENDENT_CODE ON) - endif() endif() @@ -211,7 +204,7 @@ endif() # Write binaries to a seperate directory. -if(WIN32 AND NOT BUILD_LIBRETRO_CORE) +if(WIN32) # For Windows, use the source directory, except for libretro. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/${CPU_ARCH}") else() @@ -232,6 +225,6 @@ enable_testing() add_subdirectory(dep) add_subdirectory(src) -if(ANDROID AND NOT BUILD_LIBRETRO_CORE) +if(ANDROID) add_subdirectory(android/app/src/cpp) endif() diff --git a/README.md b/README.md index a66f55b68..39fdb06c6 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # DuckStation - PlayStation 1, aka. PSX Emulator -[Latest News](#latest-news) | [Features](#features) | [Screenshots](#screenshots) | [Downloading and Running](#downloading-and-running) | [Libretro Core](#libretro-core) | [Building](#building) | [Disclaimers](#disclaimers) +[Latest News](#latest-news) | [Features](#features) | [Screenshots](#screenshots) | [Downloading and Running](#downloading-and-running) | [Building](#building) | [Disclaimers](#disclaimers) **Discord Server:** https://discord.gg/Buktv3t -**Latest Windows, Linux (AppImage), Mac, Android, and Libretro Builds:** https://github.com/stenzek/duckstation/releases/tag/latest +**Latest Windows, Linux (AppImage), Mac, Android** https://github.com/stenzek/duckstation/releases/tag/latest **Available on Google Play:** https://play.google.com/store/apps/details?id=com.github.stenzek.duckstation&hl=en_AU&gl=US @@ -32,7 +32,6 @@ Older entries are available at https://github.com/stenzek/duckstation/blob/maste - 2020/12/10: Translation support added for Android version. Currently Brazillian Portuguese, Italian, and Dutch are available. - 2020/11/27: Cover support added for game list in Android version. Procedure is the same as the desktop version, except you should place cover images in `/duckstation/covers` (see [Adding Game Covers](https://github.com/stenzek/duckstation/wiki/Adding-Game-Covers)). - 2020/11/27: Disc database is shipped with desktop and Android versions courtesy of redump.org. This will provide titles for games on Android, where it was not possible previously. -- 2020/11/27: Compatibility databases added to libretro core - broken enhancements will be automatically disabled. You can turn this off by disabling "Apply Compatibility Settings" in the core options. - 2020/11/27: SDL game controller database is included with desktop versions courtesy of https://github.com/gabomdq/SDL_GameControllerDB. - 2020/11/21: OpenGL ES 2.0 host display support added. You cannot use the hardware renderer with GLES2, it still requires GLES3, but GLES2 GPUs can now use the software renderer. - 2020/11/21: Threaded renderer for software renderer added. Can result in a significant speed boost depending on the game. @@ -270,22 +269,6 @@ Hotkeys: - **Page Up/Down:** Increase/decrease resolution scale in hardware renderers - **End:** Toggle software renderer -## Libretro Core - -DuckStation is available as a libretro core, supporting most of the features of the full frontend within the constraints and limitations of being a libretro core. - -As of December 2020, the libretro core is no longer supported by the developer. The core will remain in the tree, but fixing any issues will not be a priority, -and any bugs must be tested in the standalone version prior to being reported. - -To build on Windows, use cmake using the following commands from a `x64 Native Tools Command Prompt for VS 2019`: -- mkdir build -- cd build -- cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON .. - -You should then have a file named `duckstation_libretro.dll` which can be loaded as a core. - -To build on Linux, follow the same instructions as for a normal build, but for cmake use `cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBRETRO_CORE=ON ..`. The shared library will be named `duckstation_libretro.so` in the current directory. - ## Tests - Passes amidog's CPU and GTE tests in both interpreter and recompiler modes, partial passing of CPX tests diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt index 4f1b1be53..a23cc18a0 100644 --- a/dep/CMakeLists.txt +++ b/dep/CMakeLists.txt @@ -10,14 +10,11 @@ add_subdirectory(xxhash) add_subdirectory(rapidjson) add_subdirectory(glslang) add_subdirectory(vulkan-loader) - -if(NOT BUILD_LIBRETRO_CORE) - add_subdirectory(googletest) - add_subdirectory(cubeb) - add_subdirectory(imgui) - add_subdirectory(simpleini) - add_subdirectory(tinyxml2) -endif() +add_subdirectory(googletest) +add_subdirectory(cubeb) +add_subdirectory(imgui) +add_subdirectory(simpleini) +add_subdirectory(tinyxml2) if(ENABLE_DISCORD_PRESENCE) add_subdirectory(discord-rpc) @@ -27,10 +24,6 @@ if(BUILD_SDL_FRONTEND) add_subdirectory(nativefiledialog) endif() -if(BUILD_LIBRETRO_CORE) - add_subdirectory(libretro-common) -endif() - if(${CPU_ARCH} STREQUAL "aarch32" OR ${CPU_ARCH} STREQUAL "aarch64") add_subdirectory(vixl) endif() diff --git a/dep/libretro-common/CMakeLists.txt b/dep/libretro-common/CMakeLists.txt deleted file mode 100644 index 213ae9bfd..000000000 --- a/dep/libretro-common/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_library(libretro-common INTERFACE) -target_include_directories(libretro-common INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/") diff --git a/dep/libretro-common/include/libretro.h b/dep/libretro-common/include/libretro.h deleted file mode 100644 index bfe42be38..000000000 --- a/dep/libretro-common/include/libretro.h +++ /dev/null @@ -1,2880 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro API header (libretro.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef LIBRETRO_H__ -#define LIBRETRO_H__ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __cplusplus -#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 -#define true 1 -#define false 0 -#else -#include -#endif -#endif - -#ifndef RETRO_CALLCONV -# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__) -# define RETRO_CALLCONV __attribute__((cdecl)) -# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64) -# define RETRO_CALLCONV __cdecl -# else -# define RETRO_CALLCONV /* all other platforms only have one calling convention each */ -# endif -#endif - -#ifndef RETRO_API -# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) -# ifdef RETRO_IMPORT_SYMBOLS -# ifdef __GNUC__ -# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__)) -# else -# define RETRO_API RETRO_CALLCONV __declspec(dllimport) -# endif -# else -# ifdef __GNUC__ -# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__)) -# else -# define RETRO_API RETRO_CALLCONV __declspec(dllexport) -# endif -# endif -# else -# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__) -# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default"))) -# else -# define RETRO_API RETRO_CALLCONV -# endif -# endif -#endif - -/* Used for checking API/ABI mismatches that can break libretro - * implementations. - * It is not incremented for compatible changes to the API. - */ -#define RETRO_API_VERSION 1 - -/* - * 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 - * and a pointer. - * - * 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 - * correctly to arbitrary controller layouts. - */ - -#define RETRO_DEVICE_TYPE_SHIFT 8 -#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) -#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) - -/* Input disabled. */ -#define RETRO_DEVICE_NONE 0 - -/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo - * controller, 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 - * pointer is supposed to be on the screen. - * 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 - * pressed state. - * For event/text based keyboard input, see - * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. - */ -#define RETRO_DEVICE_KEYBOARD 3 - -/* 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 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 - * screen a mouse (or something similar) is being placed. - * For a touch centric device, coordinates reported are the coordinates - * of the press. - * - * 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 - * 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 - * game image, etc. - * - * 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 - * left mouse button, but this is a frontend decision. - * PRESSED will only return 1 if the pointer is inside the game screen. - * - * For multi-touch, the index variable can be used to successively query - * more presses. - * 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 - * index = 1, and so on. - * 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 - * Super Nintendo controller. - * 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 -#define RETRO_DEVICE_ID_JOYPAD_START 3 -#define RETRO_DEVICE_ID_JOYPAD_UP 4 -#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 -#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 -#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 -#define RETRO_DEVICE_ID_JOYPAD_A 8 -#define RETRO_DEVICE_ID_JOYPAD_X 9 -#define RETRO_DEVICE_ID_JOYPAD_L 10 -#define RETRO_DEVICE_ID_JOYPAD_R 11 -#define RETRO_DEVICE_ID_JOYPAD_L2 12 -#define RETRO_DEVICE_ID_JOYPAD_R2 13 -#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 - -/* Id values for MOUSE. */ -#define RETRO_DEVICE_ID_MOUSE_X 0 -#define RETRO_DEVICE_ID_MOUSE_Y 1 -#define RETRO_DEVICE_ID_MOUSE_LEFT 2 -#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 -#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 -#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 -#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 -#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7 -#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8 -#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 -#define RETRO_REGION_PAL 1 - -/* 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_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 -}; - -/* Passed to retro_get_memory_data/size(). - * If the memory type doesn't apply to the - * implementation NULL/0 can be returned. - */ -#define RETRO_MEMORY_MASK 0xff - -/* Regular save RAM. This RAM is usually found on a game cartridge, - * backed up by a battery. - * If save game data is too complex for a single memory buffer, - * the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment - * callback can be used. */ -#define RETRO_MEMORY_SAVE_RAM 0 - -/* Some games have a built-in clock to keep track of time. - * This memory is usually just a couple of bytes to keep track of time. - */ -#define RETRO_MEMORY_RTC 1 - -/* System ram lets a frontend peek into a game systems main RAM. */ -#define RETRO_MEMORY_SYSTEM_RAM 2 - -/* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ -#define RETRO_MEMORY_VIDEO_RAM 3 - -/* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ -enum retro_key -{ - RETROK_UNKNOWN = 0, - RETROK_FIRST = 0, - RETROK_BACKSPACE = 8, - RETROK_TAB = 9, - RETROK_CLEAR = 12, - RETROK_RETURN = 13, - RETROK_PAUSE = 19, - RETROK_ESCAPE = 27, - RETROK_SPACE = 32, - RETROK_EXCLAIM = 33, - RETROK_QUOTEDBL = 34, - RETROK_HASH = 35, - RETROK_DOLLAR = 36, - RETROK_AMPERSAND = 38, - RETROK_QUOTE = 39, - RETROK_LEFTPAREN = 40, - RETROK_RIGHTPAREN = 41, - RETROK_ASTERISK = 42, - RETROK_PLUS = 43, - RETROK_COMMA = 44, - RETROK_MINUS = 45, - RETROK_PERIOD = 46, - RETROK_SLASH = 47, - RETROK_0 = 48, - RETROK_1 = 49, - RETROK_2 = 50, - RETROK_3 = 51, - RETROK_4 = 52, - RETROK_5 = 53, - RETROK_6 = 54, - RETROK_7 = 55, - RETROK_8 = 56, - RETROK_9 = 57, - RETROK_COLON = 58, - RETROK_SEMICOLON = 59, - RETROK_LESS = 60, - RETROK_EQUALS = 61, - RETROK_GREATER = 62, - RETROK_QUESTION = 63, - RETROK_AT = 64, - RETROK_LEFTBRACKET = 91, - RETROK_BACKSLASH = 92, - RETROK_RIGHTBRACKET = 93, - RETROK_CARET = 94, - RETROK_UNDERSCORE = 95, - RETROK_BACKQUOTE = 96, - RETROK_a = 97, - RETROK_b = 98, - RETROK_c = 99, - RETROK_d = 100, - RETROK_e = 101, - RETROK_f = 102, - RETROK_g = 103, - RETROK_h = 104, - RETROK_i = 105, - RETROK_j = 106, - RETROK_k = 107, - RETROK_l = 108, - RETROK_m = 109, - RETROK_n = 110, - RETROK_o = 111, - RETROK_p = 112, - RETROK_q = 113, - RETROK_r = 114, - RETROK_s = 115, - RETROK_t = 116, - RETROK_u = 117, - RETROK_v = 118, - RETROK_w = 119, - 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, - RETROK_KP1 = 257, - RETROK_KP2 = 258, - RETROK_KP3 = 259, - RETROK_KP4 = 260, - RETROK_KP5 = 261, - RETROK_KP6 = 262, - RETROK_KP7 = 263, - RETROK_KP8 = 264, - RETROK_KP9 = 265, - RETROK_KP_PERIOD = 266, - RETROK_KP_DIVIDE = 267, - RETROK_KP_MULTIPLY = 268, - RETROK_KP_MINUS = 269, - RETROK_KP_PLUS = 270, - RETROK_KP_ENTER = 271, - RETROK_KP_EQUALS = 272, - - RETROK_UP = 273, - RETROK_DOWN = 274, - RETROK_RIGHT = 275, - RETROK_LEFT = 276, - RETROK_INSERT = 277, - RETROK_HOME = 278, - RETROK_END = 279, - RETROK_PAGEUP = 280, - RETROK_PAGEDOWN = 281, - - RETROK_F1 = 282, - RETROK_F2 = 283, - RETROK_F3 = 284, - RETROK_F4 = 285, - RETROK_F5 = 286, - RETROK_F6 = 287, - RETROK_F7 = 288, - RETROK_F8 = 289, - RETROK_F9 = 290, - RETROK_F10 = 291, - RETROK_F11 = 292, - RETROK_F12 = 293, - RETROK_F13 = 294, - RETROK_F14 = 295, - RETROK_F15 = 296, - - RETROK_NUMLOCK = 300, - RETROK_CAPSLOCK = 301, - RETROK_SCROLLOCK = 302, - RETROK_RSHIFT = 303, - RETROK_LSHIFT = 304, - RETROK_RCTRL = 305, - RETROK_LCTRL = 306, - RETROK_RALT = 307, - RETROK_LALT = 308, - RETROK_RMETA = 309, - RETROK_LMETA = 310, - RETROK_LSUPER = 311, - RETROK_RSUPER = 312, - RETROK_MODE = 313, - RETROK_COMPOSE = 314, - - RETROK_HELP = 315, - RETROK_PRINT = 316, - RETROK_SYSREQ = 317, - RETROK_BREAK = 318, - RETROK_MENU = 319, - RETROK_POWER = 320, - RETROK_EURO = 321, - RETROK_UNDO = 322, - RETROK_OEM_102 = 323, - - RETROK_LAST, - - RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ -}; - -enum retro_mod -{ - RETROKMOD_NONE = 0x0000, - - RETROKMOD_SHIFT = 0x01, - RETROKMOD_CTRL = 0x02, - RETROKMOD_ALT = 0x04, - RETROKMOD_META = 0x08, - - RETROKMOD_NUMLOCK = 0x10, - RETROKMOD_CAPSLOCK = 0x20, - RETROKMOD_SCROLLOCK = 0x40, - - RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ -}; - -/* 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. */ -#define RETRO_ENVIRONMENT_PRIVATE 0x20000 - -/* Environment commands. */ -#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- - * Sets screen rotation of graphics. - * 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 * -- - * 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 * -- - * Boolean value whether or not frontend supports frame duping, - * passing NULL to video frame callback. - */ - - /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), - * and reserved to avoid possible ABI clash. - */ - -#define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- - * Sets a message to be displayed in implementation-specific manner - * for a certain amount of 'frames'. - * Should not be used for trivial messages, which should simply be - * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a - * fallback, stderr). - */ -#define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- - * Requests the frontend to shutdown. - * Should only be used if game has a specific - * way to shutdown the game from a menu item or similar. - */ -#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 - /* const unsigned * -- - * Gives a hint to the frontend how demanding this implementation - * is on a system. E.g. reporting a level of 2 means - * this implementation should run decently on all frontends - * of level 2 and up. - * - * It can be used by the frontend to potentially warn - * about too demanding implementations. - * - * The levels are "floating". - * - * This function can be called on a per-game basis, - * as certain games an implementation can play might be - * particularly demanding. - * If called, it should be called in retro_load_game(). - */ -#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 - * 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 - * memory cards, etc, for lack of a better place to put it. - * This is now discouraged, and if possible, cores should try to - * use the new GET_SAVE_DIRECTORY. - */ -#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 - /* const enum retro_pixel_format * -- - * Sets the internal pixel format used by the implementation. - * 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 - * format. - * - * 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 - * being set to NULL. - * 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 - /* const struct retro_keyboard_callback * -- - * Sets a callback function used to notify core about keyboard events. - */ -#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 - * disk images. - * 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 - * hardware acceleration. - * Should be called in retro_load_game(). - * 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 - * max_width/max_height provided in get_av_info(). - * 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 - * 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 - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * 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 - * '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 - * of expected values. - * - * 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. - * - * 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 - * values split up with '|'. - * - * 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 - /* bool * -- - * Result is set to true if some variables are updated by - * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. - * Variables should be queried with GET_VARIABLE. - */ -#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 - /* const bool * -- - * 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 - * implementation was loaded. - * 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 - * be loaded without ugly hacks. - */ - - /* 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 - * being available for writing. - * 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 - * asynchronous and audio can be generated on the fly. - * This interface is not recommended for use with emulators which have - * highly synchronous audio. - * - * 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 - * 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 - * implement the "normal" audio interface. - * - * A libretro core using SET_AUDIO_CALLBACK should also make use of - * SET_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 - * state of rumble motors in controllers. - * 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 - * handled properly in a call to retro_input_state_t. - * 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(). - */ -#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* 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, - * enabling/disable it entirely, etc. - * 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 - * video camera. - * 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 - * will be delivered as a raw framebuffer, - * or as an OpenGL texture directly. - * - * 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 - * libretro GL core (SET_HW_RENDER). - * It is recommended to use a libretro GL core when - * using camera interface. - * - * 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 - * logging in a cross-platform way - * 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 - * 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 - * architecture-specific features, such as SIMD support. - */ -#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 - /* struct retro_location_callback * -- - * Gets access to the location interface. - * The purpose of this interface is to be able to retrieve - * location-based information from the host device, - * such as current latitude / longitude. - */ -#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ -#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 - /* const char ** -- - * Returns the "core assets" directory of the frontend. - * This directory can be used to store specific assets that the - * core relies upon, such as art assets, - * input data, etc etc. - * The returned value can be NULL. - * If so, no such directory is defined, - * and it's up to the implementation to find a suitable directory. - */ -#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 - /* const char ** -- - * Returns the "save" directory of the frontend, unless there is no - * save directory available. The save directory should be used to - * store SRAM, memory cards, high scores, etc, if the libretro core - * cannot use the regular memory interface (retro_get_memory_data()). - * - * If the frontend cannot designate a save directory, it will return - * NULL to indicate that the core should attempt to operate without a - * save directory set. - * - * NOTE: early libretro cores used the system directory for save - * files. Cores that need to be backwards-compatible can still check - * GET_SYSTEM_DIRECTORY. - */ -#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 - /* const struct retro_system_av_info * -- - * Sets a new av_info structure. This can only be called from - * within retro_run(). - * This should *only* be used if the core is completely altering the - * internal resolutions, aspect ratios, timings, sampling rate, etc. - * Calling this can require a full reinitialization of video/audio - * drivers in the frontend, - * - * so it is important to call it very sparingly, and usually only with - * the users explicit consent. - * An eventual driver reinitialize will happen so that video and - * audio callbacks - * happening after this call within the same retro_run() call will - * target the newly initialized driver. - * - * This callback makes it possible to support configurable resolutions - * in games, which can be useful to - * avoid setting the "worst case" in max_width/max_height. - * - * ***HIGHLY RECOMMENDED*** Do not call this callback every time - * resolution changes in an emulator core if it's - * expected to be a temporary change, for the reasons of possible - * driver reinitialization. - * This call is not a free pass for not trying to provide - * correct values in retro_get_system_av_info(). If you need to change - * things like aspect ratio or nominal width/height, - * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant - * of SET_SYSTEM_AV_INFO. - * - * If this returns false, the frontend does not acknowledge a - * changed av_info struct. - */ -#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 - /* const struct retro_get_proc_address_interface * -- - * Allows a libretro core to announce support for the - * get_proc_address() interface. - * This interface allows for a standard way to extend libretro where - * use of environment calls are too indirect, - * e.g. for cases where the frontend wants to call directly into the core. - * - * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK - * **MUST** be called from within retro_set_environment(). - */ -#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 - /* const struct retro_subsystem_info * -- - * This environment call introduces the concept of libretro "subsystems". - * A subsystem is a variant of a libretro core which supports - * different kinds of games. - * The purpose of this is to support e.g. emulators which might - * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. - * It can also be used to pick among subsystems in an explicit way - * if the libretro implementation is a multi-system emulator itself. - * - * Loading a game via a subsystem is done with retro_load_game_special(), - * and this environment call allows a libretro core to expose which - * subsystems are supported for use with retro_load_game_special(). - * A core passes an array of retro_game_special_info which is terminated - * with a zeroed out retro_game_special_info struct. - * - * If a core wants to use this functionality, SET_SUBSYSTEM_INFO - * **MUST** be called from within retro_set_environment(). - */ -#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 - /* const struct retro_controller_info * -- - * This environment call lets a libretro core tell the frontend - * which controller subclasses are recognized in calls to - * retro_set_controller_port_device(). - * - * Some emulators such as Super Nintendo support multiple lightgun - * types which must be specifically selected from. It is therefore - * sometimes necessary for a frontend to be able to tell the core - * about a special kind of input device which is not specifcally - * provided by the Libretro API. - * - * In order for a frontend to understand the workings of those devices, - * they must be defined as a specialized subclass of the generic device - * types already defined in the libretro API. - * - * The core must pass an array of const struct retro_controller_info which - * is terminated with a blanked out struct. Each element of the - * retro_controller_info struct corresponds to the ascending port index - * that is passed to retro_set_controller_port_device() when that function - * is called to indicate to the core that the frontend has changed the - * active device subclass. SEE ALSO: retro_set_controller_port_device() - * - * The ascending input port indexes provided by the core in the struct - * are generally presented by frontends as ascending User # or Player #, - * such as Player 1, Player 2, Player 3, etc. Which device subclasses are - * supported can vary per input port. - * - * The first inner element of each entry in the retro_controller_info array - * is a retro_controller_description struct that specifies the names and - * codes of all device subclasses that are available for the corresponding - * User or Player, beginning with the generic Libretro device that the - * subclasses are derived from. The second inner element of each entry is the - * total number of subclasses that are listed in the retro_controller_description. - * - * NOTE: Even if special device types are set in the libretro core, - * libretro should only poll input based on the base input device types. - */ -#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_memory_map * -- - * This environment call lets a libretro core tell the frontend - * about the memory maps this core emulates. - * This can be used to implement, for example, cheats in a core-agnostic way. - * - * Should only be used by emulators; it doesn't make much sense for - * anything else. - * It is recommended to expose all relevant pointers through - * retro_get_memory_* as well. - * - * Can be called from retro_init and retro_load_game. - */ -#define RETRO_ENVIRONMENT_SET_GEOMETRY 37 - /* const struct retro_game_geometry * -- - * This environment call is similar to SET_SYSTEM_AV_INFO for changing - * video parameters, but provides a guarantee that drivers will not be - * reinitialized. - * This can only be called from within retro_run(). - * - * The purpose of this call is to allow a core to alter nominal - * width/heights as well as aspect ratios on-the-fly, which can be - * useful for some emulators to change in run-time. - * - * max_width/max_height arguments are ignored and cannot be changed - * with this call as this could potentially require a reinitialization or a - * non-constant time operation. - * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. - * - * A frontend must guarantee that this environment call completes in - * constant time. - */ -#define RETRO_ENVIRONMENT_GET_USERNAME 38 - /* const char ** - * Returns the specified username of the frontend, if specified by the user. - * This username can be used as a nickname for a core that has online facilities - * or any other mode where personalization of the user is desirable. - * The returned value can be NULL. - * If this environ callback is used by a core that requires a valid username, - * a default username should be specified by the core. - */ -#define RETRO_ENVIRONMENT_GET_LANGUAGE 39 - /* unsigned * -- - * Returns the specified language of the frontend, if specified by the user. - * It can be used by the core for localization purposes. - */ -#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_framebuffer * -- - * Returns a preallocated framebuffer which the core can use for rendering - * the frame into when not using SET_HW_RENDER. - * The framebuffer returned from this call must not be used - * after the current call to retro_run() returns. - * - * The goal of this call is to allow zero-copy behavior where a core - * can render directly into video memory, avoiding extra bandwidth cost by copying - * memory from core to video memory. - * - * If this call succeeds and the core renders into it, - * the framebuffer pointer and pitch can be passed to retro_video_refresh_t. - * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used, - * the core must pass the exact - * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER; - * i.e. passing a pointer which is offset from the - * buffer is undefined. The width, height and pitch parameters - * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER. - * - * It is possible for a frontend to return a different pixel format - * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend - * needs to perform conversion. - * - * It is still valid for a core to render to a different buffer - * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds. - * - * A frontend must make sure that the pointer obtained from this function is - * writeable (and readable). - */ -#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_interface ** -- - * Returns an API specific rendering interface for accessing API specific data. - * Not all HW rendering APIs support or need this. - * The contents of the returned pointer is specific to the rendering API - * being used. See the various headers like libretro_vulkan.h, etc. - * - * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called. - * Similarly, after context_destroyed callback returns, - * the contents of the HW_RENDER_INTERFACE are invalidated. - */ -#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const bool * -- - * If true, the libretro implementation supports achievements - * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS - * or via retro_get_memory_data/retro_get_memory_size. - * - * This must be called before the first call to retro_run. - */ -#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_context_negotiation_interface * -- - * Sets an interface which lets the libretro core negotiate with frontend how a context is created. - * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier. - * This interface will be used when the frontend is trying to create a HW rendering context, - * so it will be used after SET_HW_RENDER, but before the context_reset callback. - */ -#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44 - /* uint64_t * -- - * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't - * recognize or support. Should be set in either retro_init or retro_load_game, but not both. - */ -#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* N/A (null) * -- - * The frontend will try to use a 'shared' hardware context (mostly applicable - * to OpenGL) when a hardware context is being set up. - * - * Returns true if the frontend supports shared hardware contexts and false - * if the frontend does not support shared hardware contexts. - * - * This will do nothing on its own until SET_HW_RENDER env callbacks are - * being used. - */ -#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_vfs_interface_info * -- - * Gets access to the VFS interface. - * VFS presence needs to be queried prior to load_game or any - * get_system/save/other_directory being called to let front end know - * core supports VFS before it starts handing out paths. - * It is recomended to do so in retro_set_environment - */ -#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_led_interface * -- - * Gets an interface which is used by a libretro core to set - * state of LEDs. - */ -#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* int * -- - * Tells the core if the frontend wants audio or video. - * If disabled, the frontend will discard the audio or video, - * so the core may decide to skip generating a frame or generating audio. - * This is mainly used for increasing performance. - * Bit 0 (value 1): Enable Video - * Bit 1 (value 2): Enable Audio - * Bit 2 (value 4): Use Fast Savestates. - * Bit 3 (value 8): Hard Disable Audio - * Other bits are reserved for future use and will default to zero. - * If video is disabled: - * * The frontend wants the core to not generate any video, - * including presenting frames via hardware acceleration. - * * The frontend's video frame callback will do nothing. - * * After running the frame, the video output of the next frame should be - * no different than if video was enabled, and saving and loading state - * should have no issues. - * If audio is disabled: - * * The frontend wants the core to not generate any audio. - * * The frontend's audio callbacks will do nothing. - * * After running the frame, the audio output of the next frame should be - * no different than if audio was enabled, and saving and loading state - * should have no issues. - * Fast Savestates: - * * Guaranteed to be created by the same binary that will load them. - * * Will not be written to or read from the disk. - * * Suggest that the core assumes loading state will succeed. - * * Suggest that the core updates its memory buffers in-place if possible. - * * Suggest that the core skips clearing memory. - * * Suggest that the core skips resetting the system. - * * Suggest that the core may skip validation steps. - * Hard Disable Audio: - * * Used for a secondary core when running ahead. - * * Indicates that the frontend will never need audio from the core. - * * Suggests that the core may stop synthesizing audio, but this should not - * compromise emulation accuracy. - * * Audio output for the next frame does not matter, and the frontend will - * never need an accurate audio state in the future. - * * State will never be saved when using Hard Disable Audio. - */ -#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_midi_interface ** -- - * Returns a MIDI interface that can be used for raw data I/O. - */ - -#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* bool * -- - * Boolean value that indicates whether or not the frontend is in - * fastforwarding mode. - */ - -#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* float * -- - * Float value that lets us know what target refresh rate - * is curently in use by the frontend. - * - * The core can use the returned value to set an ideal - * refresh rate/framerate. - */ - -#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* bool * -- - * Boolean value that indicates whether or not the frontend supports - * input bitmasks being returned by retro_input_state_t. The advantage - * of this is that retro_input_state_t has to be only called once to - * grab all button states instead of multiple times. - * - * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id' - * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD). - * It will return a bitmask of all the digital buttons. - */ - -#define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52 - /* unsigned * -- - * Unsigned value is the API version number of the core options - * interface supported by the frontend. If callback return false, - * API version is assumed to be 0. - * - * In legacy code, core options are set by passing an array of - * retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES. - * This may be still be done regardless of the core options - * interface version. - * - * If version is >= 1 however, core options may instead be set by - * passing an array of retro_core_option_definition structs to - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of - * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. - * This allows the core to additionally set option sublabel information - * and/or provide localisation support. - */ - -#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53 - /* const struct retro_core_option_definition ** -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION - * returns an API version of >= 1. - * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterwards 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_core_option_definition structs - * terminated by a { NULL, NULL, NULL, {{0}}, NULL } element. - * retro_core_option_definition::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_core_option_definition::desc should contain a human readable - * description of the key. - * retro_core_option_definition::info should contain any additional human - * readable information text that a typical user may need to - * understand the functionality of the option. - * retro_core_option_definition::values is an array of retro_core_option_value - * structs terminated by a { NULL, NULL } element. - * > retro_core_option_definition::values[index].value is an expected option - * value. - * > retro_core_option_definition::values[index].label is a human readable - * label used when displaying the value on screen. If NULL, - * the value itself is used. - * retro_core_option_definition::default_value is the default core option - * setting. It must match one of the expected option values in the - * retro_core_option_definition::values array. If it does not, or the - * default value is NULL, the first entry in the - * retro_core_option_definition::values array is treated as the default. - * - * The number of possible options should be very limited, - * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. - * i.e. it should be feasible to cycle through options - * without a keyboard. - * - * Example entry: - * { - * "foo_option", - * "Speed hack coprocessor X", - * "Provides increased performance at the expense of reduced accuracy", - * { - * { "false", NULL }, - * { "true", NULL }, - * { "unstable", "Turbo (Unstable)" }, - * { NULL, NULL }, - * }, - * "false" - * } - * - * Only strings are operated on. The possible values will - * generally be displayed and stored as-is by the frontend. - */ - -#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54 - /* const struct retro_core_options_intl * -- - * Allows an implementation to signal the environment - * which variables it might want to check for later using - * GET_VARIABLE. - * This allows the frontend to present these variables to - * a user dynamically. - * This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION - * returns an API version of >= 1. - * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. - * This should be called the first time as early as - * possible (ideally in retro_set_environment). - * Afterwards 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. - * - * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS, - * with the addition of localisation support. The description of the - * RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted - * for further details. - * - * 'data' points to a retro_core_options_intl struct. - * - * retro_core_options_intl::us is a pointer to an array of - * retro_core_option_definition structs defining the US English - * core options implementation. It must point to a valid array. - * - * retro_core_options_intl::local is a pointer to an array of - * retro_core_option_definition structs defining core options for - * the current frontend language. It may be NULL (in which case - * retro_core_options_intl::us is used by the frontend). Any items - * missing from this array will be read from retro_core_options_intl::us - * instead. - * - * NOTE: Default core option values are always taken from the - * retro_core_options_intl::us array. Any default values in - * retro_core_options_intl::local array will be ignored. - */ - -#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55 - /* struct retro_core_option_display * -- - * - * Allows an implementation to signal the environment to show - * or hide a variable when displaying core options. This is - * considered a *suggestion*. The frontend is free to ignore - * this callback, and its implementation not considered mandatory. - * - * 'data' points to a retro_core_option_display struct - * - * retro_core_option_display::key is a variable identifier - * which has already been set by SET_VARIABLES/SET_CORE_OPTIONS. - * - * retro_core_option_display::visible is a boolean, specifying - * whether variable should be displayed - * - * Note that all core option variables will be set visible by - * default when calling SET_VARIABLES/SET_CORE_OPTIONS. - */ - -#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56 - /* unsigned * -- - * - * Allows an implementation to ask frontend preferred hardware - * context to use. Core should use this information to deal - * with what specific context to request with SET_HW_RENDER. - * - * 'data' points to an unsigned variable - */ - -#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57 - /* unsigned * -- - * Unsigned value is the API version number of the disk control - * interface supported by the frontend. If callback return false, - * API version is assumed to be 0. - * - * In legacy code, the disk control interface is defined by passing - * a struct of type retro_disk_control_callback to - * RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. - * This may be still be done regardless of the disk control - * interface version. - * - * If version is >= 1 however, the disk control interface may - * instead be defined by passing a struct of type - * retro_disk_control_ext_callback to - * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE. - * This allows the core to provide additional information about - * disk images to the frontend and/or enables extra - * disk control functionality by the frontend. - */ - -#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58 - /* const struct retro_disk_control_ext_callback * -- - * Sets an interface which frontend can use to eject and insert - * disk images, and also obtain information about individual - * disk image files registered by the core. - * This is used for games which consist of multiple images and - * must be manually swapped out by the user (e.g. PSX, floppy disk - * based systems). - */ - -/* VFS functionality */ - -/* File paths: - * File paths passed as parameters when using this API shall be well formed UNIX-style, - * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator. - * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead). - * Other than the directory separator, cores shall not make assumptions about path format: - * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths. - * Cores may replace the basename or remove path components from the end, and/or add new components; - * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end. - * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much. - * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable). - * Cores are allowed to try using them, but must remain functional if the front rejects such requests. - * Cores are encouraged to use the libretro-common filestream functions for file I/O, - * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate - * and provide platform-specific fallbacks in cases where front ends do not support VFS. */ - -/* Opaque file handle - * Introduced in VFS API v1 */ -struct retro_vfs_file_handle; - -/* Opaque directory handle - * Introduced in VFS API v3 */ -struct retro_vfs_dir_handle; - -/* File open flags - * Introduced in VFS API v1 */ -#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */ -#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */ -#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/ -#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */ - -/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use, - and how they react to unlikely external interference (for example someone else writing to that file, - or the file's server going down), behavior will not change. */ -#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0) -/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */ -#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0) - -/* Seek positions */ -#define RETRO_VFS_SEEK_POSITION_START 0 -#define RETRO_VFS_SEEK_POSITION_CURRENT 1 -#define RETRO_VFS_SEEK_POSITION_END 2 - -/* stat() result flags - * Introduced in VFS API v3 */ -#define RETRO_VFS_STAT_IS_VALID (1 << 0) -#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1) -#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2) - -/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle - * Introduced in VFS API v1 */ -typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream); - -/* Open a file for reading or writing. If path points to a directory, this will - * fail. Returns the opaque file handle, or NULL for error. - * Introduced in VFS API v1 */ -typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints); - -/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure. - * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. - * Introduced in VFS API v1 */ -typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream); - -/* Return the size of the file in bytes, or -1 for error. - * Introduced in VFS API v1 */ -typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream); - -/* Truncate file to specified size. Returns 0 on success or -1 on error - * Introduced in VFS API v2 */ -typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length); - -/* Get the current read / write position for the file. Returns -1 for error. - * Introduced in VFS API v1 */ -typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream); - -/* Set the current read/write position for the file. Returns the new position, -1 for error. - * Introduced in VFS API v1 */ -typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position); - -/* Read data from a file. Returns the number of bytes read, or -1 for error. - * Introduced in VFS API v1 */ -typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len); - -/* Write data to a file. Returns the number of bytes written, or -1 for error. - * Introduced in VFS API v1 */ -typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len); - -/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure. - * Introduced in VFS API v1 */ -typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream); - -/* Delete the specified file. Returns 0 on success, -1 on failure - * Introduced in VFS API v1 */ -typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path); - -/* Rename the specified file. Returns 0 on success, -1 on failure - * Introduced in VFS API v1 */ -typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path); - -/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid. - * Additionally stores file size in given variable, unless NULL is given. - * Introduced in VFS API v3 */ -typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size); - -/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists. - * Introduced in VFS API v3 */ -typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir); - -/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error. - * Support for the include_hidden argument may vary depending on the platform. - * Introduced in VFS API v3 */ -typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden); - -/* Read the directory entry at the current position, and move the read pointer to the next position. - * Returns true on success, false if already on the last entry. - * Introduced in VFS API v3 */ -typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream); - -/* Get the name of the last entry read. Returns a string on success, or NULL for error. - * The returned string pointer is valid until the next call to readdir or closedir. - * Introduced in VFS API v3 */ -typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream); - -/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error). - * Introduced in VFS API v3 */ -typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream); - -/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure. - * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used. - * Introduced in VFS API v3 */ -typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream); - -struct retro_vfs_interface -{ - /* VFS API v1 */ - retro_vfs_get_path_t get_path; - retro_vfs_open_t open; - retro_vfs_close_t close; - retro_vfs_size_t size; - retro_vfs_tell_t tell; - retro_vfs_seek_t seek; - retro_vfs_read_t read; - retro_vfs_write_t write; - retro_vfs_flush_t flush; - retro_vfs_remove_t remove; - retro_vfs_rename_t rename; - /* VFS API v2 */ - retro_vfs_truncate_t truncate; - /* VFS API v3 */ - retro_vfs_stat_t stat; - retro_vfs_mkdir_t mkdir; - retro_vfs_opendir_t opendir; - retro_vfs_readdir_t readdir; - retro_vfs_dirent_get_name_t dirent_get_name; - retro_vfs_dirent_is_dir_t dirent_is_dir; - retro_vfs_closedir_t closedir; -}; - -struct retro_vfs_interface_info -{ - /* Set by core: should this be higher than the version the front end supports, - * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call - * Introduced in VFS API v1 */ - uint32_t required_interface_version; - - /* Frontend writes interface pointer here. The frontend also sets the actual - * version, must be at least required_interface_version. - * Introduced in VFS API v1 */ - struct retro_vfs_interface *iface; -}; - -enum retro_hw_render_interface_type -{ - RETRO_HW_RENDER_INTERFACE_VULKAN = 0, - RETRO_HW_RENDER_INTERFACE_D3D9 = 1, - RETRO_HW_RENDER_INTERFACE_D3D10 = 2, - RETRO_HW_RENDER_INTERFACE_D3D11 = 3, - RETRO_HW_RENDER_INTERFACE_D3D12 = 4, - RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5, - RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX -}; - -/* Base struct. All retro_hw_render_interface_* types - * contain at least these fields. */ -struct retro_hw_render_interface -{ - enum retro_hw_render_interface_type interface_type; - unsigned interface_version; -}; - -typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state); -struct retro_led_interface -{ - retro_set_led_state_t set_led_state; -}; - -/* Retrieves the current state of the MIDI input. - * Returns true if it's enabled, false otherwise. */ -typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void); - -/* Retrieves the current state of the MIDI output. - * Returns true if it's enabled, false otherwise */ -typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void); - -/* Reads next byte from the input stream. - * Returns true if byte is read, false otherwise. */ -typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte); - -/* Writes byte to the output stream. - * 'delta_time' is in microseconds and represent time elapsed since previous write. - * Returns true if byte is written, false otherwise. */ -typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time); - -/* Flushes previously written data. - * Returns true if successful, false otherwise. */ -typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void); - -struct retro_midi_interface -{ - retro_midi_input_enabled_t input_enabled; - retro_midi_output_enabled_t output_enabled; - retro_midi_read_t read; - retro_midi_write_t write; - retro_midi_flush_t flush; -}; - -enum retro_hw_render_context_negotiation_interface_type -{ - RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0, - RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX -}; - -/* Base struct. All retro_hw_render_context_negotiation_interface_* types - * contain at least these fields. */ -struct retro_hw_render_context_negotiation_interface -{ - enum retro_hw_render_context_negotiation_interface_type interface_type; - unsigned interface_version; -}; - -/* Serialized state is incomplete in some way. Set if serialization is - * usable in typical end-user cases but should not be relied upon to - * implement frame-sensitive frontend features such as netplay or - * rerecording. */ -#define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0) -/* The core must spend some time initializing before serialization is - * supported. retro_serialize() will initially fail; retro_unserialize() - * and retro_serialize_size() may or may not work correctly either. */ -#define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1) -/* Serialization size may change within a session. */ -#define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2) -/* Set by the frontend to acknowledge that it supports variable-sized - * states. */ -#define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3) -/* Serialized state can only be loaded during the same session. */ -#define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4) -/* Serialized state cannot be loaded on an architecture with a different - * endianness from the one it was saved on. */ -#define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5) -/* Serialized state cannot be loaded on a different platform from the one it - * was saved on for reasons other than endianness, such as word size - * dependence */ -#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6) - -#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ -#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ -#define RETRO_MEMDESC_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */ -#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */ -#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */ -#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ -#define RETRO_MEMDESC_ALIGN_4 (2 << 16) -#define RETRO_MEMDESC_ALIGN_8 (3 << 16) -#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ -#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) -#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) -struct retro_memory_descriptor -{ - uint64_t flags; - - /* Pointer to the start of the relevant ROM or RAM chip. - * It's strongly recommended to use 'offset' if possible, rather than - * doing math on the pointer. - * - * If the same byte is mapped my multiple descriptors, their descriptors - * must have the same pointer. - * If 'start' does not point to the first byte in the pointer, put the - * difference in 'offset' instead. - * - * May be NULL if there's nothing usable here (e.g. hardware registers and - * open bus). No flags should be set if the pointer is NULL. - * It's recommended to minimize the number of descriptors if possible, - * but not mandatory. */ - void *ptr; - size_t offset; - - /* This is the location in the emulated address space - * where the mapping starts. */ - size_t start; - - /* Which bits must be same as in 'start' for this mapping to apply. - * The first memory descriptor to claim a certain byte is the one - * that applies. - * A bit which is set in 'start' must also be set in this. - * Can be zero, in which case each byte is assumed mapped exactly once. - * In this case, 'len' must be a power of two. */ - size_t select; - - /* If this is nonzero, the set bits are assumed not connected to the - * memory chip's address pins. */ - size_t disconnect; - - /* This one tells the size of the current memory area. - * If, after start+disconnect are applied, the address is higher than - * this, the highest bit of the address is cleared. - * - * If the address is still too high, the next highest bit is cleared. - * Can be zero, in which case it's assumed to be infinite (as limited - * by 'select' and 'disconnect'). */ - size_t len; - - /* To go from emulated address to physical address, the following - * order applies: - * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ - - /* The address space name must consist of only a-zA-Z0-9_-, - * should be as short as feasible (maximum length is 8 plus the NUL), - * and may not be any other address space plus one or more 0-9A-F - * at the end. - * However, multiple memory descriptors for the same address space is - * allowed, and the address space name can be empty. NULL is treated - * as empty. - * - * Address space names are case sensitive, but avoid lowercase if possible. - * The same pointer may exist in multiple address spaces. - * - * Examples: - * blank+blank - valid (multiple things may be mapped in the same namespace) - * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) - * 'A'+'B' - valid (neither is a prefix of each other) - * 'S'+blank - valid ('S' is not in 0-9A-F) - * 'a'+blank - valid ('a' is not in 0-9A-F) - * 'a'+'A' - valid (neither is a prefix of each other) - * 'AR'+blank - valid ('R' is not in 0-9A-F) - * 'ARB'+blank - valid (the B can't be part of the address either, because - * there is no namespace 'AR') - * blank+'B' - not valid, because it's ambigous which address space B1234 - * would refer to. - * The length can't be used for that purpose; the frontend may want - * to append arbitrary data to an address, without a separator. */ - const char *addrspace; - - /* TODO: When finalizing this one, add a description field, which should be - * "WRAM" or something roughly equally long. */ - - /* TODO: When finalizing this one, replace 'select' with 'limit', which tells - * which bits can vary and still refer to the same address (limit = ~select). - * TODO: limit? range? vary? something else? */ - - /* TODO: When finalizing this one, if 'len' is above what 'select' (or - * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len' - * and 'select' != 0, and the mappings don't tell how the system switches the - * banks. */ - - /* TODO: When finalizing this one, fix the 'len' bit removal order. - * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00. - * Algorithm: Take bits highest to lowest, but if it goes above len, clear - * the most recent addition and continue on the next bit. - * TODO: Can the above be optimized? Is "remove the lowest bit set in both - * pointer and 'len'" equivalent? */ - - /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing - * the emulated memory in 32-bit chunks, native endian. But that's nothing - * compared to Darek Mihocka - * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE - * RAM backwards! I'll want to represent both of those, via some flags. - * - * I suspect MAME either didn't think of that idea, or don't want the #ifdef. - * Not sure which, nor do I really care. */ - - /* TODO: Some of those flags are unused and/or don't really make sense. Clean - * them up. */ -}; - -/* The frontend may use the largest value of 'start'+'select' in a - * certain namespace to infer the size of the address space. - * - * If the address space is larger than that, a mapping with .ptr=NULL - * should be at the end of the array, with .select set to all ones for - * as long as the address space is big. - * - * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): - * SNES WRAM: - * .start=0x7E0000, .len=0x20000 - * (Note that this must be mapped before the ROM in most cases; some of the - * ROM mappers - * try to claim $7E0000, or at least $7E8000.) - * SNES SPC700 RAM: - * .addrspace="S", .len=0x10000 - * SNES WRAM mirrors: - * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 - * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 - * SNES WRAM mirrors, alternate equivalent descriptor: - * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF - * (Various similar constructions can be created by combining parts of - * the above two.) - * SNES LoROM (512KB, mirrored a couple of times): - * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 - * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 - * SNES HiROM (4MB): - * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 - * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 - * SNES ExHiROM (8MB): - * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 - * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 - * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 - * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 - * Clarify the size of the address space: - * .ptr=NULL, .select=0xFFFFFF - * .len can be implied by .select in many of them, but was included for clarity. - */ - -struct retro_memory_map -{ - const struct retro_memory_descriptor *descriptors; - unsigned num_descriptors; -}; - -struct retro_controller_description -{ - /* Human-readable description of the controller. Even if using a generic - * input device type, this can be set to the particular device type the - * core uses. */ - const char *desc; - - /* Device type passed to retro_set_controller_port_device(). If the device - * type is a sub-class of a generic input device type, use the - * RETRO_DEVICE_SUBCLASS macro to create an ID. - * - * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ - unsigned id; -}; - -struct retro_controller_info -{ - const struct retro_controller_description *types; - unsigned num_types; -}; - -struct retro_subsystem_memory_info -{ - /* The extension associated with a memory type, e.g. "psram". */ - const char *extension; - - /* The memory type for retro_get_memory(). This should be at - * least 0x100 to avoid conflict with standardized - * libretro memory types. */ - unsigned type; -}; - -struct retro_subsystem_rom_info -{ - /* Describes what the content is (SGB BIOS, GB ROM, etc). */ - const char *desc; - - /* Same definition as retro_get_system_info(). */ - const char *valid_extensions; - - /* Same definition as retro_get_system_info(). */ - bool need_fullpath; - - /* Same definition as retro_get_system_info(). */ - bool block_extract; - - /* This is set if the content is required to load a game. - * If this is set to false, a zeroed-out retro_game_info can be passed. */ - bool required; - - /* Content can have multiple associated persistent - * memory types (retro_get_memory()). */ - const struct retro_subsystem_memory_info *memory; - unsigned num_memory; -}; - -struct retro_subsystem_info -{ - /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ - const char *desc; - - /* A computer friendly short string identifier for the subsystem type. - * This name must be [a-z]. - * E.g. if desc is "Super GameBoy", this can be "sgb". - * This identifier can be used for command-line interfaces, etc. - */ - const char *ident; - - /* Infos for each content file. The first entry is assumed to be the - * "most significant" content for frontend purposes. - * E.g. with Super GameBoy, the first content should be the GameBoy ROM, - * as it is the most "significant" content to a user. - * If a frontend creates new file paths based on the content used - * (e.g. savestates), it should use the path for the first ROM to do so. */ - const struct retro_subsystem_rom_info *roms; - - /* Number of content files associated with a subsystem. */ - unsigned num_roms; - - /* The type passed to retro_load_game_special(). */ - unsigned id; -}; - -typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); - -/* libretro API extension functions: - * (None here so far). - * - * Get a symbol from a libretro core. - * Cores should only return symbols which are actual - * extensions to the libretro API. - * - * Frontends should not use this to obtain symbols to standard - * libretro entry points (static linking or dlsym). - * - * The symbol name must be equal to the function name, - * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". - * The returned function pointer must be cast to the corresponding type. - */ -typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym); - -struct retro_get_proc_address_interface -{ - retro_get_proc_address_t get_proc_address; -}; - -enum retro_log_level -{ - RETRO_LOG_DEBUG = 0, - RETRO_LOG_INFO, - RETRO_LOG_WARN, - RETRO_LOG_ERROR, - - RETRO_LOG_DUMMY = INT_MAX -}; - -/* Logging function. Takes log level argument as well. */ -typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level, - const char *fmt, ...); - -struct retro_log_callback -{ - retro_log_printf_t log; -}; - -/* Performance related functions */ - -/* ID values for SIMD CPU features */ -#define RETRO_SIMD_SSE (1 << 0) -#define RETRO_SIMD_SSE2 (1 << 1) -#define RETRO_SIMD_VMX (1 << 2) -#define RETRO_SIMD_VMX128 (1 << 3) -#define RETRO_SIMD_AVX (1 << 4) -#define RETRO_SIMD_NEON (1 << 5) -#define RETRO_SIMD_SSE3 (1 << 6) -#define RETRO_SIMD_SSSE3 (1 << 7) -#define RETRO_SIMD_MMX (1 << 8) -#define RETRO_SIMD_MMXEXT (1 << 9) -#define RETRO_SIMD_SSE4 (1 << 10) -#define RETRO_SIMD_SSE42 (1 << 11) -#define RETRO_SIMD_AVX2 (1 << 12) -#define RETRO_SIMD_VFPU (1 << 13) -#define RETRO_SIMD_PS (1 << 14) -#define RETRO_SIMD_AES (1 << 15) -#define RETRO_SIMD_VFPV3 (1 << 16) -#define RETRO_SIMD_VFPV4 (1 << 17) -#define RETRO_SIMD_POPCNT (1 << 18) -#define RETRO_SIMD_MOVBE (1 << 19) -#define RETRO_SIMD_CMOV (1 << 20) -#define RETRO_SIMD_ASIMD (1 << 21) - -typedef uint64_t retro_perf_tick_t; -typedef int64_t retro_time_t; - -struct retro_perf_counter -{ - const char *ident; - retro_perf_tick_t start; - retro_perf_tick_t total; - retro_perf_tick_t call_cnt; - - bool registered; -}; - -/* Returns current time in microseconds. - * Tries to use the most accurate timer available. - */ -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 - * performance counter system). - * */ -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_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_CALLCONV *retro_perf_log_t)(void); - -/* Register a performance counter. - * 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 - * frontend redundantly, you can check registered field first. */ -typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter); - -/* Starts a registered counter. */ -typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter); - -/* Stops a registered 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.: - * #ifdef LOG_PERFORMANCE - * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) - * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) - * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) - * #else - * ... Blank macros ... - * #endif - * - * These can then be used mid-functions around code snippets. - * - * extern struct retro_perf_callback perf_cb; * Somewhere in the core. - * - * void do_some_heavy_work(void) - * { - * RETRO_PERFORMANCE_INIT(cb, work_1; - * RETRO_PERFORMANCE_START(cb, work_1); - * heavy_work_1(); - * RETRO_PERFORMANCE_STOP(cb, work_1); - * - * RETRO_PERFORMANCE_INIT(cb, work_2); - * RETRO_PERFORMANCE_START(cb, work_2); - * heavy_work_2(); - * RETRO_PERFORMANCE_STOP(cb, work_2); - * } - * - * void retro_deinit(void) - * { - * perf_cb.perf_log(); * Log all perf counters here for example. - * } - */ - -struct retro_perf_callback -{ - retro_perf_get_time_usec_t get_time_usec; - retro_get_cpu_features_t get_cpu_features; - - retro_perf_get_counter_t get_perf_counter; - retro_perf_register_t perf_register; - retro_perf_start_t perf_start; - retro_perf_stop_t perf_stop; - retro_perf_log_t perf_log; -}; - -/* FIXME: Document the sensor API and work out behavior. - * It will be marked as experimental until then. - */ -enum retro_sensor_action -{ - RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, - RETRO_SENSOR_ACCELEROMETER_DISABLE, - RETRO_SENSOR_GYROSCOPE_ENABLE, - RETRO_SENSOR_GYROSCOPE_DISABLE, - RETRO_SENSOR_ILLUMINANCE_ENABLE, - RETRO_SENSOR_ILLUMINANCE_DISABLE, - - RETRO_SENSOR_DUMMY = INT_MAX -}; - -/* Id values for SENSOR types. */ -#define RETRO_SENSOR_ACCELEROMETER_X 0 -#define RETRO_SENSOR_ACCELEROMETER_Y 1 -#define RETRO_SENSOR_ACCELEROMETER_Z 2 -#define RETRO_SENSOR_GYROSCOPE_X 3 -#define RETRO_SENSOR_GYROSCOPE_Y 4 -#define RETRO_SENSOR_GYROSCOPE_Z 5 -#define RETRO_SENSOR_ILLUMINANCE 6 - -typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, - enum retro_sensor_action action, unsigned rate); - -typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id); - -struct retro_sensor_interface -{ - retro_set_sensor_state_t set_sensor_state; - retro_sensor_get_input_t get_sensor_input; -}; - -enum retro_camera_buffer -{ - RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, - RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, - - RETRO_CAMERA_BUFFER_DUMMY = INT_MAX -}; - -/* Starts the camera driver. Can only be called in retro_run(). */ -typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void); - -/* Stops the camera driver. Can only be called in retro_run(). */ -typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void); - -/* Callback which signals when the camera driver is initialized - * and/or deinitialized. - * retro_camera_start_t can be called in initialized callback. - */ -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_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 - * 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 - * more depending on extensions. - * - * 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 - * 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 - * the API definition. - */ -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. - * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). - */ - uint64_t caps; - - /* Desired resolution for camera. Is only used as a hint. */ - unsigned width; - unsigned height; - - /* 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; - - /* 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 - * 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 - * location-based data. - * - * To ensure compatibility with all location-based implementations, - * values for both interval_ms and interval_distance should be provided. - * - * interval_ms is the interval expressed in milliseconds. - * interval_distance is the distance interval expressed in meters. - */ -typedef void (RETRO_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 - * retro_location_set_interval_t). */ -typedef bool (RETRO_CALLCONV *retro_location_start_t)(void); - -/* Stop location services. The device will stop listening for changes - * to the current location. */ -typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); - -/* Get the position of the current location. Will set parameters to - * 0 if no new location update has happened since the last time. */ -typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, - double *horiz_accuracy, double *vert_accuracy); - -/* Callback which signals when the location driver is initialized - * and/or deinitialized. - * retro_location_start_t can be called in initialized callback. - */ -typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); - -struct retro_location_callback -{ - retro_location_start_t start; - retro_location_stop_t stop; - retro_location_get_position_t get_position; - retro_location_set_interval_t set_interval; - - retro_location_lifetime_status_t initialized; - retro_location_lifetime_status_t deinitialized; -}; - -enum retro_rumble_effect -{ - RETRO_RUMBLE_STRONG = 0, - RETRO_RUMBLE_WEAK = 1, - - RETRO_RUMBLE_DUMMY = INT_MAX -}; - -/* 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. - * Calling this before first retro_run() is likely to return false. */ -typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port, - enum retro_rumble_effect effect, uint16_t strength); - -struct retro_rumble_interface -{ - retro_set_rumble_state_t set_rumble_state; -}; - -/* Notifies libretro that audio data should be written. */ -typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void); - -/* True: Audio driver in frontend is active, and callback is - * 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 - * called with true. - * Initial state is false (inactive). - */ -typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); - -struct retro_audio_callback -{ - retro_audio_callback_t callback; - retro_audio_set_state_callback_t set_state; -}; - -/* 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 - * 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_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 - * rounding to ensure that framestepping, etc is exact. */ - retro_usec_t reference; -}; - -/* Pass this to retro_video_refresh_t if rendering to hardware. - * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. - * */ -#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) - -/* Invalidates the current HW context. - * Any GL state is lost, and must not be deinitialized explicitly. - * If explicit deinitialization is desired by the libretro core, - * it should implement context_destroy callback. - * If called, all GPU resources must be reinitialized. - * Usually called when frontend reinits video driver. - * Also called first time video driver is initialized, - * allowing libretro core to initialize resources. - */ -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_CALLCONV *retro_hw_get_current_framebuffer_t)(void); - -/* Get a symbol from HW context. */ -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, - /* OpenGL ES 2.0. */ - RETRO_HW_CONTEXT_OPENGLES2 = 2, - /* Modern desktop core GL context. Use version_major/ - * version_minor fields to set GL version. */ - RETRO_HW_CONTEXT_OPENGL_CORE = 3, - /* OpenGL ES 3.0 */ - RETRO_HW_CONTEXT_OPENGLES3 = 4, - /* OpenGL ES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, - * use the corresponding enums directly. */ - RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, - - /* 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 -}; - -struct retro_hw_render_callback -{ - /* Which API to use. Set by libretro core. */ - enum retro_hw_context_type context_type; - - /* Called when a context has been created or when it has been reset. - * An OpenGL context is only valid after context_reset() has been called. - * - * When context_reset is called, OpenGL resources in the libretro - * implementation are guaranteed to be invalid. - * - * It is possible that context_reset is called multiple times during an - * application lifecycle. - * If context_reset is called without any notification (context_destroy), - * the OpenGL context was lost and resources should just be recreated - * without any attempt to "free" old resources. - */ - retro_hw_context_reset_t context_reset; - - /* Set by frontend. - * TODO: This is rather obsolete. The frontend should not - * be providing preallocated framebuffers. */ - retro_hw_get_current_framebuffer_t get_current_framebuffer; - - /* 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. - * TODO: Obsolete. */ - bool depth; - - /* Set if stencil buffers should be attached. - * TODO: Obsolete. */ - bool stencil; - - /* 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, - * 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 - * 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 - * such as if the context is lost beyond recovery. - * - * For optimal stability, set this to false, and allow context to be - * reset at any time. - */ - - /* 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 - * just be destroyed without any notification. - * - * Even when context_destroy is non-NULL, it is possible that - * context_reset is called without any destroy notification. - * This happens if context is lost by external factors (such as - * notified by GL_ARB_robustness). - * - * In this case, the context is assumed to be already dead, - * and the libretro implementation must not try to free any OpenGL - * resources in the subsequent context_reset. - */ - - /* Creates a debug context. */ - bool debug_context; -}; - -/* 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. - * character is the text character of the pressed key. (UTF-32). - * 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 - * 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 - * character, character should be 0. - */ -typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode, - uint32_t character, uint16_t key_modifiers); - -struct retro_keyboard_callback -{ - retro_keyboard_event_t callback; -}; - -/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE & - * RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE. - * 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 - * set_eject_state(true). - * 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_CALLCONV *retro_set_eject_state_t)(bool ejected); - -/* Gets current eject state. The initial state is 'not ejected'. */ -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_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 - * index >= get_num_images(). - */ -typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); - -/* Gets total number of images which are available to use. */ -typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); - -struct retro_game_info; - -/* Replaces the disk image associated with index. - * 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 - * 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() - * returned 4 before. - * Index 1 will be removed, and the new index is 3. - */ -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 - * with replace_image_index. */ -typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void); - -/* Sets initial image to insert in drive when calling - * core_load_game(). - * Since we cannot pass the initial index when loading - * content (this would require a major API change), this - * is set by the frontend *before* calling the core's - * retro_load_game()/retro_load_game_special() implementation. - * A core should therefore cache the index/path values and handle - * them inside retro_load_game()/retro_load_game_special(). - * - If 'index' is invalid (index >= get_num_images()), the - * core should ignore the set value and instead use 0 - * - 'path' is used purely for error checking - i.e. when - * content is loaded, the core should verify that the - * disk specified by 'index' has the specified file path. - * This is to guard against auto selecting the wrong image - * if (for example) the user should modify an existing M3U - * playlist. We have to let the core handle this because - * set_initial_image() must be called before loading content, - * i.e. the frontend cannot access image paths in advance - * and thus cannot perform the error check itself. - * If set path and content path do not match, the core should - * ignore the set 'index' value and instead use 0 - * Returns 'false' if index or 'path' are invalid, or core - * does not support this functionality - */ -typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path); - -/* Fetches the path of the specified disk image file. - * Returns 'false' if index is invalid (index >= get_num_images()) - * or path is otherwise unavailable. - */ -typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len); - -/* Fetches a core-provided 'label' for the specified disk - * image file. In the simplest case this may be a file name - * (without extension), but for cores with more complex - * content requirements information may be provided to - * facilitate user disk swapping - for example, a core - * running floppy-disk-based content may uniquely label - * save disks, data disks, level disks, etc. with names - * corresponding to in-game disk change prompts (so the - * frontend can provide better user guidance than a 'dumb' - * disk index value). - * Returns 'false' if index is invalid (index >= get_num_images()) - * or label is otherwise unavailable. - */ -typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len); - -struct retro_disk_control_callback -{ - retro_set_eject_state_t set_eject_state; - retro_get_eject_state_t get_eject_state; - - retro_get_image_index_t get_image_index; - retro_set_image_index_t set_image_index; - retro_get_num_images_t get_num_images; - - retro_replace_image_index_t replace_image_index; - retro_add_image_index_t add_image_index; -}; - -struct retro_disk_control_ext_callback -{ - retro_set_eject_state_t set_eject_state; - retro_get_eject_state_t get_eject_state; - - retro_get_image_index_t get_image_index; - retro_set_image_index_t set_image_index; - retro_get_num_images_t get_num_images; - - retro_replace_image_index_t replace_image_index; - retro_add_image_index_t add_image_index; - - /* NOTE: Frontend will only attempt to record/restore - * last used disk index if both set_initial_image() - * and get_image_path() are implemented */ - retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */ - - retro_get_image_path_t get_image_path; /* Optional - may be NULL */ - retro_get_image_label_t get_image_label; /* Optional - may be NULL */ -}; - -enum retro_pixel_format -{ - /* 0RGB1555, native endian. - * 0 bit must be set to 0. - * This pixel format is default for compatibility concerns only. - * If a 15/16-bit pixel format is desired, consider using RGB565. */ - RETRO_PIXEL_FORMAT_0RGB1555 = 0, - - /* XRGB8888, native endian. - * X bits are ignored. */ - RETRO_PIXEL_FORMAT_XRGB8888 = 1, - - /* 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 - * available on a wide range of low-power devices. - * - * It is also natively supported in APIs like OpenGL ES. */ - RETRO_PIXEL_FORMAT_RGB565 = 2, - - /* Ensure sizeof() == sizeof(int). */ - RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX -}; - -struct retro_message -{ - const char *msg; /* Message to be displayed. */ - unsigned frames; /* Duration in frames of message. */ -}; - -/* Describes how the libretro implementation maps a libretro input bind - * to its internal input system through a human readable string. - * This string can be used to better let a user configure input. */ -struct retro_input_descriptor -{ - /* Associates given parameters with a description. */ - unsigned port; - unsigned device; - unsigned index; - unsigned id; - - /* Human readable description for parameters. - * The pointer must remain valid until - * retro_unload_game() is called. */ - const char *description; -}; - -struct retro_system_info -{ - /* 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 - * 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 - * load, separated with pipe. - * I.e. "bin|rom|iso". - * Typically used for a GUI to filter - * out extensions. */ - - /* 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 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 - * - * 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 - * loading the real content. - * Necessary for certain libretro implementations that load games - * from zipped archives. */ - bool block_extract; -}; - -struct retro_game_geometry -{ - unsigned base_width; /* Nominal video width of game. */ - unsigned base_height; /* Nominal video height of game. */ - unsigned max_width; /* Maximum possible width of game. */ - unsigned max_height; /* Maximum possible height of game. */ - - float aspect_ratio; /* Nominal aspect ratio of game. If - * aspect_ratio is <= 0.0, an aspect ratio - * of base_width / base_height is assumed. - * A frontend could override this setting, - * if desired. */ -}; - -struct retro_system_timing -{ - double fps; /* FPS of video content. */ - double sample_rate; /* Sampling rate of audio. */ -}; - -struct retro_system_av_info -{ - struct retro_game_geometry geometry; - struct retro_system_timing timing; -}; - -struct retro_variable -{ - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - * If NULL, obtains the complete environment string if more - * complex parsing is necessary. - * 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; -}; - -struct retro_core_option_display -{ - /* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */ - const char *key; - - /* Specifies whether variable should be displayed - * when presenting core options to the user */ - bool visible; -}; - -/* Maximum number of values permitted for a core option - * > Note: We have to set a maximum value due the limitations - * of the C language - i.e. it is not possible to create an - * array of structs each containing a variable sized array, - * so the retro_core_option_definition values array must - * have a fixed size. The size limit of 128 is a balancing - * act - it needs to be large enough to support all 'sane' - * core options, but setting it too large may impact low memory - * platforms. In practise, if a core option has more than - * 128 values then the implementation is likely flawed. - * To quote the above API reference: - * "The number of possible options should be very limited - * i.e. it should be feasible to cycle through options - * without a keyboard." - */ -#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 - -struct retro_core_option_value -{ - /* Expected option value */ - const char *value; - - /* Human-readable value label. If NULL, value itself - * will be displayed by the frontend */ - const char *label; -}; - -struct retro_core_option_definition -{ - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */ - const char *key; - - /* Human-readable core option description (used as menu label) */ - const char *desc; - - /* Human-readable core option information (used as menu sublabel) */ - const char *info; - - /* Array of retro_core_option_value structs, terminated by NULL */ - struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; - - /* Default core option value. Must match one of the values - * in the retro_core_option_value array, otherwise will be - * ignored */ - const char *default_value; -}; - -struct retro_core_options_intl -{ - /* Pointer to an array of retro_core_option_definition structs - * - US English implementation - * - Must point to a valid array */ - struct retro_core_option_definition *us; - - /* Pointer to an array of retro_core_option_definition structs - * - Implementation for current frontend language - * - May be NULL */ - struct retro_core_option_definition *local; -}; - -struct retro_game_info -{ - const char *path; /* Path to game, UTF-8 encoded. - * 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 - * if need_fullpath was set. */ - size_t size; /* Size of memory buffer. */ - const char *meta; /* String of implementation specific meta-data. */ -}; - -#define RETRO_MEMORY_ACCESS_WRITE (1 << 0) - /* The core will write to the buffer provided by retro_framebuffer::data. */ -#define RETRO_MEMORY_ACCESS_READ (1 << 1) - /* The core will read from retro_framebuffer::data. */ -#define RETRO_MEMORY_TYPE_CACHED (1 << 0) - /* The memory in data is cached. - * If not cached, random writes and/or reading from the buffer is expected to be very slow. */ -struct retro_framebuffer -{ - void *data; /* The framebuffer which the core can render into. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. - The initial contents of data are unspecified. */ - unsigned width; /* The framebuffer width used by the core. Set by core. */ - unsigned height; /* The framebuffer height used by the core. Set by core. */ - size_t pitch; /* The number of bytes between the beginning of a scanline, - and beginning of the next scanline. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ - enum retro_pixel_format format; /* The pixel format the core must use to render into data. - This format could differ from the format used in - SET_PIXEL_FORMAT. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ - - unsigned access_flags; /* How the core will access the memory in the framebuffer. - RETRO_MEMORY_ACCESS_* flags. - Set by core. */ - unsigned memory_flags; /* Flags telling core how the memory has been mapped. - RETRO_MEMORY_TYPE_* flags. - Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ -}; - -/* Callbacks */ - -/* Environment callback. Gives implementations a way of performing - * uncommon tasks. Extensible. */ -typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); - -/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian - * 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 - * that is packed in memory, i.e. pitch == width * byte_per_pixel. - * Certain graphic APIs, such as OpenGL ES, do not like textures - * that are not packed in memory. - */ -typedef void (RETRO_CALLCONV *retro_video_refresh_t)(const void *data, unsigned width, - unsigned height, size_t pitch); - -/* Renders a single audio frame. Should only be used if implementation - * generates a single sample at a time. - * Format is signed 16-bit native endian. - */ -typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); - -/* Renders multiple audio frames in one go. - * - * One frame is defined as a sample of left and right channels, interleaved. - * 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_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data, - size_t frames); - -/* Polls input. */ -typedef void (RETRO_CALLCONV *retro_input_poll_t)(void); - -/* Queries for input for player 'port'. device will be masked with - * RETRO_DEVICE_MASK. - * - * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that - * have been set with retro_set_controller_port_device() - * will still use the higher level RETRO_DEVICE_JOYPAD to request input. - */ -typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device, - unsigned index, unsigned id); - -/* 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 - * 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); -RETRO_API void retro_set_audio_sample(retro_audio_sample_t); -RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t); -RETRO_API void retro_set_input_poll(retro_input_poll_t); -RETRO_API void retro_set_input_state(retro_input_state_t); - -/* Library global initialization/deinitialization. */ -RETRO_API void retro_init(void); -RETRO_API void retro_deinit(void); - -/* Must return RETRO_API_VERSION. Used to validate ABI compatibility - * when the API is revised. */ -RETRO_API unsigned retro_api_version(void); - -/* 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 - * variable if needed. - * 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 - * 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. - * - * 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. */ -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 - * 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 - * 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 - * value, to ensure that the frontend can allocate a save state buffer once. - */ -RETRO_API size_t retro_serialize_size(void); - -/* Serializes internal state. If failed, or size is lower than - * retro_serialize_size(), it should return false, true otherwise. */ -RETRO_API bool retro_serialize(void *data, size_t size); -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. - * 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, - * except in extreme cases. */ -RETRO_API bool retro_load_game_special( - unsigned game_type, - const struct retro_game_info *info, size_t num_info -); - -/* Unloads the currently loaded game. Called before retro_deinit(void). */ -RETRO_API void retro_unload_game(void); - -/* Gets region of game. */ -RETRO_API unsigned retro_get_region(void); - -/* Gets region of memory. */ -RETRO_API void *retro_get_memory_data(unsigned id); -RETRO_API size_t retro_get_memory_size(unsigned id); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/dep/libretro-common/include/libretro_d3d.h b/dep/libretro-common/include/libretro_d3d.h deleted file mode 100644 index 78f36a5a0..000000000 --- a/dep/libretro-common/include/libretro_d3d.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro API header (libretro_d3d.h) - * --------------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the - * "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef LIBRETRO_DIRECT3D_H__ -#define LIBRETRO_DIRECT3D_H__ - -#include "libretro.h" - -#ifdef HAVE_D3D11 - -#include -#include - -#define RETRO_HW_RENDER_INTERFACE_D3D11_VERSION 1 - -struct retro_hw_render_interface_d3d11 -{ - /* Must be set to RETRO_HW_RENDER_INTERFACE_D3D11. */ - enum retro_hw_render_interface_type interface_type; - /* Must be set to RETRO_HW_RENDER_INTERFACE_D3D11_VERSION. */ - unsigned interface_version; - - /* Opaque handle to the d3d11 backend in the frontend - * which must be passed along to all function pointers - * in this interface. - */ - void* handle; - ID3D11Device *device; - ID3D11DeviceContext *context; - D3D_FEATURE_LEVEL featureLevel; - pD3DCompile D3DCompile; -}; - -#endif - -#endif /* LIBRETRO_DIRECT3D_H__ */ diff --git a/dep/libretro-common/include/libretro_vulkan.h b/dep/libretro-common/include/libretro_vulkan.h deleted file mode 100644 index d766d68e3..000000000 --- a/dep/libretro-common/include/libretro_vulkan.h +++ /dev/null @@ -1,397 +0,0 @@ -/* Copyright (C) 2010-2020 The RetroArch team - * - * --------------------------------------------------------------------------------------------- - * The following license statement only applies to this libretro API header (libretro_vulkan.h) - * --------------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef LIBRETRO_VULKAN_H__ -#define LIBRETRO_VULKAN_H__ - -#include -#include - -#define RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION 5 -#define RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION 1 - -struct retro_vulkan_image -{ - VkImageView image_view; - VkImageLayout image_layout; - VkImageViewCreateInfo create_info; -}; - -typedef void (*retro_vulkan_set_image_t)(void *handle, - const struct retro_vulkan_image *image, - uint32_t num_semaphores, - const VkSemaphore *semaphores, - uint32_t src_queue_family); - -typedef uint32_t (*retro_vulkan_get_sync_index_t)(void *handle); -typedef uint32_t (*retro_vulkan_get_sync_index_mask_t)(void *handle); -typedef void (*retro_vulkan_set_command_buffers_t)(void *handle, - uint32_t num_cmd, - const VkCommandBuffer *cmd); -typedef void (*retro_vulkan_wait_sync_index_t)(void *handle); -typedef void (*retro_vulkan_lock_queue_t)(void *handle); -typedef void (*retro_vulkan_unlock_queue_t)(void *handle); -typedef void (*retro_vulkan_set_signal_semaphore_t)(void *handle, VkSemaphore semaphore); - -typedef const VkApplicationInfo *(*retro_vulkan_get_application_info_t)(void); - -struct retro_vulkan_context -{ - VkPhysicalDevice gpu; - VkDevice device; - VkQueue queue; - uint32_t queue_family_index; - VkQueue presentation_queue; - uint32_t presentation_queue_family_index; -}; - -typedef bool (*retro_vulkan_create_device_t)( - struct retro_vulkan_context *context, - VkInstance instance, - VkPhysicalDevice gpu, - VkSurfaceKHR surface, - PFN_vkGetInstanceProcAddr get_instance_proc_addr, - const char **required_device_extensions, - unsigned num_required_device_extensions, - const char **required_device_layers, - unsigned num_required_device_layers, - const VkPhysicalDeviceFeatures *required_features); - -typedef void (*retro_vulkan_destroy_device_t)(void); - -/* Note on thread safety: - * The Vulkan API is heavily designed around multi-threading, and - * the libretro interface for it should also be threading friendly. - * A core should be able to build command buffers and submit - * command buffers to the GPU from any thread. - */ - -struct retro_hw_render_context_negotiation_interface_vulkan -{ - /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN. */ - enum retro_hw_render_context_negotiation_interface_type interface_type; - /* Must be set to RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION. */ - unsigned interface_version; - - /* If non-NULL, returns a VkApplicationInfo struct that the frontend can use instead of - * its "default" application info. - */ - retro_vulkan_get_application_info_t get_application_info; - - /* If non-NULL, the libretro core will choose one or more physical devices, - * create one or more logical devices and create one or more queues. - * The core must prepare a designated PhysicalDevice, Device, Queue and queue family index - * which the frontend will use for its internal operation. - * - * If gpu is not VK_NULL_HANDLE, the physical device provided to the frontend must be this PhysicalDevice. - * The core is still free to use other physical devices. - * - * The frontend will request certain extensions and layers for a device which is created. - * The core must ensure that the queue and queue_family_index support GRAPHICS and COMPUTE. - * - * If surface is not VK_NULL_HANDLE, the core must consider presentation when creating the queues. - * If presentation to "surface" is supported on the queue, presentation_queue must be equal to queue. - * If not, a second queue must be provided in presentation_queue and presentation_queue_index. - * If surface is not VK_NULL_HANDLE, the instance from frontend will have been created with supported for - * VK_KHR_surface extension. - * - * The core is free to set its own queue priorities. - * Device provided to frontend is owned by the frontend, but any additional device resources must be freed by core - * in destroy_device callback. - * - * If this function returns true, a PhysicalDevice, Device and Queues are initialized. - * If false, none of the above have been initialized and the frontend will attempt - * to fallback to "default" device creation, as if this function was never called. - */ - retro_vulkan_create_device_t create_device; - - /* If non-NULL, this callback is called similar to context_destroy for HW_RENDER_INTERFACE. - * However, it will be called even if context_reset was not called. - * This can happen if the context never succeeds in being created. - * destroy_device will always be called before the VkInstance - * of the frontend is destroyed if create_device was called successfully so that the core has a chance of - * tearing down its own device resources. - * - * Only auxillary resources should be freed here, i.e. resources which are not part of retro_vulkan_context. - */ - retro_vulkan_destroy_device_t destroy_device; -}; - -struct retro_hw_render_interface_vulkan -{ - /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN. */ - enum retro_hw_render_interface_type interface_type; - /* Must be set to RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION. */ - unsigned interface_version; - - /* Opaque handle to the Vulkan backend in the frontend - * which must be passed along to all function pointers - * in this interface. - * - * The rationale for including a handle here (which libretro v1 - * doesn't currently do in general) is: - * - * - Vulkan cores should be able to be freely threaded without lots of fuzz. - * This would break frontends which currently rely on TLS - * to deal with multiple cores loaded at the same time. - * - Fixing this in general is TODO for an eventual libretro v2. - */ - void *handle; - - /* The Vulkan instance the context is using. */ - VkInstance instance; - /* The physical device used. */ - VkPhysicalDevice gpu; - /* The logical device used. */ - VkDevice device; - - /* Allows a core to fetch all its needed symbols without having to link - * against the loader itself. */ - PFN_vkGetDeviceProcAddr get_device_proc_addr; - PFN_vkGetInstanceProcAddr get_instance_proc_addr; - - /* The queue the core must use to submit data. - * This queue and index must remain constant throughout the lifetime - * of the context. - * - * This queue will be the queue that supports graphics and compute - * if the device supports compute. - */ - VkQueue queue; - unsigned queue_index; - - /* Before calling retro_video_refresh_t with RETRO_HW_FRAME_BUFFER_VALID, - * set which image to use for this frame. - * - * If num_semaphores is non-zero, the frontend will wait for the - * semaphores provided to be signaled before using the results further - * in the pipeline. - * - * Semaphores provided by a single call to set_image will only be - * waited for once (waiting for a semaphore resets it). - * E.g. set_image, video_refresh, and then another - * video_refresh without set_image, - * but same image will only wait for semaphores once. - * - * For this reason, ownership transfer will only occur if semaphores - * are waited on for a particular frame in the frontend. - * - * Using semaphores is optional for synchronization purposes, - * but if not using - * semaphores, an image memory barrier in vkCmdPipelineBarrier - * should be used in the graphics_queue. - * Example: - * - * vkCmdPipelineBarrier(cmd, - * srcStageMask = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - * dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - * image_memory_barrier = { - * srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - * dstAccessMask = VK_ACCESS_SHADER_READ_BIT, - * }); - * - * The use of pipeline barriers instead of semaphores is encouraged - * as it is simpler and more fine-grained. A layout transition - * must generally happen anyways which requires a - * pipeline barrier. - * - * The image passed to set_image must have imageUsage flags set to at least - * VK_IMAGE_USAGE_TRANSFER_SRC_BIT and VK_IMAGE_USAGE_SAMPLED_BIT. - * The core will naturally want to use flags such as - * VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT and/or - * VK_IMAGE_USAGE_TRANSFER_DST_BIT depending - * on how the final image is created. - * - * The image must also have been created with MUTABLE_FORMAT bit set if - * 8-bit formats are used, so that the frontend can reinterpret sRGB - * formats as it sees fit. - * - * Images passed to set_image should be created with TILING_OPTIMAL. - * The image layout should be transitioned to either - * VK_IMAGE_LAYOUT_GENERIC or VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL. - * The actual image layout used must be set in image_layout. - * - * The image must be a 2D texture which may or not be layered - * and/or mipmapped. - * - * The image must be suitable for linear sampling. - * While the image_view is typically the only field used, - * the frontend may want to reinterpret the texture as sRGB vs. - * non-sRGB for example so the VkImageViewCreateInfo used to - * create the image view must also be passed in. - * - * The data in the pointer to the image struct will not be copied - * as the pNext field in create_info cannot be reliably deep-copied. - * The image pointer passed to set_image must be valid until - * retro_video_refresh_t has returned. - * - * If frame duping is used when passing NULL to retro_video_refresh_t, - * the frontend is free to either use the latest image passed to - * set_image or reuse the older pointer passed to set_image the - * frame RETRO_HW_FRAME_BUFFER_VALID was last used. - * - * Essentially, the lifetime of the pointer passed to - * retro_video_refresh_t should be extended if frame duping is used - * so that the frontend can reuse the older pointer. - * - * The image itself however, must not be touched by the core until - * wait_sync_index has been completed later. The frontend may perform - * layout transitions on the image, so even read-only access is not defined. - * The exception to read-only rule is if GENERAL layout is used for the image. - * In this case, the frontend is not allowed to perform any layout transitions, - * so concurrent reads from core and frontend are allowed. - * - * If frame duping is used, or if set_command_buffers is used, - * the frontend will not wait for any semaphores. - * - * The src_queue_family is used to specify which queue family - * the image is currently owned by. If using multiple queue families - * (e.g. async compute), the frontend will need to acquire ownership of the - * image before rendering with it and release the image afterwards. - * - * If src_queue_family is equal to the queue family (queue_index), - * no ownership transfer will occur. - * Similarly, if src_queue_family is VK_QUEUE_FAMILY_IGNORED, - * no ownership transfer will occur. - * - * The frontend will always release ownership back to src_queue_family. - * Waiting for frontend to complete with wait_sync_index() ensures that - * the frontend has released ownership back to the application. - * Note that in Vulkan, transfering ownership is a two-part process. - * - * Example frame: - * - core releases ownership from src_queue_index to queue_index with VkImageMemoryBarrier. - * - core calls set_image with src_queue_index. - * - Frontend will acquire the image with src_queue_index -> queue_index as well, completing the ownership transfer. - * - Frontend renders the frame. - * - Frontend releases ownership with queue_index -> src_queue_index. - * - Next time image is used, core must acquire ownership from queue_index ... - * - * Since the frontend releases ownership, we cannot necessarily dupe the frame because - * the core needs to make the roundtrip of ownership transfer. - */ - retro_vulkan_set_image_t set_image; - - /* Get the current sync index for this frame which is obtained in - * frontend by calling e.g. vkAcquireNextImageKHR before calling - * retro_run(). - * - * This index will correspond to which swapchain buffer is currently - * the active one. - * - * Knowing this index is very useful for maintaining safe asynchronous CPU - * and GPU operation without stalling. - * - * The common pattern for synchronization is to receive fences when - * submitting command buffers to Vulkan (vkQueueSubmit) and add this fence - * to a list of fences for frame number get_sync_index(). - * - * Next time we receive the same get_sync_index(), we can wait for the - * fences from before, which will usually return immediately as the - * frontend will generally also avoid letting the GPU run ahead too much. - * - * After the fence has signaled, we know that the GPU has completed all - * GPU work related to work submitted in the frame we last saw get_sync_index(). - * - * This means we can safely reuse or free resources allocated in this frame. - * - * In theory, even if we wait for the fences correctly, it is not technically - * safe to write to the image we earlier passed to the frontend since we're - * not waiting for the frontend GPU jobs to complete. - * - * The frontend will guarantee that the appropriate pipeline barrier - * in graphics_queue has been used such that - * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT cannot - * start until the frontend is done with the image. - */ - retro_vulkan_get_sync_index_t get_sync_index; - - /* Returns a bitmask of how many swapchain images we currently have - * in the frontend. - * - * If bit #N is set in the return value, get_sync_index can return N. - * Knowing this value is useful for preallocating per-frame management - * structures ahead of time. - * - * While this value will typically remain constant throughout the - * applications lifecycle, it may for example change if the frontend - * suddently changes fullscreen state and/or latency. - * - * If this value ever changes, it is safe to assume that the device - * is completely idle and all synchronization objects can be deleted - * right away as desired. - */ - retro_vulkan_get_sync_index_mask_t get_sync_index_mask; - - /* Instead of submitting the command buffer to the queue first, the core - * can pass along its command buffer to the frontend, and the frontend - * will submit the command buffer together with the frontends command buffers. - * - * This has the advantage that the overhead of vkQueueSubmit can be - * amortized into a single call. For this mode, semaphores in set_image - * will be ignored, so vkCmdPipelineBarrier must be used to synchronize - * the core and frontend. - * - * The command buffers in set_command_buffers are only executed once, - * even if frame duping is used. - * - * If frame duping is used, set_image should be used for the frames - * which should be duped instead. - * - * Command buffers passed to the frontend with set_command_buffers - * must not actually be submitted to the GPU until retro_video_refresh_t - * is called. - * - * The frontend must submit the command buffer before submitting any - * other command buffers provided by set_command_buffers. */ - retro_vulkan_set_command_buffers_t set_command_buffers; - - /* Waits on CPU for device activity for the current sync index to complete. - * This is useful since the core will not have a relevant fence to sync with - * when the frontend is submitting the command buffers. */ - retro_vulkan_wait_sync_index_t wait_sync_index; - - /* If the core submits command buffers itself to any of the queues provided - * in this interface, the core must lock and unlock the frontend from - * racing on the VkQueue. - * - * Queue submission can happen on any thread. - * Even if queue submission happens on the same thread as retro_run(), - * the lock/unlock functions must still be called. - * - * NOTE: Queue submissions are heavy-weight. */ - retro_vulkan_lock_queue_t lock_queue; - retro_vulkan_unlock_queue_t unlock_queue; - - /* Sets a semaphore which is signaled when the image in set_image can safely be reused. - * The semaphore is consumed next call to retro_video_refresh_t. - * The semaphore will be signalled even for duped frames. - * The semaphore will be signalled only once, so set_signal_semaphore should be called every frame. - * The semaphore may be VK_NULL_HANDLE, which disables semaphore signalling for next call to retro_video_refresh_t. - * - * This is mostly useful to support use cases where you're rendering to a single image that - * is recycled in a ping-pong fashion with the frontend to save memory (but potentially less throughput). - */ - retro_vulkan_set_signal_semaphore_t set_signal_semaphore; -}; - -#endif diff --git a/duckstation.sln b/duckstation.sln index 4a853475c..022ab1f05 100644 --- a/duckstation.sln +++ b/duckstation.sln @@ -51,8 +51,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scmversion", "src\scmversio EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "discord-rpc", "dep\discord-rpc\discord-rpc.vcxproj", "{4266505B-DBAF-484B-AB31-B53B9C8235B3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "duckstation-libretro", "src\duckstation-libretro\duckstation-libretro.vcxproj", "{9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glslang", "dep\glslang\glslang.vcxproj", "{7F909E29-4808-4BD9-A60C-56C51A3AAEC2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vulkan-loader", "dep\vulkan-loader\vulkan-loader.vcxproj", "{9C8DDEB0-2B8F-4F5F-BA86-127CDF27F035}" @@ -629,18 +627,6 @@ Global {4266505B-DBAF-484B-AB31-B53B9C8235B3}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64 {4266505B-DBAF-484B-AB31-B53B9C8235B3}.ReleaseLTCG|x86.ActiveCfg = ReleaseLTCG|Win32 {4266505B-DBAF-484B-AB31-B53B9C8235B3}.ReleaseLTCG|x86.Build.0 = ReleaseLTCG|Win32 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.Debug|x64.ActiveCfg = Debug|x64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.Debug|x86.ActiveCfg = Debug|Win32 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.DebugFast|ARM64.ActiveCfg = DebugFast|ARM64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.DebugFast|x64.ActiveCfg = DebugFast|x64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.DebugFast|x86.ActiveCfg = DebugFast|Win32 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.Release|ARM64.ActiveCfg = Release|ARM64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.Release|x64.ActiveCfg = Release|x64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.Release|x86.ActiveCfg = Release|Win32 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG|ARM64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64 - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF}.ReleaseLTCG|x86.ActiveCfg = ReleaseLTCG|Win32 {7F909E29-4808-4BD9-A60C-56C51A3AAEC2}.Debug|ARM64.ActiveCfg = Debug|ARM64 {7F909E29-4808-4BD9-A60C-56C51A3AAEC2}.Debug|ARM64.Build.0 = Debug|ARM64 {7F909E29-4808-4BD9-A60C-56C51A3AAEC2}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/scripts/gamesettings_to_libretro.py b/scripts/gamesettings_to_libretro.py deleted file mode 100644 index c14a6e1f1..000000000 --- a/scripts/gamesettings_to_libretro.py +++ /dev/null @@ -1,106 +0,0 @@ -import sys -import configparser - -def parse_ini(path): - config = configparser.ConfigParser() - config.read(path) - - entries = {} - int_keys = { - "DisplayActiveStartOffset": "display_active_start_offset", - "DisplayActiveEndOffset": "display_active_end_offset", - "DMAMaxSliceTicks": "dma_max_slice_ticks", - "DMAHaltTicks": "dma_halt_ticks", - "GPUFIFOSize" : "gpu_fifo_size", - "GPUMaxRunAhead" : "gpu_max_run_ahead" - } - float_keys = { - "GPUPGXPTolerance" : "gpu_pgxp_tolerance" - } - traits = [ - "ForceInterpreter", - "ForceSoftwareRenderer", - "ForceInterlacing", - "DisableTrueColor", - "DisableUpscaling", - "DisableScaledDithering", - "DisableForceNTSCTimings", - "DisableWidescreen", - "DisablePGXP", - "DisablePGXPCulling", - "DisablePGXPTextureCorrection", - "ForcePGXPVertexCache", - "ForcePGXPCPUMode", - "DisableAnalogModeForcing", - "ForceRecompilerMemoryExceptions", - "ForceRecompilerICache" - ] - - for gameid in config.sections(): - entry = {} - for ini_key, cpp_key in int_keys.items(): - try: - value = config.get(gameid, ini_key) - if value is not None: - entry[cpp_key] = str(value) - except configparser.NoOptionError: - pass - - for ini_key, cpp_key in float_keys.items(): - try: - value = config.getfloat(gameid, ini_key, fallback=None) - if value is not None: - entry[cpp_key] = str(value) - except configparser.NoOptionError: - pass - - for trait in traits: - try: - value = config.getboolean(gameid, trait, fallback=None) - if value == True: - if "traits" not in entry: - entry["traits"] = [] - entry["traits"].append(trait) - except configparser.NoOptionError: - pass - - if len(entry) > 0: - entries[gameid] = entry - - return entries - - -def write_cpp(entries, path): - print("Writing %u entries to '%s'" % (len(entries), path)) - with open(path, "w") as f: - f.write('#include "libretro_game_settings.h"\n') - f.write('\n') - f.write('std::unique_ptr GetSettingsForGame(const std::string& game_code)\n') - f.write('{\n') - f.write(' std::unique_ptr gs = std::make_unique();\n') - f.write('\n') - - for gameid, entry in entries.items(): - f.write(' if (game_code == "%s")\n' % gameid) - f.write(' {\n') - for key, value in entry.items(): - if key == "traits": - for trait in value: - f.write(' gs->AddTrait(GameSettings::Trait::%s);\n' % trait) - else: - f.write(' gs->%s = %s;\n' % (key, value)) - f.write(' return gs;\n') - f.write(' }\n') - f.write('\n') - - f.write(' return {};\n') - f.write('}\n') - - -if __name__ == "__main__": - if len(sys.argv) < 3: - print("usage: %s " % sys.argv[0]) - sys.exit(1) - - entries = parse_ini(sys.argv[1]) - write_cpp(entries, sys.argv[2]) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e91fb70a8..3baa44a37 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,19 +1,13 @@ -if(BUILD_LIBRETRO_CORE) - add_definitions("-DLIBRETRO=1") -endif() - add_subdirectory(common) add_subdirectory(core) add_subdirectory(scmversion) -if(NOT BUILD_LIBRETRO_CORE) - add_subdirectory(common-tests) - if(WIN32) - add_subdirectory(updater) - endif() +add_subdirectory(common-tests) +if(WIN32) + add_subdirectory(updater) endif() -if(ANDROID OR BUILD_SDL_FRONTEND OR BUILD_QT_FRONTEND OR BUILD_LIBRETRO_CORE) +if(ANDROID OR BUILD_SDL_FRONTEND OR BUILD_QT_FRONTEND) add_subdirectory(frontend-common) endif() @@ -24,8 +18,3 @@ endif() if(BUILD_QT_FRONTEND) add_subdirectory(duckstation-qt) endif() - -if(BUILD_LIBRETRO_CORE) - add_subdirectory(duckstation-libretro) -endif() - diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e71eceecc..777553dbc 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -179,9 +179,6 @@ endif() if(APPLE) # Needed for Vulkan Swap Chain. target_link_libraries(common PRIVATE "objc") -endif() - -if(APPLE AND NOT BUILD_LIBRETRO_CORE) target_sources(common PRIVATE gl/context_agl.mm gl/context_agl.h diff --git a/src/common/gl/context.cpp b/src/common/gl/context.cpp index 861cb21cf..aecabae23 100644 --- a/src/common/gl/context.cpp +++ b/src/common/gl/context.cpp @@ -11,7 +11,7 @@ Log_SetChannel(GL::Context); #if defined(WIN32) && !defined(_M_ARM64) #include "context_wgl.h" -#elif defined(__APPLE__) && !defined(LIBERTRO) +#elif defined(__APPLE__) #include "context_agl.h" #endif @@ -77,7 +77,7 @@ std::unique_ptr Context::Create(const WindowInfo& wi, const Version std::unique_ptr context; #if defined(WIN32) && !defined(_M_ARM64) context = ContextWGL::Create(wi, versions_to_try, num_versions_to_try); -#elif defined(__APPLE__) && !defined(LIBRETRO) +#elif defined(__APPLE__) context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try); #elif defined(ANDROID) #ifdef USE_EGL diff --git a/src/common/vulkan/shader_compiler.cpp b/src/common/vulkan/shader_compiler.cpp index 9340522e6..45833e5d5 100644 --- a/src/common/vulkan/shader_compiler.cpp +++ b/src/common/vulkan/shader_compiler.cpp @@ -124,9 +124,7 @@ bool InitializeGlslang() return false; } -#ifndef LIBRETRO std::atexit([]() { glslang::FinalizeProcess(); }); -#endif glslang_initialized = true; return true; diff --git a/src/common/window_info.h b/src/common/window_info.h index 258bd1783..0c5943efd 100644 --- a/src/common/window_info.h +++ b/src/common/window_info.h @@ -12,7 +12,6 @@ struct WindowInfo Wayland, MacOS, Android, - Libretro, }; enum class SurfaceFormat diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 77f909a04..059ef1838 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -116,6 +116,9 @@ target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_link_libraries(core PUBLIC Threads::Threads common zlib vulkan-loader) target_link_libraries(core PRIVATE glad stb xxhash) +target_compile_definitions(core PRIVATE "WITH_IMGUI=1") +target_link_libraries(core PRIVATE imgui) + if(WIN32) target_sources(core PRIVATE gpu_hw_d3d11.cpp @@ -148,8 +151,3 @@ elseif(${CPU_ARCH} STREQUAL "aarch64") else() message("Not building recompiler") endif() - -if(NOT BUILD_LIBRETRO_CORE) - target_link_libraries(core PRIVATE imgui) - target_compile_definitions(core PRIVATE "WITH_IMGUI=1") -endif() diff --git a/src/duckstation-libretro/CMakeLists.txt b/src/duckstation-libretro/CMakeLists.txt deleted file mode 100644 index 6efc85d56..000000000 --- a/src/duckstation-libretro/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -add_library(duckstation_libretro SHARED - libretro_audio_stream.cpp - libretro_audio_stream.h - libretro_game_settings.cpp - libretro_game_settings.h - libretro_host_display.cpp - libretro_host_display.h - libretro_host_interface.cpp - libretro_host_interface.h - libretro_opengl_host_display.cpp - libretro_opengl_host_display.h - libretro_settings_interface.cpp - libretro_settings_interface.h - libretro_vulkan_host_display.cpp - libretro_vulkan_host_display.h - main.cpp -) - -if(WIN32) - target_sources(duckstation_libretro PRIVATE - libretro_d3d11_host_display.cpp - libretro_d3d11_host_display.h - ) -endif() - -target_link_libraries(duckstation_libretro PRIVATE core common glad scmversion frontend-common vulkan-loader libretro-common) - -# no lib prefix -set_target_properties(duckstation_libretro PROPERTIES PREFIX "") - -# drop in the build directory -set_target_properties(duckstation_libretro PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") -set_target_properties(duckstation_libretro PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") - -# work around .sln issue of hardcoded config directories -if(WIN32) - set_target_properties(duckstation_libretro PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}") - set_target_properties(duckstation_libretro PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}") -endif() - -# for android, suffix _android -if(ANDROID) - set_target_properties(duckstation_libretro PROPERTIES OUTPUT_NAME "duckstation_libretro_android") -endif() diff --git a/src/duckstation-libretro/duckstation-libretro.vcxproj b/src/duckstation-libretro/duckstation-libretro.vcxproj deleted file mode 100644 index ad3205ceb..000000000 --- a/src/duckstation-libretro/duckstation-libretro.vcxproj +++ /dev/null @@ -1,582 +0,0 @@ - - - - - DebugFast - ARM64 - - - DebugFast - Win32 - - - DebugFast - x64 - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - ReleaseLTCG - ARM64 - - - ReleaseLTCG - Win32 - - - ReleaseLTCG - x64 - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - - {9c8ddeb0-2b8f-4f5f-ba86-127cdf27f035} - - - {ee054e08-3799-4a59-a422-18259c105ffd} - - - {868b98c8-65a1-494b-8346-250a73a48c0a} - - - {6245dec8-d2da-47ee-a373-cbd6fcf3ece6} - - - {075ced82-6a20-46df-94c7-9624ac9ddbeb} - - - - - - - - - - - - - - - - - - - - - - - - - {9D206548-DE8F-4D9D-A561-C7E5CD7A20DF} - Win32Proj - duckstation-libretro - 10.0 - - - - DynamicLibrary - true - v142 - NotSet - - - DynamicLibrary - true - v142 - NotSet - - - DynamicLibrary - true - v142 - NotSet - - - DynamicLibrary - true - v142 - NotSet - - - DynamicLibrary - true - v142 - NotSet - - - DynamicLibrary - true - v142 - NotSet - - - DynamicLibrary - false - v142 - true - NotSet - false - - - DynamicLibrary - false - v142 - true - NotSet - false - - - DynamicLibrary - false - v142 - true - NotSet - false - - - DynamicLibrary - false - v142 - true - NotSet - false - - - DynamicLibrary - false - v142 - true - NotSet - false - - - DynamicLibrary - false - v142 - true - NotSet - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(SolutionDir)bin\$(Platform)\ - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - true - $(SolutionDir)bin\$(Platform)\ - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - true - $(SolutionDir)bin\$(Platform)\ - - - true - $(SolutionDir)bin\$(Platform)\ - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - true - $(SolutionDir)bin\$(Platform)\ - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - true - $(SolutionDir)bin\$(Platform)\ - - - $(SolutionDir)bin\$(Platform)\ - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - - - false - $(SolutionDir)bin\$(Platform)\ - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - $(SolutionDir)bin\$(Platform)\ - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - $(SolutionDir)bin\$(Platform)\ - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - false - $(SolutionDir)bin\$(Platform)\ - - - $(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\ - $(ProjectName)-$(Platform)-$(Configuration) - false - $(SolutionDir)bin\$(Platform)\ - - - - - - Level4 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ProgramDatabase - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - false - stdcpp17 - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ProgramDatabase - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - false - stdcpp17 - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ProgramDatabase - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - false - stdcpp17 - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - _ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ProgramDatabase - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - Default - true - false - stdcpp17 - false - OnlyExplicitInline - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - _ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ProgramDatabase - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - Default - true - false - stdcpp17 - false - OnlyExplicitInline - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - - - - - - - Level4 - Disabled - _ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - true - ProgramDatabase - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - Default - true - false - stdcpp17 - false - OnlyExplicitInline - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - - - - - Level4 - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - false - stdcpp17 - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - true - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - Default - - - - - Level4 - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - true - stdcpp17 - true - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - true - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - Level4 - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - false - stdcpp17 - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - true - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - Default - - - - - Level4 - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - false - stdcpp17 - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - true - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - Default - - - - - Level4 - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - true - stdcpp17 - true - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - true - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - Level4 - - - MaxSpeed - true - _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) - $(SolutionDir)dep\imgui\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan-loader\include;$(SolutionDir)dep\libretro-common\include;$(SolutionDir)src;%(AdditionalIncludeDirectories) - true - true - stdcpp17 - true - true - /Zo /utf-8 %(AdditionalOptions) - - - Windows - true - true - true - d3d11.lib;dxgi.lib;%(AdditionalDependencies) - UseLinkTimeCodeGeneration - - - - - - \ No newline at end of file diff --git a/src/duckstation-libretro/duckstation-libretro.vcxproj.filters b/src/duckstation-libretro/duckstation-libretro.vcxproj.filters deleted file mode 100644 index e1941f70f..000000000 --- a/src/duckstation-libretro/duckstation-libretro.vcxproj.filters +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/duckstation-libretro/libretro_audio_stream.cpp b/src/duckstation-libretro/libretro_audio_stream.cpp deleted file mode 100644 index b29c4942b..000000000 --- a/src/duckstation-libretro/libretro_audio_stream.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "libretro_audio_stream.h" -#include "libretro_host_interface.h" - -LibretroAudioStream::LibretroAudioStream() = default; - -LibretroAudioStream::~LibretroAudioStream() = default; - -bool LibretroAudioStream::OpenDevice() -{ - m_output_buffer.resize(m_buffer_size * m_channels); - return true; -} - -void LibretroAudioStream::PauseDevice(bool paused) {} - -void LibretroAudioStream::CloseDevice() {} - -void LibretroAudioStream::FramesAvailable() -{ - const u32 num_frames = GetSamplesAvailable(); - ReadFrames(m_output_buffer.data(), num_frames, false); - g_retro_audio_sample_batch_callback(m_output_buffer.data(), num_frames); -} diff --git a/src/duckstation-libretro/libretro_audio_stream.h b/src/duckstation-libretro/libretro_audio_stream.h deleted file mode 100644 index 45e718753..000000000 --- a/src/duckstation-libretro/libretro_audio_stream.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "common/audio_stream.h" -#include -#include - -class LibretroAudioStream final : public AudioStream -{ -public: - LibretroAudioStream(); - ~LibretroAudioStream(); - -protected: - bool OpenDevice() override; - void PauseDevice(bool paused) override; - void CloseDevice() override; - void FramesAvailable() override; - -private: - // TODO: Optimize this buffer away. - std::vector m_output_buffer; -}; diff --git a/src/duckstation-libretro/libretro_d3d11_host_display.cpp b/src/duckstation-libretro/libretro_d3d11_host_display.cpp deleted file mode 100644 index 4692f34df..000000000 --- a/src/duckstation-libretro/libretro_d3d11_host_display.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "libretro_d3d11_host_display.h" -#include "common/align.h" -#include "common/assert.h" -#include "common/d3d11/shader_compiler.h" -#include "common/log.h" -#include "libretro_host_interface.h" -Log_SetChannel(LibretroD3D11HostDisplay); - -#define HAVE_D3D11 -#include "libretro_d3d.h" - -LibretroD3D11HostDisplay::LibretroD3D11HostDisplay() = default; - -LibretroD3D11HostDisplay::~LibretroD3D11HostDisplay() = default; - -void LibretroD3D11HostDisplay::SetVSync(bool enabled) -{ - // The libretro frontend controls this. - Log_DevPrintf("Ignoring SetVSync(%u)", BoolToUInt32(enabled)); -} - -bool LibretroD3D11HostDisplay::RequestHardwareRendererContext(retro_hw_render_callback* cb) -{ - cb->cache_context = false; - cb->bottom_left_origin = false; - cb->context_type = RETRO_HW_CONTEXT_DIRECT3D; - cb->version_major = 11; - cb->version_minor = 0; - - return g_retro_environment_callback(RETRO_ENVIRONMENT_SET_HW_RENDER, cb); -} - -bool LibretroD3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, - bool debug_device, bool threaded_presentation) -{ - retro_hw_render_interface* ri = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, &ri)) - { - Log_ErrorPrint("Failed to get HW render interface"); - return false; - } - else if (ri->interface_type != RETRO_HW_RENDER_INTERFACE_D3D11 || - ri->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) - { - Log_ErrorPrintf("Unexpected HW interface - type %u version %u", static_cast(ri->interface_type), - static_cast(ri->interface_version)); - return false; - } - - const retro_hw_render_interface_d3d11* d3d11_ri = reinterpret_cast(ri); - if (!d3d11_ri->device || !d3d11_ri->context) - { - Log_ErrorPrintf("Missing D3D device or context"); - return false; - } - - m_device = d3d11_ri->device; - m_context = d3d11_ri->context; - return true; -} - -void LibretroD3D11HostDisplay::DestroyResources() -{ - D3D11HostDisplay::DestroyResources(); - m_framebuffer.Destroy(); -} - -void LibretroD3D11HostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_height) -{ - m_window_info.surface_width = static_cast(new_window_width); - m_window_info.surface_height = static_cast(new_window_height); -} - -bool LibretroD3D11HostDisplay::ChangeRenderWindow(const WindowInfo& new_wi) -{ - // Check that the device hasn't changed. - retro_hw_render_interface* ri = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, &ri)) - { - Log_ErrorPrint("Failed to get HW render interface"); - return false; - } - else if (ri->interface_type != RETRO_HW_RENDER_INTERFACE_D3D11 || - ri->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) - { - Log_ErrorPrintf("Unexpected HW interface - type %u version %u", static_cast(ri->interface_type), - static_cast(ri->interface_version)); - return false; - } - - const retro_hw_render_interface_d3d11* d3d11_ri = reinterpret_cast(ri); - if (d3d11_ri->device != m_device.Get() || d3d11_ri->context != m_context.Get()) - { - Log_ErrorPrintf("D3D device/context changed outside our control"); - return false; - } - - m_window_info = new_wi; - return true; -} - -bool LibretroD3D11HostDisplay::Render() -{ - const u32 resolution_scale = g_libretro_host_interface.GetResolutionScale(); - const u32 display_width = static_cast(m_display_width) * resolution_scale; - const u32 display_height = static_cast(m_display_height) * resolution_scale; - if (!CheckFramebufferSize(display_width, display_height)) - return false; - - // Ensure we're not currently bound. - ID3D11ShaderResourceView* null_srv = nullptr; - m_context->PSSetShaderResources(0, 1, &null_srv); - m_context->OMSetRenderTargets(1u, m_framebuffer.GetD3DRTVArray(), nullptr); - - if (HasDisplayTexture()) - { - const auto [left, top, width, height] = CalculateDrawRect(display_width, display_height, 0, false); - RenderDisplay(left, top, width, height, m_display_texture_handle, m_display_texture_width, m_display_texture_height, - m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width, - m_display_texture_view_height, m_display_linear_filtering); - } - - if (HasSoftwareCursor()) - { - // TODO: Scale mouse x/y - const auto [left, top, width, height] = CalculateSoftwareCursorDrawRect(m_mouse_position_x, m_mouse_position_y); - RenderSoftwareCursor(left, top, width, height, m_cursor_texture.get()); - } - - // NOTE: libretro frontend expects the data bound to PS SRV slot 0. - m_context->OMSetRenderTargets(0, nullptr, nullptr); - m_context->PSSetShaderResources(0, 1, m_framebuffer.GetD3DSRVArray()); - g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, display_width, display_height, 0); - return true; -} - -bool LibretroD3D11HostDisplay::CheckFramebufferSize(u32 width, u32 height) -{ - if (m_framebuffer.GetWidth() == width && m_framebuffer.GetHeight() == height) - return true; - - return m_framebuffer.Create(m_device.Get(), width, height, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, - D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET); -} diff --git a/src/duckstation-libretro/libretro_d3d11_host_display.h b/src/duckstation-libretro/libretro_d3d11_host_display.h deleted file mode 100644 index 896f76a53..000000000 --- a/src/duckstation-libretro/libretro_d3d11_host_display.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "common/d3d11/texture.h" -#include "frontend-common/d3d11_host_display.h" -#include "libretro.h" - -class LibretroD3D11HostDisplay final : public FrontendCommon::D3D11HostDisplay -{ -public: - LibretroD3D11HostDisplay(); - ~LibretroD3D11HostDisplay(); - - static bool RequestHardwareRendererContext(retro_hw_render_callback* cb); - - bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device, - bool threaded_presentation) override; - - void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) override; - bool ChangeRenderWindow(const WindowInfo& new_wi) override; - - void SetVSync(bool enabled) override; - - bool Render() override; - -protected: - void DestroyResources() override; - -private: - bool CheckFramebufferSize(u32 width, u32 height); - - D3D11::Texture m_framebuffer; -}; diff --git a/src/duckstation-libretro/libretro_game_settings.cpp b/src/duckstation-libretro/libretro_game_settings.cpp deleted file mode 100644 index ffc188013..000000000 --- a/src/duckstation-libretro/libretro_game_settings.cpp +++ /dev/null @@ -1,639 +0,0 @@ -#include "libretro_game_settings.h" - -std::unique_ptr GetSettingsForGame(const std::string& game_code) -{ - std::unique_ptr gs = std::make_unique(); - - if (game_code == "SLUS-00530") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SLUS-00634") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SLUS-00077") - { - gs->AddTrait(GameSettings::Trait::DisableUpscaling); - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLPM-87089") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLPS-03336") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-01260") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLES-01211") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-01261") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLES-02466") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLES-00259") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLES-00606") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00639") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-90039") - { - gs->AddTrait(GameSettings::Trait::ForceSoftwareRenderer); - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00337") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00606") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLPS-03553") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLPS-01211") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00656") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00952") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-01222") - { - gs->display_active_start_offset = 64; - gs->display_active_end_offset = 68; - return gs; - } - - if (game_code == "SLUS-00297") - { - gs->AddTrait(GameSettings::Trait::DisableUpscaling); - gs->AddTrait(GameSettings::Trait::DisablePGXP); - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SCUS-94350") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SCUS-94900") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "PCPX-96085") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00590") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00403") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SCUS-94300") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00214") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00204") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00006") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00213") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SCES-00344") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00355") - { - gs->AddTrait(GameSettings::Trait::DisableUpscaling); - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00331") - { - gs->AddTrait(GameSettings::Trait::DisableUpscaling); - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00106") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00005") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-01265") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00601") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLPS-00435") - { - gs->AddTrait(GameSettings::Trait::ForceRecompilerICache); - return gs; - } - - if (game_code == "SLUS-00388") - { - gs->AddTrait(GameSettings::Trait::ForceRecompilerICache); - return gs; - } - - if (game_code == "SCES-02834") - { - gs->AddTrait(GameSettings::Trait::ForceRecompilerICache); - return gs; - } - - if (game_code == "SLUS-00870") - { - gs->AddTrait(GameSettings::Trait::ForceInterpreter); - return gs; - } - - if (game_code == "SLUS-00183") - { - gs->AddTrait(GameSettings::Trait::ForceRecompilerICache); - return gs; - } - - if (game_code == "SLES-00483") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLPS-02361") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPVertexCache); - return gs; - } - - if (game_code == "SLPM-86023") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00067") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLES-00524") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLPS-00712") - { - gs->AddTrait(GameSettings::Trait::ForceRecompilerICache); - return gs; - } - - if (game_code == "SLPS-01434") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00684") - { - gs->AddTrait(GameSettings::Trait::ForceInterpreter); - return gs; - } - - if (game_code == "SLPS-02459") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLPM-86750") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLPS-02120") - { - gs->AddTrait(GameSettings::Trait::ForceInterlacing); - return gs; - } - - if (game_code == "SLUS-00102") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00152") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00603") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00348") - { - gs->AddTrait(GameSettings::Trait::DisableUpscaling); - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00042") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00561") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00035") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00057") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00014") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SCUS-94403") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00549") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00240") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00027") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00119") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00224") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00453") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00753") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00811") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00208") - { - gs->display_active_start_offset = -62; - gs->display_active_end_offset = 72; - return gs; - } - - if (game_code == "SLPS-01762") - { - gs->AddTrait(GameSettings::Trait::DisablePGXPCulling); - return gs; - } - - if (game_code == "SLPS-01567") - { - gs->display_active_start_offset = -62; - gs->display_active_end_offset = 51; - return gs; - } - - if (game_code == "SLPS-00360") - { - gs->display_active_start_offset = -62; - gs->display_active_end_offset = 72; - return gs; - } - - if (game_code == "SCES-02835") - { - gs->AddTrait(GameSettings::Trait::ForceInterpreter); - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCES-02104") - { - gs->AddTrait(GameSettings::Trait::ForceInterpreter); - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCES-01438") - { - gs->AddTrait(GameSettings::Trait::DisablePGXPCulling); - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCUS-94467") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCUS-94425") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCPS-10085") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCUS-94228") - { - gs->AddTrait(GameSettings::Trait::DisablePGXPCulling); - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SCUS-94290") - { - gs->AddTrait(GameSettings::Trait::ForcePGXPCPUMode); - return gs; - } - - if (game_code == "SLUS-01138") - { - gs->dma_max_slice_ticks = 200; - gs->gpu_max_run_ahead = 1; - return gs; - } - - if (game_code == "SLPS-02376") - { - gs->dma_max_slice_ticks = 100; - gs->gpu_max_run_ahead = 1; - return gs; - } - - if (game_code == "SLUS-00282") - { - gs->dma_max_slice_ticks = 200; - gs->gpu_max_run_ahead = 1; - return gs; - } - - if (game_code == "SLUS-00022") - { - gs->AddTrait(GameSettings::Trait::DisableUpscaling); - return gs; - } - - if (game_code == "SLUS-00292") - { - gs->AddTrait(GameSettings::Trait::ForceRecompilerICache); - return gs; - } - - if (game_code == "SLUS-00522") - { - gs->dma_max_slice_ticks = 200; - return gs; - } - - if (game_code == "SLES-00469") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLPS-01163") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLUS-00498") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLPS-00433") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLUS-01029") - { - gs->AddTrait(GameSettings::Trait::DisableAnalogModeForcing); - return gs; - } - - if (game_code == "SLUS-00506") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLES-00704") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLPS-01399") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLUS-00232") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLES-00526") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - if (game_code == "SLED-00570") - { - gs->dma_max_slice_ticks = 100; - return gs; - } - - return {}; -} diff --git a/src/duckstation-libretro/libretro_game_settings.h b/src/duckstation-libretro/libretro_game_settings.h deleted file mode 100644 index 5bbf2fec4..000000000 --- a/src/duckstation-libretro/libretro_game_settings.h +++ /dev/null @@ -1,4 +0,0 @@ -#include "frontend-common/game_settings.h" -#include - -std::unique_ptr GetSettingsForGame(const std::string& game_code); diff --git a/src/duckstation-libretro/libretro_host_display.cpp b/src/duckstation-libretro/libretro_host_display.cpp deleted file mode 100644 index b4bf7bf29..000000000 --- a/src/duckstation-libretro/libretro_host_display.cpp +++ /dev/null @@ -1,233 +0,0 @@ -#include "libretro_host_display.h" -#include "common/align.h" -#include "common/assert.h" -#include "common/log.h" -#include "libretro.h" -#include "libretro_host_interface.h" -#include -#include -Log_SetChannel(LibretroHostDisplay); - -static retro_pixel_format GetRetroPixelFormat(HostDisplayPixelFormat format) -{ - switch (format) - { - case HostDisplayPixelFormat::BGRA8: - return RETRO_PIXEL_FORMAT_XRGB8888; - - case HostDisplayPixelFormat::RGB565: - return RETRO_PIXEL_FORMAT_RGB565; - - case HostDisplayPixelFormat::RGBA5551: - return RETRO_PIXEL_FORMAT_0RGB1555; - - default: - return RETRO_PIXEL_FORMAT_UNKNOWN; - } -} - -LibretroHostDisplay::LibretroHostDisplay() -{ - retro_pixel_format pf = RETRO_PIXEL_FORMAT_RGB565; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &pf)) - Log_ErrorPrint("Failed to set pixel format to RGB565"); - else - m_current_pixel_format = pf; -} - -LibretroHostDisplay::~LibretroHostDisplay() = default; - -bool LibretroHostDisplay::CheckPixelFormat(retro_pixel_format new_format) -{ - if (new_format == RETRO_PIXEL_FORMAT_UNKNOWN || m_current_pixel_format == new_format) - return true; - - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &new_format)) - { - Log_ErrorPrintf("g_retro_environment_callback(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, %u) failed", - static_cast(new_format)); - return false; - } - - if (!g_libretro_host_interface.UpdateSystemAVInfo(false)) - return false; - - m_current_pixel_format = new_format; - return true; -} - -HostDisplay::RenderAPI LibretroHostDisplay::GetRenderAPI() const -{ - return RenderAPI::None; -} - -void* LibretroHostDisplay::GetRenderDevice() const -{ - return nullptr; -} - -void* LibretroHostDisplay::GetRenderContext() const -{ - return nullptr; -} - -bool LibretroHostDisplay::HasRenderDevice() const -{ - return true; -} - -bool LibretroHostDisplay::HasRenderSurface() const -{ - return true; -} - -bool LibretroHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device, - bool threaded_presentation) -{ - m_window_info = wi; - return true; -} - -bool LibretroHostDisplay::InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device, - bool threaded_presentation) -{ - return true; -} - -bool LibretroHostDisplay::MakeRenderContextCurrent() -{ - return true; -} - -bool LibretroHostDisplay::DoneRenderContextCurrent() -{ - return true; -} - -void LibretroHostDisplay::DestroyRenderDevice() {} - -void LibretroHostDisplay::DestroyRenderSurface() {} - -bool LibretroHostDisplay::CreateResources() -{ - return true; -} - -void LibretroHostDisplay::DestroyResources() {} - -bool LibretroHostDisplay::ChangeRenderWindow(const WindowInfo& wi) -{ - m_window_info = wi; - return true; -} - -void LibretroHostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_height) -{ - m_window_info.surface_width = new_window_width; - m_window_info.surface_height = new_window_height; -} - -bool LibretroHostDisplay::SupportsFullscreen() const -{ - return false; -} - -bool LibretroHostDisplay::IsFullscreen() -{ - return false; -} - -bool LibretroHostDisplay::SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) -{ - return false; -} - -bool LibretroHostDisplay::SetPostProcessingChain(const std::string_view& config) -{ - return false; -} - -std::unique_ptr LibretroHostDisplay::CreateTexture(u32 width, u32 height, const void* data, - u32 data_stride, bool dynamic) -{ - return nullptr; -} - -void LibretroHostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, - const void* data, u32 data_stride) -{ -} - -bool LibretroHostDisplay::DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, - u32 y, u32 width, u32 height, void* out_data, u32 out_data_stride) -{ - return false; -} - -bool LibretroHostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const -{ - // For when we can change the pixel format. - // return (GetRetroPixelFormat(format) != RETRO_PIXEL_FORMAT_UNKNOWN); - return (GetRetroPixelFormat(format) == m_current_pixel_format); -} - -bool LibretroHostDisplay::BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer, - u32* out_pitch) -{ - const retro_pixel_format retro_pf = GetRetroPixelFormat(format); - if (!CheckPixelFormat(retro_pf)) - return false; - - m_software_fb.data = nullptr; - m_software_fb.width = width; - m_software_fb.height = height; - m_software_fb.pitch = 0; - m_software_fb.format = RETRO_PIXEL_FORMAT_UNKNOWN; - m_software_fb.access_flags = RETRO_MEMORY_ACCESS_WRITE; - m_software_fb.memory_flags = 0; - if (g_retro_environment_callback(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &m_software_fb) && - m_software_fb.format == retro_pf) - { - SetDisplayTexture(m_software_fb.data, format, m_software_fb.width, m_software_fb.height, 0, 0, m_software_fb.width, - m_software_fb.height); - *out_buffer = m_software_fb.data; - *out_pitch = static_cast(m_software_fb.pitch); - return true; - } - - const u32 pitch = Common::AlignUpPow2(width * GetDisplayPixelFormatSize(format), 4); - const u32 required_size = height * pitch; - if (m_frame_buffer.size() < (required_size / 4)) - m_frame_buffer.resize(required_size / 4); - - m_frame_buffer_pitch = pitch; - SetDisplayTexture(m_frame_buffer.data(), format, width, height, 0, 0, width, height); - *out_buffer = m_frame_buffer.data(); - *out_pitch = pitch; - return true; -} - -void LibretroHostDisplay::EndSetDisplayPixels() -{ - // noop -} - -void LibretroHostDisplay::SetVSync(bool enabled) -{ - // The libretro frontend controls this. - Log_DevPrintf("Ignoring SetVSync(%u)", BoolToUInt32(enabled)); -} - -bool LibretroHostDisplay::Render() -{ - if (HasDisplayTexture()) - { - g_retro_video_refresh_callback(m_display_texture_handle, m_display_texture_view_width, - m_display_texture_view_height, m_frame_buffer_pitch); - - if (m_display_texture_handle == m_software_fb.data) - ClearDisplayTexture(); - } - - return true; -} diff --git a/src/duckstation-libretro/libretro_host_display.h b/src/duckstation-libretro/libretro_host_display.h deleted file mode 100644 index ec6778d89..000000000 --- a/src/duckstation-libretro/libretro_host_display.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#include "core/host_display.h" -#include "libretro.h" - -class LibretroHostDisplay final : public HostDisplay -{ -public: - LibretroHostDisplay(); - ~LibretroHostDisplay(); - - RenderAPI GetRenderAPI() const override; - void* GetRenderDevice() const override; - void* GetRenderContext() const override; - - bool HasRenderDevice() const override; - bool HasRenderSurface() const override; - - bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device, - bool threaded_presentation) override; - bool InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device, - bool threaded_presentation) override; - void DestroyRenderDevice() override; - - bool MakeRenderContextCurrent() override; - bool DoneRenderContextCurrent() override; - - bool ChangeRenderWindow(const WindowInfo& wi) override; - void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) override; - bool SupportsFullscreen() const override; - bool IsFullscreen() override; - bool SetFullscreen(bool fullscreen, u32 width, u32 height, float refresh_rate) override; - void DestroyRenderSurface() override; - - bool SetPostProcessingChain(const std::string_view& config) override; - - bool CreateResources() override; - void DestroyResources() override; - - std::unique_ptr CreateTexture(u32 width, u32 height, const void* data, u32 data_stride, - bool dynamic) override; - void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, - u32 data_stride) override; - bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width, - u32 height, void* out_data, u32 out_data_stride) override; - - void SetVSync(bool enabled) override; - - bool Render() override; - - bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const override; - - bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer, - u32* out_pitch) override; - void EndSetDisplayPixels() override; - -private: - bool CheckPixelFormat(retro_pixel_format new_format); - - std::vector m_frame_buffer; - u32 m_frame_buffer_pitch = 0; - retro_framebuffer m_software_fb = {}; - retro_pixel_format m_current_pixel_format = RETRO_PIXEL_FORMAT_UNKNOWN; -}; diff --git a/src/duckstation-libretro/libretro_host_interface.cpp b/src/duckstation-libretro/libretro_host_interface.cpp deleted file mode 100644 index bb5f647ec..000000000 --- a/src/duckstation-libretro/libretro_host_interface.cpp +++ /dev/null @@ -1,1528 +0,0 @@ -#include "libretro_host_interface.h" -#include "common/assert.h" -#include "common/byte_stream.h" -#include "common/cpu_detect.h" -#include "common/file_system.h" -#include "common/log.h" -#include "common/string_util.h" -#include "core/analog_controller.h" -#include "core/bus.h" -#include "core/cheats.h" -#include "core/digital_controller.h" -#include "core/gpu.h" -#include "core/system.h" -#include "libretro_audio_stream.h" -#include "libretro_game_settings.h" -#include "libretro_host_display.h" -#include "libretro_opengl_host_display.h" -#include "libretro_settings_interface.h" -#include "libretro_vulkan_host_display.h" -#include -#include -#include -#include -#include -Log_SetChannel(LibretroHostInterface); - -#ifdef WIN32 -#include "libretro_d3d11_host_display.h" -#endif - -LibretroHostInterface g_libretro_host_interface; -#define P_THIS (&g_libretro_host_interface) - -retro_environment_t g_retro_environment_callback; -retro_video_refresh_t g_retro_video_refresh_callback; -retro_audio_sample_t g_retro_audio_sample_callback; -retro_audio_sample_batch_t g_retro_audio_sample_batch_callback; -retro_input_poll_t g_retro_input_poll_callback; -retro_input_state_t g_retro_input_state_callback; - -static retro_log_callback s_libretro_log_callback = {}; -static bool s_libretro_log_callback_valid = false; -static bool s_libretro_log_callback_registered = false; - -static void LibretroLogCallback(void* pUserParam, const char* channelName, const char* functionName, LOGLEVEL level, - const char* message) -{ - static constexpr std::array levels = { - {RETRO_LOG_ERROR, RETRO_LOG_ERROR, RETRO_LOG_WARN, RETRO_LOG_INFO, RETRO_LOG_INFO, RETRO_LOG_INFO, RETRO_LOG_DEBUG, - RETRO_LOG_DEBUG, RETRO_LOG_DEBUG, RETRO_LOG_DEBUG}}; - - s_libretro_log_callback.log(levels[level], "[%s] %s\n", (level <= LOGLEVEL_PERF) ? functionName : channelName, - message); -} - -LibretroHostInterface::LibretroHostInterface() = default; - -LibretroHostInterface::~LibretroHostInterface() -{ - // should be cleaned up by the context destroy, but just in case - if (m_hw_render_display) - { - m_hw_render_display->DestroyRenderDevice(); - m_hw_render_display.reset(); - } -} - -void LibretroHostInterface::retro_set_environment() -{ - SetCoreOptions(); - InitDiskControlInterface(); - InitLogging(); -} - -void LibretroHostInterface::InitInterfaces() -{ - InitRumbleInterface(); - - unsigned dummy = 0; - m_supports_input_bitmasks = g_retro_environment_callback(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, &dummy); -} - -void LibretroHostInterface::InitLogging() -{ - if (s_libretro_log_callback_registered) - return; - - s_libretro_log_callback_valid = - g_retro_environment_callback(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &s_libretro_log_callback); - - if (s_libretro_log_callback_valid) - { - Log::RegisterCallback(LibretroLogCallback, nullptr); - s_libretro_log_callback_registered = true; - } -} - -bool LibretroHostInterface::Initialize() -{ - if (!HostInterface::Initialize()) - return false; - - InitInterfaces(); - LoadSettings(); - FixIncompatibleSettings(true); - UpdateLogging(); - - m_last_aspect_ratio = Settings::GetDisplayAspectRatioValue(g_settings.display_aspect_ratio); - return true; -} - -void LibretroHostInterface::Shutdown() -{ - HostInterface::Shutdown(); -} - -void LibretroHostInterface::ReportError(const char* message) -{ - AddFormattedOSDMessage(10.0f, "ERROR: %s", message); - Log_ErrorPrint(message); -} - -void LibretroHostInterface::ReportMessage(const char* message) -{ - AddOSDMessage(message, 5.0f); - Log_InfoPrint(message); -} - -bool LibretroHostInterface::ConfirmMessage(const char* message) -{ - Log_InfoPrintf("Confirm: %s", message); - return false; -} - -void LibretroHostInterface::GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) -{ - // Just use the filename for now... we don't have the game list. Unless we can pull this from the frontend somehow? - *title = System::GetTitleForPath(path); - *code = System::GetGameCodeForImage(image); -} - -static const char* GetSaveDirectory() -{ - const char* save_directory = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_directory) || !save_directory) - save_directory = "saves"; - - return save_directory; -} - -std::string LibretroHostInterface::GetSharedMemoryCardPath(u32 slot) const -{ - return StringUtil::StdStringFromFormat("%s" FS_OSPATH_SEPARATOR_STR "duckstation_shared_card_%d.mcd", - GetSaveDirectory(), slot + 1); -} - -std::string LibretroHostInterface::GetGameMemoryCardPath(const char* game_code, u32 slot) const -{ - return StringUtil::StdStringFromFormat("%s" FS_OSPATH_SEPARATOR_STR "%s_%d.mcd", GetSaveDirectory(), game_code, - slot + 1); -} - -std::string LibretroHostInterface::GetShaderCacheBasePath() const -{ - // Use the save directory, and failing that, the system directory. - const char* save_directory_ptr = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_directory_ptr) || !save_directory_ptr) - { - save_directory_ptr = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &save_directory_ptr) || - !save_directory_ptr) - { - Log_WarningPrint("No shader cache directory available, startup will be slower."); - return std::string(); - } - } - - // Use a directory named "duckstation_cache" in the save/system directory. - std::string shader_cache_path = StringUtil::StdStringFromFormat( - "%s" FS_OSPATH_SEPARATOR_STR "duckstation_cache" FS_OSPATH_SEPARATOR_STR, save_directory_ptr); - if (!FileSystem::DirectoryExists(shader_cache_path.c_str()) && - !FileSystem::CreateDirectory(shader_cache_path.c_str(), false)) - { - Log_ErrorPrintf("Failed to create shader cache directory: '%s'", shader_cache_path.c_str()); - return std::string(); - } - - Log_InfoPrintf("Shader cache directory: '%s'", shader_cache_path.c_str()); - return shader_cache_path; -} - -std::string LibretroHostInterface::GetStringSettingValue(const char* section, const char* key, - const char* default_value /*= ""*/) -{ - TinyString name; - name.Format("duckstation_%s.%s", section, key); - retro_variable var{name, default_value}; - if (g_retro_environment_callback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - return var.value; - else - return default_value; -} - -void LibretroHostInterface::AddOSDMessage(std::string message, float duration /*= 2.0f*/) -{ - if (!g_settings.display_show_osd_messages) - return; - - retro_message msg = {}; - msg.msg = message.c_str(); - msg.frames = static_cast(duration * (System::IsShutdown() ? 60.0f : System::GetThrottleFrequency())); - g_retro_environment_callback(RETRO_ENVIRONMENT_SET_MESSAGE, &msg); -} - -void LibretroHostInterface::retro_get_system_av_info(struct retro_system_av_info* info) -{ - const bool use_resolution_scale = (g_settings.gpu_renderer != GPURenderer::Software); - GetSystemAVInfo(info, use_resolution_scale); - - Log_InfoPrintf("base = %ux%u, max = %ux%u, aspect ratio = %.2f, fps = %.2f", info->geometry.base_width, - info->geometry.base_height, info->geometry.max_width, info->geometry.max_height, - info->geometry.aspect_ratio, info->timing.fps); -} - -void LibretroHostInterface::GetSystemAVInfo(struct retro_system_av_info* info, bool use_resolution_scale) -{ - const u32 resolution_scale = use_resolution_scale ? g_settings.gpu_resolution_scale : 1u; - Assert(System::IsValid()); - - std::memset(info, 0, sizeof(*info)); - - info->geometry.aspect_ratio = m_last_aspect_ratio; - info->geometry.base_width = 320; - info->geometry.base_height = 240; - info->geometry.max_width = VRAM_WIDTH * resolution_scale; - info->geometry.max_height = VRAM_HEIGHT * resolution_scale; - - info->timing.fps = System::GetThrottleFrequency(); - info->timing.sample_rate = static_cast(AUDIO_SAMPLE_RATE); -} - -bool LibretroHostInterface::UpdateSystemAVInfo(bool use_resolution_scale) -{ - struct retro_system_av_info avi; - GetSystemAVInfo(&avi, use_resolution_scale); - - Log_InfoPrintf("base = %ux%u, max = %ux%u, aspect ratio = %.2f, fps = %.2f", avi.geometry.base_width, - avi.geometry.base_height, avi.geometry.max_width, avi.geometry.max_height, avi.geometry.aspect_ratio, - avi.timing.fps); - - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &avi)) - { - Log_ErrorPrintf("Failed to update system AV info on resolution change"); - return false; - } - - return true; -} - -void LibretroHostInterface::UpdateGeometry() -{ - struct retro_system_av_info avi; - const bool use_resolution_scale = (g_settings.gpu_renderer != GPURenderer::Software); - GetSystemAVInfo(&avi, use_resolution_scale); - - Log_InfoPrintf("base = %ux%u, max = %ux%u, aspect ratio = %.2f", avi.geometry.base_width, avi.geometry.base_height, - avi.geometry.max_width, avi.geometry.max_height, avi.geometry.aspect_ratio); - - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_SET_GEOMETRY, &avi.geometry)) - Log_WarningPrint("RETRO_ENVIRONMENT_SET_GEOMETRY failed"); -} - -void LibretroHostInterface::UpdateLogging() -{ - Log::SetFilterLevel(g_settings.log_level); - - if (s_libretro_log_callback_valid) - Log::SetConsoleOutputParams(false); - else - Log::SetConsoleOutputParams(true, nullptr, g_settings.log_level); -} - -bool LibretroHostInterface::UpdateGameSettings() -{ - std::unique_ptr new_game_settings; - - if (!System::IsShutdown() && !System::GetRunningCode().empty()) - { - new_game_settings = GetSettingsForGame(System::GetRunningCode()); - if (new_game_settings) - Log_InfoPrintf("Game settings found for %s", System::GetRunningCode().c_str()); - } - - if (new_game_settings == m_game_settings) - return false; - - m_game_settings = std::move(new_game_settings); - return true; -} - -void LibretroHostInterface::ApplyGameSettings() -{ - if (!g_settings.apply_game_settings || !m_game_settings) - return; - - m_game_settings->ApplySettings(System::GetState() == System::State::Starting); -} - -bool LibretroHostInterface::retro_load_game(const struct retro_game_info* game) -{ - SystemBootParameters bp; - bp.filename = game->path; - bp.media_playlist_index = m_next_disc_index.value_or(0); - bp.force_software_renderer = !m_hw_render_callback_valid; - - struct retro_input_descriptor desc[] = { -#define JOYP(port) \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select"}, \ - {port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start"}, \ - {port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X"}, \ - {port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y"}, \ - {port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X"}, \ - {port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y"}, - - JOYP(0) JOYP(1) JOYP(2) JOYP(3) JOYP(4) JOYP(5) JOYP(6) JOYP(7) - - {0}, - }; - - g_retro_environment_callback(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); - - if (!BootSystem(bp)) - return false; - - if (g_settings.gpu_renderer != GPURenderer::Software) - { - if (!m_hw_render_callback_valid) - RequestHardwareRendererContext(); - else - SwitchToHardwareRenderer(); - } - - return true; -} - -void LibretroHostInterface::retro_run_frame() -{ - Assert(!System::IsShutdown()); - - if (HasCoreVariablesChanged()) - UpdateSettings(); - - UpdateControllers(); - - System::RunFrame(); - - const float aspect_ratio = m_display->GetDisplayAspectRatio(); - if (aspect_ratio != m_last_aspect_ratio) - { - m_last_aspect_ratio = aspect_ratio; - UpdateGeometry(); - } - - m_display->Render(); -} - -unsigned LibretroHostInterface::retro_get_region() -{ - return System::IsPALRegion() ? RETRO_REGION_PAL : RETRO_REGION_NTSC; -} - -size_t LibretroHostInterface::retro_serialize_size() -{ - return System::MAX_SAVE_STATE_SIZE; -} - -bool LibretroHostInterface::retro_serialize(void* data, size_t size) -{ - std::unique_ptr stream = ByteStream_CreateMemoryStream(data, static_cast(size)); - if (!System::SaveState(stream.get(), 0)) - { - Log_ErrorPrintf("Failed to save state to memory stream"); - return false; - } - - return true; -} - -bool LibretroHostInterface::retro_unserialize(const void* data, size_t size) -{ - std::unique_ptr stream = ByteStream_CreateReadOnlyMemoryStream(data, static_cast(size)); - if (!System::LoadState(stream.get(), false)) - { - Log_ErrorPrintf("Failed to load save state from memory stream"); - return false; - } - - return true; -} - -void* LibretroHostInterface::retro_get_memory_data(unsigned id) -{ - switch (id) - { - case RETRO_MEMORY_SYSTEM_RAM: - return System::IsShutdown() ? nullptr : Bus::g_ram; - - default: - return nullptr; - } -} - -size_t LibretroHostInterface::retro_get_memory_size(unsigned id) -{ - switch (id) - { - case RETRO_MEMORY_SYSTEM_RAM: - return Bus::RAM_SIZE; - - default: - return 0; - } -} - -void LibretroHostInterface::retro_cheat_reset() -{ - System::SetCheatList(nullptr); -} - -void LibretroHostInterface::retro_cheat_set(unsigned index, bool enabled, const char* code) -{ - CheatList* cl = System::GetCheatList(); - if (!cl) - { - System::SetCheatList(std::make_unique()); - cl = System::GetCheatList(); - } - - CheatCode cc; - cc.description = StringUtil::StdStringFromFormat("Cheat%u", index); - cc.enabled = true; - if (!CheatList::ParseLibretroCheat(&cc, code)) - Log_ErrorPrintf("Failed to parse cheat %u '%s'", index, code); - - cl->SetCode(index, std::move(cc)); -} - -bool LibretroHostInterface::AcquireHostDisplay() -{ - // start in software mode, switch to hardware later - m_display = std::make_unique(); - return true; -} - -void LibretroHostInterface::ReleaseHostDisplay() -{ - if (m_hw_render_display) - { - m_hw_render_display->DestroyRenderDevice(); - m_hw_render_display.reset(); - } - - m_display->DestroyRenderDevice(); - m_display.reset(); -} - -std::unique_ptr LibretroHostInterface::CreateAudioStream(AudioBackend backend) -{ - return std::make_unique(); -} - -void LibretroHostInterface::OnSystemDestroyed() -{ - HostInterface::OnSystemDestroyed(); - m_using_hardware_renderer = false; -} - -static std::array s_option_definitions = {{ - {"duckstation_Console.Region", - "Console Region", - "Determines which region/hardware to emulate. Auto-Detect will use the region of the disc inserted.", - {{"Auto", "Auto-Detect"}, - {"NTSC-J", "NTSC-J (Japan)"}, - {"NTSC-U", "NTSC-U/C (US, Canada)"}, - {"PAL", "PAL (Europe, Australia)"}}, - "Auto"}, - {"duckstation_BIOS.PatchFastBoot", - "Fast Boot", - "Skips the BIOS shell/intro, booting directly into the game. Usually safe to enable, but some games break.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_CDROM.RegionCheck", - "CD-ROM Region Check", - "Prevents discs from incorrect regions being read by the emulator. Usually safe to disable.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_CDROM.ReadThread", - "CD-ROM Read Thread", - "Reads CD-ROM sectors ahead asynchronously, reducing the risk of frame time spikes.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_CDROM.LoadImageToRAM", - "Preload CD-ROM Image To RAM", - "Loads the disc image to RAM before starting emulation. May reduce hitching if you are running off a network share, " - "at a cost of a greater startup time. As libretro provides no way to draw overlays, the emulator will appear to " - "lock up while the image is preloaded.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_CDROM.MuteCDAudio", - "Mute CD Audio", - "Forcibly mutes both CD-DA and XA audio from the CD-ROM. Can be used to disable background music in some games.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_CDROM.ReadSpeedup", - "CD-ROM Read Speedup", - "Speeds up CD-ROM reads by the specified factor. Only applies to double-speed reads, and is ignored when audio " - "is playing. May improve loading speeds in some games, at the cost of breaking others.", - {{"1", "None (Double Speed)"}, - {"2", "2x (Quad Speed)"}, - {"3", "3x (6x Speed)"}, - {"4", "4x (8x Speed)"}, - {"5", "5x (10x Speed)"}, - {"6", "6x (12x Speed)"}, - {"7", "7x (14x Speed)"}, - {"8", "8x (16x Speed)"}, - {"9", "9x (18x Speed)"}, - {"10", "10x (20x Speed)"}}, - "1"}, - {"duckstation_CPU.ExecutionMode", - "CPU Execution Mode", - "Which mode to use for CPU emulation. Recompiler provides the best performance.", - {{"Interpreter", "Interpreter"}, {"CachedIntepreter", "Cached Interpreter"}, {"Recompiler", "Recompiler"}}, - "Recompiler"}, - {"duckstation_CPU.Overclock", - "CPU Overclocking", - "Runs the emulated CPU faster or slower than native speed, which can improve framerates in some games. Will break " - "other games and increase system requirements, use with caution.", - {{"25", "25%"}, {"50", "50%"}, {"100", "100% (Default)"}, {"125", "125%"}, {"150", "150%"}, - {"175", "175%"}, {"200", "200%"}, {"225", "225%"}, {"250", "250%"}, {"275", "275%"}, - {"300", "300%"}, {"350", "350%"}, {"400", "400%"}, {"450", "450%"}, {"500", "500%"}, - {"600", "600%"}, {"700", "700%"}, {"800", "800%"}, {"900", "900%"}, {"1000", "1000%"}}, - "100"}, - {"duckstation_GPU.Renderer", - "GPU Renderer", - "Which renderer to use to emulate the GPU", - {{"Auto", "Hardware (Auto)"}, -#ifdef WIN32 - {"D3D11", "Hardware (D3D11)"}, -#endif - {"OpenGL", "Hardware (OpenGL)"}, - {"Vulkan", "Hardware (Vulkan)"}, - {"Software", "Software"}}, -#ifdef WIN32 - "D3D11" -#else - "OpenGL" -#endif - }, - {"duckstation_GPU.UseThread", - "Threaded Rendering (Software)", - "Uses a second thread for drawing graphics. Currently only available for the software renderer, but can provide a " - "significant speed improvement, and is safe to use.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_GPU.ResolutionScale", - "Internal Resolution Scale", - "Scales internal VRAM resolution by the specified multiplier. Larger values are slower. Some games require " - "1x VRAM resolution or they will have rendering issues.", - {{"1", "1x"}, - {"2", "2x"}, - {"3", "3x (for 720p)"}, - {"4", "4x"}, - {"5", "5x (for 1080p)"}, - {"6", "6x (for 1440p)"}, - {"7", "7x"}, - {"8", "8x"}, - {"9", "9x (for 4K)"}, - {"10", "10x"}, - {"11", "11x"}, - {"12", "12x"}, - {"13", "13x"}, - {"14", "14x"}, - {"15", "15x"}, - {"16", "16x"}}, - "1"}, - {"duckstation_GPU.MSAA", - "Multisample Antialiasing", - "Uses multisample antialiasing for rendering 3D objects. Can smooth out jagged edges on polygons at a lower " - "cost to performance compared to increasing the resolution scale, but may be more likely to cause rendering " - "errors in some games.", - {{"1", "Disabled"}, - {"2", "2x MSAA"}, - {"4", "4x MSAA"}, - {"8", "8x MSAA"}, - {"16", "16x MSAA"}, - {"32", "32x MSAA"}, - {"2-ssaa", "2x SSAA"}, - {"4-ssaa", "4x SSAA"}, - {"8-ssaa", "8x SSAA"}, - {"16-ssaa", "16x SSAA"}, - {"32-ssaa", "32x SSAA"}}, - "1"}, - {"duckstation_GPU.TrueColor", - "True Color Rendering", - "Disables dithering and uses the full 8 bits per channel of color information. May break rendering in some games.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.ScaledDithering", - "Scaled Dithering", - "Scales the dithering pattern with the internal rendering resolution, making it less noticeable. Usually safe to " - "enable.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_GPU.DisableInterlacing", - "Disable Interlacing", - "Disables interlaced rendering and display in the GPU. Some games can render in 480p this way, but others will " - "break.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.ForceNTSCTimings", - "Force NTSC Timings", - "Forces PAL games to run at NTSC timings, i.e. 60hz. Some PAL games will run at their \"normal\" speeds, while " - "others will break.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_Display.Force4_3For24Bit", - "Force 4:3 For 24-Bit Display", - "Switches back to 4:3 display aspect ratio when displaying 24-bit content, usually FMVs.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.ChromaSmoothing24Bit", - "Chroma Smoothing For 24-Bit Display", - "Smooths out blockyness between colour transitions in 24-bit content, usually FMVs. Only applies to the hardware " - "renderers.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.TextureFilter", - "Texture Filtering", - "Smooths out the blockyness of magnified textures on 3D object by using bilinear filtering. Will have a " - "greater effect on higher resolution scales. Only applies to the hardware renderers.", - {{"Nearest", "Nearest-Neighbor"}, - {"Bilinear", "Bilinear"}, - {"BilinearBinAlpha", "Bilinear (No Edge Blending)"}, - {"JINC2", "JINC2"}, - {"JINC2BinAlpha", "JINC2 (No Edge Blending)"}, - {"xBR", "xBR"}, - {"xBRBinAlpha", "xBR (No Edge Blending)"}}, - "Nearest"}, - {"duckstation_GPU.WidescreenHack", - "Widescreen Hack", - "Increases the field of view from 4:3 to the chosen display aspect ratio in 3D games. For 2D games, or games which " - "use pre-rendered backgrounds, this enhancement will not work as expected.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.PGXPEnable", - "PGXP Geometry Correction", - "Reduces \"wobbly\" polygons by attempting to preserve the fractional component through memory transfers. Only " - "works with the hardware renderers, and may not be compatible with all games.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.PGXPCulling", - "PGXP Culling Correction", - "Increases the precision of polygon culling, reducing the number of holes in geometry. Requires geometry correction " - "enabled.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_GPU.PGXPTextureCorrection", - "PGXP Texture Correction", - "Uses perspective-correct interpolation for texture coordinates and colors, straightening out warped textures. " - "Requires geometry correction enabled.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_GPU.PGXPDepthBuffer", - "PGXP Depth Buffer", - "Attempts to reduce polygon Z-fighting by testing pixels against the depth values from PGXP. Low compatibility, " - "but can work well in some games. Requires geometry correction enabled.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.PGXPVertexCache", - "PGXP Vertex Cache", - "Uses screen coordinates as a fallback when tracking vertices through memory fails. May improve PGXP compatibility.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.PGXPCPU", - "PGXP CPU Mode", - "Tries to track vertex manipulation through the CPU. Some games require this option for PGXP to be effective. " - "Very slow, and incompatible with the recompiler.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_Display.AspectRatio", - "Aspect Ratio", - "Sets the core-provided aspect ratio.", - {{"Auto", "Auto (Game Native)"}, - {"4:3", "4:3"}, - {"16:9", "16:9"}, - {"16:10", "16:10"}, - {"19:9", "19:9"}, - {"21:9", "21:9"}, - {"32:9", "32:9"}, - {"8:7", "8:7"}, - {"5:4", "5:4"}, - {"3:2", "3:2"}, - {"2:1 (VRAM 1:1)", "2:1 (VRAM 1:1)"}, - {"1:1", "1:1"}, - {"PAR 1:1", "PAR 1:1"}}, - "Auto"}, - {"duckstation_Display.CropMode", - "Crop Mode", - "Changes how much of the image is cropped. Some games display garbage in the overscan area which is typically " - "hidden.", - {{"None", "None"}, {"Overscan", "Only Overscan Area"}, {"Borders", "All Borders"}}, - "Overscan"}, - {"duckstation_GPU.DownsampleMode", - "Downsampling", - "Downsamples the rendered image prior to displaying it. Can improve overall image quality in mixed 2D/3D games, but " - "should be disabled for pure 3D games. Only applies to the hardware renderers.", - {{"Disabled", "Disabled"}, - {"Box", "Box (Downsample 3D/Smooth All)"}, - {"Adaptive", "Adaptive (Preserve 3D/Smooth 2D)"}}, - "Disabled"}, - {"duckstation_Main.LoadDevicesFromSaveStates", - "Load Devices From Save States", - "Sets whether the contents of devices and memory cards will be loaded when a save state is loaded.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_MemoryCards.Card1Type", - "Memory Card 1 Type", - "Sets the type of memory card for Slot 1.", - {{"None", "No Memory Card"}, - {"Shared", "Shared Between All Games"}, - {"PerGame", "Separate Card Per Game (Game Code)"}, - {"PerGameTitle", "Separate Card Per Game (Game Title)"}}, - "PerGameTitle"}, - {"duckstation_MemoryCards.Card2Type", - "Memory Card 2 Type", - "Sets the type of memory card for Slot 2.", - {{"None", "No Memory Card"}, - {"Shared", "Shared Between All Games"}, - {"PerGame", "Separate Card Per Game (Game Code)"}, - {"PerGameTitle", "Separate Card Per Game (Game Title)"}}, - "None"}, - {"duckstation_MemoryCards.UsePlaylistTitle", - "Use Single Card For Playlist", - "When using a playlist (m3u) and per-game (title) memory cards, a single memory card " - "will be used for all discs. If unchecked, a separate card will be used for each disc.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_Controller1.Type", - "Controller 1 Type", - "Sets the type of controller for Slot 1.", - {{"None", "None"}, - {"DigitalController", "Digital Controller"}, - {"AnalogController", "Analog Controller (DualShock)"}}, - "DigitalController"}, - {"duckstation_Controller1.ForceAnalogOnReset", - "Controller 1 Force Analog Mode on Reset", - "Forces analog mode in Analog Controller (DualShock) at start/reset. May cause issues with some games. Only use " - "this option for games that support analog mode but do not automatically enable it themselves.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_Controller1.AnalogDPadInDigitalMode", - "Controller 1 Use Analog Sticks for D-Pad in Digital Mode", - "Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_Controller1.AxisScale", - "Controller 1 Analog Axis Scale", - "Sets the analog stick axis scaling factor.", - {{"1.00f", "1.00"}, {"1.40f", "1.40"}}, - "1.00f"}, - {"duckstation_Controller2.Type", - "Controller 2 Type", - "Sets the type of controller for Slot 2.", - {{"None", "None"}, - {"DigitalController", "Digital Controller"}, - {"AnalogController", "Analog Controller (DualShock)"}}, - "None"}, - {"duckstation_Controller2.ForceAnalogOnReset", - "Controller 2 Force Analog Mode on Reset", - "Forces analog mode in Analog Controller (DualShock) at start/reset. May cause issues with some games. Only use " - "this option for games that support analog mode but do not automatically enable it themselves.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_Controller2.AnalogDPadInDigitalMode", - "Controller 2 Use Analog Sticks for D-Pad in Digital Mode", - "Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_Controller2.AxisScale", - "Controller 2 Analog Axis Scale", - "Sets the analog stick axis scaling factor.", - {{"1.00f", "1.00"}, {"1.40f", "1.40"}}, - "1.00f"}, - {"duckstation_Display.ShowOSDMessages", - "Display OSD Messages", - "Shows on-screen messages generated by the core.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_Main.ApplyGameSettings", - "Apply Compatibility Settings", - "Automatically disables enhancements on games which are incompatible.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "true"}, - {"duckstation_Logging.LogLevel", - "Log Level", - "Sets the level of information logged by the core.", - {{"None", "None"}, - {"Error", "Error"}, - {"Warning", "Warning"}, - {"Perf", "Performance"}, - {"Success", "Success"}, - {"Info", "Information"}, - {"Dev", "Developer"}, - {"Profile", "Profile"}, - {"Debug", "Debug"}, - {"Trace", "Trace"}}, - "Info"}, - {"duckstation_CPU.RecompilerICache", - "CPU Recompiler ICache", - "Determines whether the CPU's instruction cache is simulated in the recompiler. Improves accuracy at a small cost " - "to performance. If games are running too fast, try enabling this option.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_CPU.FastmemMode", - "CPU Recompiler Fast Memory Access", - "Uses page faults to determine hardware memory accesses at runtime. Can provide a significant performance " - "improvement in some games, but make the core more difficult to debug.", - {{"Disabled", "Disabled (Slowest)"}, {"MMap", "MMap (Hardware, Fastest, 64-Bit Only)"}, {"LUT", "LUT (Faster)"}}, -#if defined(CPU_X64) || defined(CPU_AARCH64) - "MMap" -#else - "LUT" -#endif - }, - {"duckstation_Display.LineStartOffset", - "Display Line Start Offset", - "Pads or crops off lines from the top of the displayed image.", - {{"-30", "-30"}, {"-29", "-29"}, {"-28", "-28"}, {"-27", "-27"}, {"-26", "-26"}, {"-25", "-25"}, {"-24", "-24"}, - {"-23", "-23"}, {"-22", "-22"}, {"-21", "-21"}, {"-20", "-20"}, {"-19", "-19"}, {"-18", "-18"}, {"-17", "-17"}, - {"-16", "-16"}, {"-15", "-15"}, {"-14", "-14"}, {"-13", "-13"}, {"-12", "-12"}, {"-11", "-11"}, {"-10", "-10"}, - {"-9", "-9"}, {"-8", "-8"}, {"-7", "-7"}, {"-6", "-6"}, {"-5", "-5"}, {"-4", "-4"}, {"-3", "-3"}, - {"-2", "-2"}, {"-1", "-1"}, {"0", "0"}, {"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"}, - {"5", "5"}, {"6", "6"}, {"7", "7"}, {"8", "8"}, {"9", "9"}, {"10", "10"}, {"11", "11"}, - {"12", "12"}, {"13", "13"}, {"14", "14"}, {"15", "15"}, {"16", "16"}, {"17", "17"}, {"18", "18"}, - {"19", "19"}, {"20", "20"}, {"21", "21"}, {"22", "22"}, {"23", "23"}, {"24", "24"}, {"25", "25"}, - {"26", "26"}, {"27", "27"}, {"28", "28"}, {"29", "29"}, {"30", "30"}}, - "0"}, - {"duckstation_Display.LineEndOffset", - "Display Line End Offset", - "Pads or crops off lines from the bottom of the displayed image.", - {{"-30", "-30"}, {"-29", "-29"}, {"-28", "-28"}, {"-27", "-27"}, {"-26", "-26"}, {"-25", "-25"}, {"-24", "-24"}, - {"-23", "-23"}, {"-22", "-22"}, {"-21", "-21"}, {"-20", "-20"}, {"-19", "-19"}, {"-18", "-18"}, {"-17", "-17"}, - {"-16", "-16"}, {"-15", "-15"}, {"-14", "-14"}, {"-13", "-13"}, {"-12", "-12"}, {"-11", "-11"}, {"-10", "-10"}, - {"-9", "-9"}, {"-8", "-8"}, {"-7", "-7"}, {"-6", "-6"}, {"-5", "-5"}, {"-4", "-4"}, {"-3", "-3"}, - {"-2", "-2"}, {"-1", "-1"}, {"0", "0"}, {"1", "1"}, {"2", "2"}, {"3", "3"}, {"4", "4"}, - {"5", "5"}, {"6", "6"}, {"7", "7"}, {"8", "8"}, {"9", "9"}, {"10", "10"}, {"11", "11"}, - {"12", "12"}, {"13", "13"}, {"14", "14"}, {"15", "15"}, {"16", "16"}, {"17", "17"}, {"18", "18"}, - {"19", "19"}, {"20", "20"}, {"21", "21"}, {"22", "22"}, {"23", "23"}, {"24", "24"}, {"25", "25"}, - {"26", "26"}, {"27", "27"}, {"28", "28"}, {"29", "29"}, {"30", "30"}}, - "0"}, - {"duckstation_GPU.PGXPPreserveProjFP", - "PGXP Preserve Projection Precision", - "Enables additional precision for PGXP. May improve visuals in some games but break others.", - {{"true", "Enabled"}, {"false", "Disabled"}}, - "false"}, - {"duckstation_GPU.PGXPTolerance", - "PGXP Geometry Tolerance", - "Ignores precise positions if the difference exceeds this threshold.", - { - {"-1.0", "None"}, {"0.5", "0.5 pixels"}, {"1.0", "1.0 pixels"}, {"1.5", "1.5 pixels"}, - {"2.0", "2.0 pixels"}, {"2.5", "2.5 pixels"}, {"3.0", "3.0 pixels"}, {"3.5", "3.5 pixels"}, - {"4.0", "4.0 pixels"}, {"4.5", "4.5 pixels"}, {"5.0", "5.0 pixels"}, {"5.5", "5.5 pixels"}, - {"6.0", "6.0 pixels"}, {"6.5", "6.5 pixels"}, {"7.0", "7.0 pixels"}, {"7.5", "7.5 pixels"}, - {"8.0", "8.0 pixels"}, {"8.5", "8.5 pixels"}, {"9.0", "9.0 pixels"}, {"9.5", "9.0 pixels"}, - {"10.0", "10.0 pixels"}, - - }, - "-1.0"}, - {}, -}}; - -bool LibretroHostInterface::SetCoreOptions() -{ - unsigned options_version = 0; - if (g_retro_environment_callback(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &options_version) && - options_version >= 1) - { - return g_retro_environment_callback(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &s_option_definitions); - } - - // use legacy options struct, which sucks. do we need to? - return false; -} - -bool LibretroHostInterface::HasCoreVariablesChanged() -{ - bool changed = false; - return (g_retro_environment_callback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &changed) && changed); -} - -std::string LibretroHostInterface::GetBIOSDirectory() -{ - // Assume BIOS files are located in system directory. - const char* system_directory = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_directory) || !system_directory) - return GetProgramDirectoryRelativePath("system"); - else - return system_directory; -} - -std::unique_ptr LibretroHostInterface::OpenPackageFile(const char* path, u32 flags) -{ - Log_ErrorPrintf("Ignoring request for package file '%s'", path); - return {}; -} - -void LibretroHostInterface::LoadSettings() -{ - LibretroSettingsInterface si; - HostInterface::LoadSettings(si); - - // turn percentage into fraction for overclock - const u32 overclock_percent = static_cast(std::max(si.GetIntValue("CPU", "Overclock", 100), 1)); - Settings::CPUOverclockPercentToFraction(overclock_percent, &g_settings.cpu_overclock_numerator, - &g_settings.cpu_overclock_denominator); - g_settings.cpu_overclock_enable = (overclock_percent != 100); - g_settings.UpdateOverclockActive(); - - // convert msaa settings - const std::string msaa = si.GetStringValue("GPU", "MSAA", "1"); - g_settings.gpu_multisamples = StringUtil::FromChars(msaa).value_or(1); - g_settings.gpu_per_sample_shading = StringUtil::EndsWith(msaa, "-ssaa"); - - // Ensure we don't use the standalone memcard directory in shared mode. - for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) - g_settings.memory_card_paths[i] = GetSharedMemoryCardPath(i); -} - -void LibretroHostInterface::UpdateSettings() -{ - Settings old_settings(std::move(g_settings)); - LoadSettings(); - ApplyGameSettings(); - FixIncompatibleSettings(false); - - if (System::IsValid()) - { - if (g_settings.gpu_resolution_scale != old_settings.gpu_resolution_scale && - g_settings.gpu_renderer != GPURenderer::Software) - { - ReportMessage("Resolution changed, updating system AV info..."); - - UpdateSystemAVInfo(true); - - if (!g_settings.IsUsingSoftwareRenderer()) - { - if (!m_hw_render_callback_valid) - RequestHardwareRendererContext(); - else if (!m_using_hardware_renderer) - SwitchToHardwareRenderer(); - } - - // Don't let the base class mess with the GPU. - old_settings.gpu_resolution_scale = g_settings.gpu_resolution_scale; - } - - if (g_settings.gpu_renderer != old_settings.gpu_renderer) - { - ReportFormattedMessage("Switch to %s renderer pending, please restart the core to apply.", - Settings::GetRendererDisplayName(g_settings.gpu_renderer)); - g_settings.gpu_renderer = old_settings.gpu_renderer; - } - } - - CheckForSettingsChanges(old_settings); -} - -void LibretroHostInterface::CheckForSettingsChanges(const Settings& old_settings) -{ - HostInterface::CheckForSettingsChanges(old_settings); - - if (g_settings.display_aspect_ratio != old_settings.display_aspect_ratio) - UpdateGeometry(); - - if (g_settings.log_level != old_settings.log_level) - UpdateLogging(); -} - -void LibretroHostInterface::OnRunningGameChanged() -{ - Log_InfoPrintf("Running game changed: %s (%s)", System::GetRunningCode().c_str(), System::GetRunningTitle().c_str()); - if (UpdateGameSettings()) - UpdateSettings(); -} - -void LibretroHostInterface::InitRumbleInterface() -{ - m_rumble_interface_valid = g_retro_environment_callback(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &m_rumble_interface); -} - -void LibretroHostInterface::UpdateControllers() -{ - g_retro_input_poll_callback(); - - for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) - { - switch (g_settings.controller_types[i]) - { - case ControllerType::None: - break; - - case ControllerType::DigitalController: - UpdateControllersDigitalController(i); - break; - - case ControllerType::AnalogController: - UpdateControllersAnalogController(i); - break; - - default: - ReportFormattedError("Unhandled controller type '%s'.", - Settings::GetControllerTypeDisplayName(g_settings.controller_types[i])); - break; - } - } -} - -void LibretroHostInterface::UpdateControllersDigitalController(u32 index) -{ - DigitalController* controller = static_cast(System::GetController(index)); - DebugAssert(controller); - - static constexpr std::array, 14> mapping = { - {{DigitalController::Button::Left, RETRO_DEVICE_ID_JOYPAD_LEFT}, - {DigitalController::Button::Right, RETRO_DEVICE_ID_JOYPAD_RIGHT}, - {DigitalController::Button::Up, RETRO_DEVICE_ID_JOYPAD_UP}, - {DigitalController::Button::Down, RETRO_DEVICE_ID_JOYPAD_DOWN}, - {DigitalController::Button::Circle, RETRO_DEVICE_ID_JOYPAD_A}, - {DigitalController::Button::Cross, RETRO_DEVICE_ID_JOYPAD_B}, - {DigitalController::Button::Triangle, RETRO_DEVICE_ID_JOYPAD_X}, - {DigitalController::Button::Square, RETRO_DEVICE_ID_JOYPAD_Y}, - {DigitalController::Button::Start, RETRO_DEVICE_ID_JOYPAD_START}, - {DigitalController::Button::Select, RETRO_DEVICE_ID_JOYPAD_SELECT}, - {DigitalController::Button::L1, RETRO_DEVICE_ID_JOYPAD_L}, - {DigitalController::Button::L2, RETRO_DEVICE_ID_JOYPAD_L2}, - {DigitalController::Button::R1, RETRO_DEVICE_ID_JOYPAD_R}, - {DigitalController::Button::R2, RETRO_DEVICE_ID_JOYPAD_R2}}}; - - if (m_supports_input_bitmasks) - { - const u16 active = g_retro_input_state_callback(index, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); - for (const auto& it : mapping) - controller->SetButtonState(it.first, (active & (static_cast(1u) << it.second)) != 0u); - } - else - { - for (const auto& it : mapping) - { - const int16_t state = g_retro_input_state_callback(index, RETRO_DEVICE_JOYPAD, 0, it.second); - controller->SetButtonState(it.first, state != 0); - } - } -} - -void LibretroHostInterface::UpdateControllersAnalogController(u32 index) -{ - AnalogController* controller = static_cast(System::GetController(index)); - DebugAssert(controller); - - static constexpr std::array, 16> button_mapping = { - {{AnalogController::Button::Left, RETRO_DEVICE_ID_JOYPAD_LEFT}, - {AnalogController::Button::Right, RETRO_DEVICE_ID_JOYPAD_RIGHT}, - {AnalogController::Button::Up, RETRO_DEVICE_ID_JOYPAD_UP}, - {AnalogController::Button::Down, RETRO_DEVICE_ID_JOYPAD_DOWN}, - {AnalogController::Button::Circle, RETRO_DEVICE_ID_JOYPAD_A}, - {AnalogController::Button::Cross, RETRO_DEVICE_ID_JOYPAD_B}, - {AnalogController::Button::Triangle, RETRO_DEVICE_ID_JOYPAD_X}, - {AnalogController::Button::Square, RETRO_DEVICE_ID_JOYPAD_Y}, - {AnalogController::Button::Start, RETRO_DEVICE_ID_JOYPAD_START}, - {AnalogController::Button::Select, RETRO_DEVICE_ID_JOYPAD_SELECT}, - {AnalogController::Button::L1, RETRO_DEVICE_ID_JOYPAD_L}, - {AnalogController::Button::L2, RETRO_DEVICE_ID_JOYPAD_L2}, - {AnalogController::Button::L3, RETRO_DEVICE_ID_JOYPAD_L3}, - {AnalogController::Button::R1, RETRO_DEVICE_ID_JOYPAD_R}, - {AnalogController::Button::R2, RETRO_DEVICE_ID_JOYPAD_R2}, - {AnalogController::Button::R3, RETRO_DEVICE_ID_JOYPAD_R3}}}; - - static constexpr std::array>, 4> axis_mapping = { - {{AnalogController::Axis::LeftX, {RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X}}, - {AnalogController::Axis::LeftY, {RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y}}, - {AnalogController::Axis::RightX, {RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X}}, - {AnalogController::Axis::RightY, {RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y}}}}; - - if (m_supports_input_bitmasks) - { - const u16 active = g_retro_input_state_callback(index, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); - for (const auto& it : button_mapping) - controller->SetButtonState(it.first, (active & (static_cast(1u) << it.second)) != 0u); - } - else - { - for (const auto& it : button_mapping) - { - const int16_t state = g_retro_input_state_callback(index, RETRO_DEVICE_JOYPAD, 0, it.second); - controller->SetButtonState(it.first, state != 0); - } - } - - for (const auto& it : axis_mapping) - { - const int16_t state = g_retro_input_state_callback(index, RETRO_DEVICE_ANALOG, it.second.first, it.second.second); - controller->SetAxisState(static_cast(it.first), std::clamp(static_cast(state) / 32767.0f, -1.0f, 1.0f)); - } - - if (m_rumble_interface_valid) - { - const u16 strong = static_cast(static_cast(controller->GetVibrationMotorStrength(0) * 65535.0f)); - const u16 weak = static_cast(static_cast(controller->GetVibrationMotorStrength(1) * 65535.0f)); - m_rumble_interface.set_rumble_state(index, RETRO_RUMBLE_STRONG, strong); - m_rumble_interface.set_rumble_state(index, RETRO_RUMBLE_WEAK, weak); - } -} - -static std::optional RetroHwContextToRenderer(retro_hw_context_type type) -{ - switch (type) - { - case RETRO_HW_CONTEXT_OPENGL: - case RETRO_HW_CONTEXT_OPENGL_CORE: - case RETRO_HW_CONTEXT_OPENGLES3: - case RETRO_HW_CONTEXT_OPENGLES_VERSION: - return GPURenderer::HardwareOpenGL; - - case RETRO_HW_CONTEXT_VULKAN: - return GPURenderer::HardwareVulkan; - -#ifdef WIN32 - case RETRO_HW_CONTEXT_DIRECT3D: - return GPURenderer::HardwareD3D11; -#endif - - default: - return std::nullopt; - } -} - -static std::optional RenderAPIToRenderer(HostDisplay::RenderAPI api) -{ - switch (api) - { - case HostDisplay::RenderAPI::OpenGL: - case HostDisplay::RenderAPI::OpenGLES: - return GPURenderer::HardwareOpenGL; - - case HostDisplay::RenderAPI::Vulkan: - return GPURenderer::HardwareVulkan; - -#ifdef WIN32 - case HostDisplay::RenderAPI::D3D11: - return GPURenderer::HardwareD3D11; -#endif - - default: - return std::nullopt; - } -} - -bool LibretroHostInterface::RequestHardwareRendererContext() -{ - retro_variable renderer_variable{"duckstation_GPU.Renderer", - Settings::GetRendererName(Settings::DEFAULT_GPU_RENDERER)}; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_VARIABLE, &renderer_variable) || !renderer_variable.value) - renderer_variable.value = Settings::GetRendererName(Settings::DEFAULT_GPU_RENDERER); - - GPURenderer renderer = Settings::ParseRendererName(renderer_variable.value).value_or(Settings::DEFAULT_GPU_RENDERER); - unsigned preferred_renderer = 0; - g_retro_environment_callback(RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER, &preferred_renderer); - if (std::strcmp(renderer_variable.value, "Auto") == 0) - { - std::optional preferred_gpu_renderer = - RetroHwContextToRenderer(static_cast(preferred_renderer)); - if (preferred_gpu_renderer.has_value()) - renderer = preferred_gpu_renderer.value(); - } - - Log_InfoPrintf("Renderer = %s", Settings::GetRendererName(renderer)); - if (renderer == GPURenderer::Software) - { - m_hw_render_callback_valid = false; - return false; - } - - Log_InfoPrintf("Requesting hardware renderer context for %s", Settings::GetRendererName(renderer)); - - m_hw_render_callback = {}; - m_hw_render_callback.context_reset = HardwareRendererContextReset; - m_hw_render_callback.context_destroy = HardwareRendererContextDestroy; - - switch (renderer) - { -#ifdef WIN32 - case GPURenderer::HardwareD3D11: - m_hw_render_callback_valid = LibretroD3D11HostDisplay::RequestHardwareRendererContext(&m_hw_render_callback); - break; -#endif - - case GPURenderer::HardwareVulkan: - m_hw_render_callback_valid = LibretroVulkanHostDisplay::RequestHardwareRendererContext(&m_hw_render_callback); - break; - - case GPURenderer::HardwareOpenGL: - { - const bool prefer_gles = - (preferred_renderer == RETRO_HW_CONTEXT_OPENGLES2 || preferred_renderer == RETRO_HW_CONTEXT_OPENGLES_VERSION); - m_hw_render_callback_valid = - LibretroOpenGLHostDisplay::RequestHardwareRendererContext(&m_hw_render_callback, prefer_gles); - } - break; - - default: - Log_ErrorPrintf("Unhandled renderer %s", Settings::GetRendererName(renderer)); - m_hw_render_callback_valid = false; - break; - } - - return m_hw_render_callback_valid; -} - -void LibretroHostInterface::HardwareRendererContextReset() -{ - Log_InfoPrintf("Hardware context reset, type = %u", - static_cast(g_libretro_host_interface.m_hw_render_callback.context_type)); - - g_libretro_host_interface.m_hw_render_callback_valid = true; - g_libretro_host_interface.SwitchToHardwareRenderer(); -} - -void LibretroHostInterface::SwitchToHardwareRenderer() -{ - struct retro_system_av_info avi; - g_libretro_host_interface.GetSystemAVInfo(&avi, true); - - WindowInfo wi; - wi.type = WindowInfo::Type::Libretro; - wi.display_connection = &g_libretro_host_interface.m_hw_render_callback; - wi.surface_width = avi.geometry.base_width; - wi.surface_height = avi.geometry.base_height; - wi.surface_scale = 1.0f; - - // use the existing device if we just resized the window - std::optional renderer; - std::unique_ptr display = std::move(m_hw_render_display); - if (display) - { - Log_InfoPrintf("Using existing hardware display"); - renderer = RenderAPIToRenderer(display->GetRenderAPI()); - if (!display->ChangeRenderWindow(wi) || !display->CreateResources()) - { - Log_ErrorPrintf("Failed to recreate resources after reinit"); - display->DestroyRenderDevice(); - display.reset(); - } - } - - if (!display) - { - renderer = RetroHwContextToRenderer(m_hw_render_callback.context_type); - if (!renderer.has_value()) - { - Log_ErrorPrintf("Unknown context type %u", static_cast(m_hw_render_callback.context_type)); - return; - } - - switch (renderer.value()) - { - case GPURenderer::HardwareOpenGL: - display = std::make_unique(); - break; - - case GPURenderer::HardwareVulkan: - display = std::make_unique(); - break; - -#ifdef WIN32 - case GPURenderer::HardwareD3D11: - display = std::make_unique(); - break; -#endif - - default: - Log_ErrorPrintf("Unhandled renderer '%s'", Settings::GetRendererName(renderer.value())); - return; - } - if (!display || !display->CreateRenderDevice(wi, {}, g_settings.gpu_use_debug_device, false) || - !display->InitializeRenderDevice(GetShaderCacheBasePath(), g_settings.gpu_use_debug_device, false)) - { - Log_ErrorPrintf("Failed to create hardware host display"); - return; - } - } - - std::swap(display, g_libretro_host_interface.m_display); - System::RecreateGPU(renderer.value()); - display->DestroyRenderDevice(); - m_using_hardware_renderer = true; -} - -void LibretroHostInterface::HardwareRendererContextDestroy() -{ - Log_InfoPrintf("Hardware context destroyed"); - - // switch back to software - if (g_libretro_host_interface.m_using_hardware_renderer) - g_libretro_host_interface.SwitchToSoftwareRenderer(); - - if (g_libretro_host_interface.m_hw_render_display) - { - g_libretro_host_interface.m_hw_render_display->DestroyRenderDevice(); - g_libretro_host_interface.m_hw_render_display.reset(); - } - - g_libretro_host_interface.m_hw_render_callback_valid = false; -} - -void LibretroHostInterface::SwitchToSoftwareRenderer() -{ - Log_InfoPrintf("Switching to software renderer"); - - // keep the hw renderer around in case we need it later - // but keep it active until we've recreated the GPU so we can save the state - std::unique_ptr save_display; - if (m_using_hardware_renderer) - { - save_display = std::move(m_display); - m_using_hardware_renderer = false; - } - - m_display = std::make_unique(); - System::RecreateGPU(GPURenderer::Software, false); - - if (save_display) - { - save_display->DestroyResources(); - m_hw_render_display = std::move(save_display); - } -} - -bool LibretroHostInterface::DiskControlSetEjectState(bool ejected) -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlSetEjectState() - no system"); - return false; - } - - Log_DevPrintf("DiskControlSetEjectState(%u)", static_cast(ejected)); - - if (ejected) - { - if (!System::HasMedia()) - return false; - - System::RemoveMedia(); - return true; - } - else - { - const u32 image_to_insert = P_THIS->m_next_disc_index.value_or(0); - Log_DevPrintf("Inserting image %u", image_to_insert); - return System::SwitchMediaFromPlaylist(image_to_insert); - } -} - -bool LibretroHostInterface::DiskControlGetEjectState() -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlGetEjectState() - no system"); - return false; - } - - Log_DevPrintf("DiskControlGetEjectState() -> %u", static_cast(System::HasMedia())); - return System::HasMedia(); -} - -unsigned LibretroHostInterface::DiskControlGetImageIndex() -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlGetImageIndex() - no system"); - return false; - } - - const u32 index = P_THIS->m_next_disc_index.value_or(System::GetMediaPlaylistIndex()); - Log_DevPrintf("DiskControlGetImageIndex() -> %u", index); - return index; -} - -bool LibretroHostInterface::DiskControlSetImageIndex(unsigned index) -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlSetImageIndex() - no system"); - return false; - } - - Log_DevPrintf("DiskControlSetImageIndex(%u)", index); - - if (index >= System::GetMediaPlaylistCount()) - return false; - - P_THIS->m_next_disc_index = index; - return true; -} - -unsigned LibretroHostInterface::DiskControlGetNumImages() -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlGetNumImages() - no system"); - return false; - } - - Log_DevPrintf("DiskControlGetNumImages() -> %u", System::GetMediaPlaylistCount()); - return static_cast(System::GetMediaPlaylistCount()); -} - -bool LibretroHostInterface::DiskControlReplaceImageIndex(unsigned index, const retro_game_info* info) -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlReplaceImageIndex() - no system"); - return false; - } - - Log_DevPrintf("DiskControlReplaceImageIndex(%u, %s)", index, info ? info->path : "null"); - if (info && info->path) - return System::ReplaceMediaPathFromPlaylist(index, info->path); - else - return System::RemoveMediaPathFromPlaylist(index); -} - -bool LibretroHostInterface::DiskControlAddImageIndex() -{ - if (System::IsShutdown()) - { - Log_ErrorPrintf("DiskControlAddImageIndex() - no system"); - return false; - } - - Log_DevPrintf("DiskControlAddImageIndex() -> %zu", System::GetMediaPlaylistCount()); - System::AddMediaPathToPlaylist({}); - return true; -} - -bool LibretroHostInterface::DiskControlSetInitialImage(unsigned index, const char* path) -{ - Log_DevPrintf("DiskControlSetInitialImage(%u, %s)", index, path); - P_THIS->m_next_disc_index = index; - return true; -} - -bool LibretroHostInterface::DiskControlGetImagePath(unsigned index, char* path, size_t len) -{ - if (System::IsShutdown() || index >= System::GetMediaPlaylistCount()) - return false; - - const std::string& image_path = System::GetMediaPlaylistPath(index); - Log_DevPrintf("DiskControlGetImagePath(%u) -> %s", index, image_path.c_str()); - if (image_path.empty()) - return false; - - StringUtil::Strlcpy(path, image_path.c_str(), len); - return true; -} - -bool LibretroHostInterface::DiskControlGetImageLabel(unsigned index, char* label, size_t len) -{ - if (System::IsShutdown() || index >= System::GetMediaPlaylistCount()) - return false; - - const std::string& image_path = System::GetMediaPlaylistPath(index); - if (image_path.empty()) - return false; - - const std::string_view title = System::GetTitleForPath(label); - StringUtil::Strlcpy(label, title, len); - Log_DevPrintf("DiskControlGetImagePath(%u) -> %s", index, label); - return true; -} - -void LibretroHostInterface::InitDiskControlInterface() -{ - unsigned version = 0; - if (g_retro_environment_callback(RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION, &version) && version >= 1) - { - retro_disk_control_ext_callback ext_cb = { - &LibretroHostInterface::DiskControlSetEjectState, &LibretroHostInterface::DiskControlGetEjectState, - &LibretroHostInterface::DiskControlGetImageIndex, &LibretroHostInterface::DiskControlSetImageIndex, - &LibretroHostInterface::DiskControlGetNumImages, &LibretroHostInterface::DiskControlReplaceImageIndex, - &LibretroHostInterface::DiskControlAddImageIndex, &LibretroHostInterface::DiskControlSetInitialImage, - &LibretroHostInterface::DiskControlGetImagePath, &LibretroHostInterface::DiskControlGetImageLabel}; - if (g_retro_environment_callback(RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE, &ext_cb)) - return; - } - - retro_disk_control_callback cb = { - &LibretroHostInterface::DiskControlSetEjectState, &LibretroHostInterface::DiskControlGetEjectState, - &LibretroHostInterface::DiskControlGetImageIndex, &LibretroHostInterface::DiskControlSetImageIndex, - &LibretroHostInterface::DiskControlGetNumImages, &LibretroHostInterface::DiskControlReplaceImageIndex, - &LibretroHostInterface::DiskControlAddImageIndex}; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &cb)) - Log_WarningPrint("Failed to set disk control interface"); -} diff --git a/src/duckstation-libretro/libretro_host_interface.h b/src/duckstation-libretro/libretro_host_interface.h deleted file mode 100644 index 6dc71e1cb..000000000 --- a/src/duckstation-libretro/libretro_host_interface.h +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once -#include "core/host_interface.h" -#include "core/system.h" -#include "libretro.h" -#include -#include -#include - -namespace GameSettings -{ -struct Entry; -} - -class LibretroHostInterface : public HostInterface -{ -public: - LibretroHostInterface(); - ~LibretroHostInterface() override; - - ALWAYS_INLINE u32 GetResolutionScale() const { return g_settings.gpu_resolution_scale; } - - bool Initialize() override; - void Shutdown() override; - - void ReportError(const char* message) override; - void ReportMessage(const char* message) override; - bool ConfirmMessage(const char* message) override; - void AddOSDMessage(std::string message, float duration = 2.0f) override; - - void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) override; - std::string GetSharedMemoryCardPath(u32 slot) const override; - std::string GetGameMemoryCardPath(const char* game_code, u32 slot) const override; - std::string GetShaderCacheBasePath() const override; - std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") override; - std::string GetBIOSDirectory() override; - std::unique_ptr OpenPackageFile(const char* path, u32 flags) override; - - bool UpdateSystemAVInfo(bool use_resolution_scale); - - // Called by frontend - void retro_set_environment(); - void retro_get_system_av_info(struct retro_system_av_info* info); - bool retro_load_game(const struct retro_game_info* game); - void retro_run_frame(); - unsigned retro_get_region(); - size_t retro_serialize_size(); - bool retro_serialize(void* data, size_t size); - bool retro_unserialize(const void* data, size_t size); - void* retro_get_memory_data(unsigned id); - size_t retro_get_memory_size(unsigned id); - void retro_cheat_reset(); - void retro_cheat_set(unsigned index, bool enabled, const char* code); - -protected: - bool AcquireHostDisplay() override; - void ReleaseHostDisplay() override; - std::unique_ptr CreateAudioStream(AudioBackend backend) override; - void OnSystemDestroyed() override; - void CheckForSettingsChanges(const Settings& old_settings) override; - void OnRunningGameChanged() override; - -private: - bool SetCoreOptions(); - bool HasCoreVariablesChanged(); - void InitInterfaces(); - void InitLogging(); - void InitDiskControlInterface(); - void InitRumbleInterface(); - - void LoadSettings() override; - void UpdateSettings(); - void UpdateControllers(); - void UpdateControllersDigitalController(u32 index); - void UpdateControllersAnalogController(u32 index); - void GetSystemAVInfo(struct retro_system_av_info* info, bool use_resolution_scale); - void UpdateGeometry(); - void UpdateLogging(); - - bool UpdateGameSettings(); - void ApplyGameSettings(); - - // Hardware renderer setup. - bool RequestHardwareRendererContext(); - void SwitchToHardwareRenderer(); - void SwitchToSoftwareRenderer(); - - static void HardwareRendererContextReset(); - static void HardwareRendererContextDestroy(); - - // Disk control callbacks - static bool RETRO_CALLCONV DiskControlSetEjectState(bool ejected); - static bool RETRO_CALLCONV DiskControlGetEjectState(); - static unsigned RETRO_CALLCONV DiskControlGetImageIndex(); - static bool RETRO_CALLCONV DiskControlSetImageIndex(unsigned index); - static unsigned RETRO_CALLCONV DiskControlGetNumImages(); - static bool RETRO_CALLCONV DiskControlReplaceImageIndex(unsigned index, const retro_game_info* info); - static bool RETRO_CALLCONV DiskControlAddImageIndex(); - static bool RETRO_CALLCONV DiskControlSetInitialImage(unsigned index, const char* path); - static bool RETRO_CALLCONV DiskControlGetImagePath(unsigned index, char* path, size_t len); - static bool RETRO_CALLCONV DiskControlGetImageLabel(unsigned index, char* label, size_t len); - - std::unique_ptr m_game_settings; - float m_last_aspect_ratio = 4.0f / 3.0f; - - retro_hw_render_callback m_hw_render_callback = {}; - std::unique_ptr m_hw_render_display; - bool m_hw_render_callback_valid = false; - bool m_using_hardware_renderer = false; - std::optional m_next_disc_index; - - retro_rumble_interface m_rumble_interface = {}; - bool m_rumble_interface_valid = false; - bool m_supports_input_bitmasks = false; -}; - -extern LibretroHostInterface g_libretro_host_interface; - -// libretro callbacks -extern retro_environment_t g_retro_environment_callback; -extern retro_video_refresh_t g_retro_video_refresh_callback; -extern retro_audio_sample_t g_retro_audio_sample_callback; -extern retro_audio_sample_batch_t g_retro_audio_sample_batch_callback; -extern retro_input_poll_t g_retro_input_poll_callback; -extern retro_input_state_t g_retro_input_state_callback; diff --git a/src/duckstation-libretro/libretro_opengl_host_display.cpp b/src/duckstation-libretro/libretro_opengl_host_display.cpp deleted file mode 100644 index ffe4da213..000000000 --- a/src/duckstation-libretro/libretro_opengl_host_display.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include "libretro_opengl_host_display.h" -#include "common/assert.h" -#include "common/log.h" -#include "core/gpu.h" -#include "libretro.h" -#include "libretro_host_interface.h" -#include -#include -Log_SetChannel(LibretroOpenGLHostDisplay); - -LibretroOpenGLHostDisplay::LibretroOpenGLHostDisplay() = default; - -LibretroOpenGLHostDisplay::~LibretroOpenGLHostDisplay() = default; - -HostDisplay::RenderAPI LibretroOpenGLHostDisplay::GetRenderAPI() const -{ - return m_is_gles ? HostDisplay::RenderAPI::OpenGLES : HostDisplay::RenderAPI::OpenGL; -} - -void LibretroOpenGLHostDisplay::SetVSync(bool enabled) -{ - // The libretro frontend controls this. - Log_DevPrintf("Ignoring SetVSync(%u)", BoolToUInt32(enabled)); -} - -static bool TryDesktopVersions(retro_hw_render_callback* cb) -{ - static constexpr std::array, 11> desktop_versions_to_try = { - {/*{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, */ {3, 3}, {3, 2}, {3, 1}, {3, 0}}}; - - for (const auto& [major, minor] : desktop_versions_to_try) - { - if (major > 3 || (major == 3 && minor >= 2)) - { - cb->context_type = RETRO_HW_CONTEXT_OPENGL_CORE; - cb->version_major = major; - cb->version_minor = minor; - } - else - { - cb->context_type = RETRO_HW_CONTEXT_OPENGL; - cb->version_major = 0; - cb->version_minor = 0; - } - - if (g_retro_environment_callback(RETRO_ENVIRONMENT_SET_HW_RENDER, cb)) - return true; - } - - return false; -} - -static bool TryESVersions(retro_hw_render_callback* cb) -{ - static constexpr std::array, 4> es_versions_to_try = {{{3, 2}, {3, 1}, {3, 0}}}; - - for (const auto& [major, minor] : es_versions_to_try) - { - if (major >= 3 && minor > 0) - { - cb->context_type = RETRO_HW_CONTEXT_OPENGLES_VERSION; - cb->version_major = major; - cb->version_minor = minor; - } - else - { - cb->context_type = RETRO_HW_CONTEXT_OPENGLES3; - cb->version_major = 0; - cb->version_minor = 0; - } - - if (g_retro_environment_callback(RETRO_ENVIRONMENT_SET_HW_RENDER, cb)) - return true; - } - - return false; -} - -bool LibretroOpenGLHostDisplay::RequestHardwareRendererContext(retro_hw_render_callback* cb, bool prefer_gles) -{ - // Prefer a desktop OpenGL context where possible. If we can't get this, try OpenGL ES. - cb->cache_context = false; - cb->bottom_left_origin = true; - - if (!prefer_gles) - { - if (TryDesktopVersions(cb) || TryESVersions(cb)) - return true; - } - else - { - if (TryESVersions(cb) || TryDesktopVersions(cb)) - return true; - } - - Log_ErrorPrint("Failed to set any GL HW renderer"); - return false; -} - -bool LibretroOpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, - bool debug_device, bool threaded_presentation) -{ - Assert(wi.type == WindowInfo::Type::Libretro); - - // gross - but can't do much because of the GLADloadproc below. - static retro_hw_render_callback* cb; - cb = static_cast(wi.display_connection); - - m_window_info = wi; - m_is_gles = (cb->context_type == RETRO_HW_CONTEXT_OPENGLES3 || cb->context_type == RETRO_HW_CONTEXT_OPENGLES_VERSION); - - const GLADloadproc get_proc_address = [](const char* sym) -> void* { - return reinterpret_cast(cb->get_proc_address(sym)); - }; - - // Load GLAD. - const auto load_result = m_is_gles ? gladLoadGLES2Loader(get_proc_address) : gladLoadGLLoader(get_proc_address); - if (!load_result) - { - Log_ErrorPrintf("Failed to load GL functions"); - return false; - } - - return true; -} - -void LibretroOpenGLHostDisplay::DestroyRenderDevice() -{ - DestroyResources(); -} - -void LibretroOpenGLHostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_height) -{ - m_window_info.surface_width = static_cast(new_window_width); - m_window_info.surface_height = static_cast(new_window_height); -} - -bool LibretroOpenGLHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi) -{ - m_window_info = new_wi; - return true; -} - -bool LibretroOpenGLHostDisplay::Render() -{ - const GLuint fbo = static_cast( - static_cast(m_window_info.display_connection)->get_current_framebuffer()); - const u32 resolution_scale = g_libretro_host_interface.GetResolutionScale(); - const u32 display_width = static_cast(m_display_width) * resolution_scale; - const u32 display_height = static_cast(m_display_height) * resolution_scale; - - glEnable(GL_SCISSOR_TEST); - glScissor(0, 0, display_width, display_height); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - if (HasDisplayTexture()) - { - const auto [left, top, width, height] = CalculateDrawRect(display_width, display_height, 0, false); - RenderDisplay(left, top, width, height, m_display_texture_handle, m_display_texture_width, m_display_texture_height, - m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width, - m_display_texture_view_height, m_display_linear_filtering); - } - - if (HasSoftwareCursor()) - { - // TODO: Scale mouse x/y - const auto [left, top, width, height] = CalculateSoftwareCursorDrawRect(m_mouse_position_x, m_mouse_position_y); - RenderSoftwareCursor(left, display_height - top - height, width, height, m_cursor_texture.get()); - } - - g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, display_width, display_height, 0); - - GL::Program::ResetLastProgram(); - return true; -} diff --git a/src/duckstation-libretro/libretro_opengl_host_display.h b/src/duckstation-libretro/libretro_opengl_host_display.h deleted file mode 100644 index 9bd74f37d..000000000 --- a/src/duckstation-libretro/libretro_opengl_host_display.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "common/gl/program.h" -#include "common/gl/texture.h" -#include "core/host_display.h" -#include "frontend-common/opengl_host_display.h" -#include "libretro.h" -#include -#include - -class LibretroOpenGLHostDisplay final : public FrontendCommon::OpenGLHostDisplay -{ -public: - LibretroOpenGLHostDisplay(); - ~LibretroOpenGLHostDisplay(); - - static bool RequestHardwareRendererContext(retro_hw_render_callback* cb, bool prefer_gles); - - RenderAPI GetRenderAPI() const override; - - bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device, - bool threaded_presentation) override; - void DestroyRenderDevice() override; - - void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) override; - bool ChangeRenderWindow(const WindowInfo& new_wi) override; - - void SetVSync(bool enabled) override; - - bool Render() override; - -private: - bool m_is_gles = false; -}; diff --git a/src/duckstation-libretro/libretro_settings_interface.cpp b/src/duckstation-libretro/libretro_settings_interface.cpp deleted file mode 100644 index ea1d7fd99..000000000 --- a/src/duckstation-libretro/libretro_settings_interface.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "libretro_settings_interface.h" -#include "common/log.h" -#include "common/string_util.h" -#include "libretro_host_interface.h" -#include -Log_SetChannel(LibretroSettingsInterface); - -template -static T GetVariable(const char* section, const char* key, DefaultValueType default_value) -{ - - TinyString full_key; - full_key.Format("duckstation_%s.%s", section, key); - - retro_variable rv = {full_key.GetCharArray(), nullptr}; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_VARIABLE, &rv) || !rv.value) - return T(default_value); - - if constexpr (std::is_same_v) - { - return T(rv.value); - } - else if constexpr (std::is_same_v) - { - return (StringUtil::Strcasecmp(rv.value, "true") == 0 || StringUtil::Strcasecmp(rv.value, "1") == 0); - } - else if constexpr (std::is_same_v) - { - return std::strtof(rv.value, nullptr); - } - else - { - std::optional parsed = StringUtil::FromChars(rv.value); - if (!parsed.has_value()) - return T(default_value); - - return parsed.value(); - } -} - -void LibretroSettingsInterface::Clear() -{ - Log_WarningPrintf("Clear not implemented"); -} - -int LibretroSettingsInterface::GetIntValue(const char* section, const char* key, int default_value /*= 0*/) -{ - return GetVariable(section, key, default_value); -} - -float LibretroSettingsInterface::GetFloatValue(const char* section, const char* key, float default_value /*= 0.0f*/) -{ - return GetVariable(section, key, default_value); -} - -bool LibretroSettingsInterface::GetBoolValue(const char* section, const char* key, bool default_value /*= false*/) -{ - return GetVariable(section, key, default_value); -} - -std::string LibretroSettingsInterface::GetStringValue(const char* section, const char* key, - const char* default_value /*= ""*/) -{ - return GetVariable(section, key, default_value); -} - -void LibretroSettingsInterface::SetIntValue(const char* section, const char* key, int value) -{ - Log_ErrorPrintf("SetIntValue(\"%s\", \"%s\", %d) not implemented", section, key, value); -} - -void LibretroSettingsInterface::SetFloatValue(const char* section, const char* key, float value) -{ - Log_ErrorPrintf("SetFloatValue(\"%s\", \"%s\", %f) not implemented", section, key, value); -} - -void LibretroSettingsInterface::SetBoolValue(const char* section, const char* key, bool value) -{ - Log_ErrorPrintf("SetBoolValue(\"%s\", \"%s\", %u) not implemented", section, key, static_cast(value)); -} - -void LibretroSettingsInterface::SetStringValue(const char* section, const char* key, const char* value) -{ - Log_ErrorPrintf("SetStringValue(\"%s\", \"%s\", \"%s\") not implemented", section, key, value); -} - -std::vector LibretroSettingsInterface::GetStringList(const char* section, const char* key) -{ - std::string value = GetVariable(section, key, ""); - if (value.empty()) - return {}; - - return std::vector({std::move(value)}); -} - -void LibretroSettingsInterface::SetStringList(const char* section, const char* key, - const std::vector& items) -{ - Log_ErrorPrintf("SetStringList(\"%s\", \"%s\") not implemented", section, key); -} - -bool LibretroSettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item) -{ - Log_ErrorPrintf("RemoveFromStringList(\"%s\", \"%s\", \"%s\") not implemented", section, key, item); - return false; -} - -bool LibretroSettingsInterface::AddToStringList(const char* section, const char* key, const char* item) -{ - Log_ErrorPrintf("AddToStringList(\"%s\", \"%s\", \"%s\") not implemented", section, key, item); - return false; -} - -void LibretroSettingsInterface::DeleteValue(const char* section, const char* key) -{ - Log_ErrorPrintf("DeleteValue(\"%s\", \"%s\") not implemented", section, key); -} - -void LibretroSettingsInterface::ClearSection(const char* section) -{ - Log_ErrorPrintf("ClearSection(\"%s\") not implemented", section); -} diff --git a/src/duckstation-libretro/libretro_settings_interface.h b/src/duckstation-libretro/libretro_settings_interface.h deleted file mode 100644 index 6ccd13491..000000000 --- a/src/duckstation-libretro/libretro_settings_interface.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "core/settings.h" - -class LibretroSettingsInterface : public SettingsInterface -{ -public: - void Clear() override; - - int GetIntValue(const char* section, const char* key, int default_value = 0) override; - float GetFloatValue(const char* section, const char* key, float default_value = 0.0f) override; - bool GetBoolValue(const char* section, const char* key, bool default_value = false) override; - std::string GetStringValue(const char* section, const char* key, const char* default_value = "") override; - - void SetIntValue(const char* section, const char* key, int value) override; - void SetFloatValue(const char* section, const char* key, float value) override; - void SetBoolValue(const char* section, const char* key, bool value) override; - void SetStringValue(const char* section, const char* key, const char* value) override; - - std::vector GetStringList(const char* section, const char* key) override; - void SetStringList(const char* section, const char* key, const std::vector& items) override; - bool RemoveFromStringList(const char* section, const char* key, const char* item) override; - bool AddToStringList(const char* section, const char* key, const char* item) override; - - void DeleteValue(const char* section, const char* key) override; - void ClearSection(const char* section) override; -}; diff --git a/src/duckstation-libretro/libretro_vulkan_host_display.cpp b/src/duckstation-libretro/libretro_vulkan_host_display.cpp deleted file mode 100644 index 5668eaabe..000000000 --- a/src/duckstation-libretro/libretro_vulkan_host_display.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include "libretro_vulkan_host_display.h" -#include "common/align.h" -#include "common/assert.h" -#include "common/log.h" -#include "common/vulkan/builders.h" -#include "common/vulkan/context.h" -#include "common/vulkan/shader_cache.h" -#include "common/vulkan/util.h" -#include "libretro_host_interface.h" -#include "vulkan_loader.h" -Log_SetChannel(LibretroVulkanHostDisplay); - -LibretroVulkanHostDisplay::LibretroVulkanHostDisplay() = default; - -LibretroVulkanHostDisplay::~LibretroVulkanHostDisplay() = default; - -void LibretroVulkanHostDisplay::SetVSync(bool enabled) -{ - // The libretro frontend controls this. - Log_DevPrintf("Ignoring SetVSync(%u)", BoolToUInt32(enabled)); -} - -static bool RetroCreateVulkanDevice(struct retro_vulkan_context* context, VkInstance instance, VkPhysicalDevice gpu, - VkSurfaceKHR surface, PFN_vkGetInstanceProcAddr get_instance_proc_addr, - const char** required_device_extensions, unsigned num_required_device_extensions, - const char** required_device_layers, unsigned num_required_device_layers, - const VkPhysicalDeviceFeatures* required_features) -{ - // We need some module functions. - vkGetInstanceProcAddr = get_instance_proc_addr; - if (!Vulkan::LoadVulkanInstanceFunctions(instance)) - { - Log_ErrorPrintf("Failed to load Vulkan instance functions"); - Vulkan::ResetVulkanLibraryFunctionPointers(); - return false; - } - - if (gpu == VK_NULL_HANDLE) - { - Vulkan::Context::GPUList gpus = Vulkan::Context::EnumerateGPUs(instance); - if (gpus.empty()) - { - g_libretro_host_interface.ReportError("No GPU provided and none available, cannot create device"); - Vulkan::ResetVulkanLibraryFunctionPointers(); - return false; - } - - Log_InfoPrintf("No GPU provided, using first/default"); - gpu = gpus[0]; - } - - if (!Vulkan::Context::CreateFromExistingInstance( - instance, gpu, surface, false, false, false, required_device_extensions, num_required_device_extensions, - required_device_layers, num_required_device_layers, required_features)) - { - Vulkan::ResetVulkanLibraryFunctionPointers(); - return false; - } - - context->gpu = g_vulkan_context->GetPhysicalDevice(); - context->device = g_vulkan_context->GetDevice(); - context->queue = g_vulkan_context->GetGraphicsQueue(); - context->queue_family_index = g_vulkan_context->GetGraphicsQueueFamilyIndex(); - context->presentation_queue = g_vulkan_context->GetPresentQueue(); - context->presentation_queue_family_index = g_vulkan_context->GetPresentQueueFamilyIndex(); - return true; -} - -static retro_hw_render_context_negotiation_interface_vulkan s_vulkan_context_negotiation_interface = { - RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN, // interface_type - RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN_VERSION, // interface_version - nullptr, // get_application_info - RetroCreateVulkanDevice, // create_device - nullptr // destroy_device -}; - -bool LibretroVulkanHostDisplay::RequestHardwareRendererContext(retro_hw_render_callback* cb) -{ - cb->cache_context = false; - cb->bottom_left_origin = false; - cb->context_type = RETRO_HW_CONTEXT_VULKAN; - return g_retro_environment_callback(RETRO_ENVIRONMENT_SET_HW_RENDER, cb) && - g_retro_environment_callback(RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE, - &s_vulkan_context_negotiation_interface); -} - -bool LibretroVulkanHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, - bool debug_device, bool threaded_presentation) -{ - retro_hw_render_interface* ri = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, &ri)) - { - Log_ErrorPrint("Failed to get HW render interface"); - return false; - } - else if (ri->interface_type != RETRO_HW_RENDER_INTERFACE_VULKAN || - ri->interface_version != RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION) - { - Log_ErrorPrintf("Unexpected HW interface - type %u version %u", static_cast(ri->interface_type), - static_cast(ri->interface_version)); - return false; - } - - if (!g_vulkan_context) - { - Log_ErrorPrintf("Vulkan context was not negotiated/created"); - return false; - } - - // TODO: Grab queue? it should be the same - m_ri = reinterpret_cast(ri); - return true; -} - -void LibretroVulkanHostDisplay::DestroyRenderDevice() -{ - VulkanHostDisplay::DestroyRenderDevice(); - Vulkan::ResetVulkanLibraryFunctionPointers(); -} - -bool LibretroVulkanHostDisplay::CreateResources() -{ - m_frame_render_pass = g_vulkan_context->GetRenderPass(FRAMEBUFFER_FORMAT, VK_FORMAT_UNDEFINED, VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_CLEAR); - if (m_frame_render_pass == VK_NULL_HANDLE) - return false; - - return VulkanHostDisplay::CreateResources(); -} - -void LibretroVulkanHostDisplay::DestroyResources() -{ - VulkanHostDisplay::DestroyResources(); - Vulkan::Util::SafeDestroyFramebuffer(m_frame_framebuffer); - m_frame_texture.Destroy(); - Vulkan::ShaderCompiler::DeinitializeGlslang(); -} - -VkRenderPass LibretroVulkanHostDisplay::GetRenderPassForDisplay() const -{ - return m_frame_render_pass; -} - -void LibretroVulkanHostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_height) -{ - m_window_info.surface_width = static_cast(new_window_width); - m_window_info.surface_height = static_cast(new_window_height); -} - -bool LibretroVulkanHostDisplay::ChangeRenderWindow(const WindowInfo& new_wi) -{ - // re-query hardware render interface - in vulkan, things get recreated without us being notified - retro_hw_render_interface* ri = nullptr; - if (!g_retro_environment_callback(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, &ri)) - { - Log_ErrorPrint("Failed to get HW render interface"); - return false; - } - else if (ri->interface_type != RETRO_HW_RENDER_INTERFACE_VULKAN || - ri->interface_version != RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION) - { - Log_ErrorPrintf("Unexpected HW interface - type %u version %u", static_cast(ri->interface_type), - static_cast(ri->interface_version)); - return false; - } - - retro_hw_render_interface_vulkan* vri = reinterpret_cast(ri); - if (vri != m_ri) - { - Log_WarningPrintf("HW render interface pointer changed without us being notified, this might cause issues?"); - m_ri = vri; - } - - return true; -} - -bool LibretroVulkanHostDisplay::Render() -{ - const u32 resolution_scale = g_libretro_host_interface.GetResolutionScale(); - const u32 display_width = static_cast(m_display_width) * resolution_scale; - const u32 display_height = static_cast(m_display_height) * resolution_scale; - if (display_width == 0 || display_height == 0 || !CheckFramebufferSize(display_width, display_height)) - return false; - - VkCommandBuffer cmdbuffer = g_vulkan_context->GetCurrentCommandBuffer(); - m_frame_texture.OverrideImageLayout(m_frame_view.image_layout); - m_frame_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - const VkClearValue clear_value = {}; - const VkRenderPassBeginInfo rp = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, m_frame_render_pass, m_frame_framebuffer, - {{0, 0}, {display_width, display_height}}, 1u, &clear_value}; - vkCmdBeginRenderPass(cmdbuffer, &rp, VK_SUBPASS_CONTENTS_INLINE); - - if (HasDisplayTexture()) - { - const auto [left, top, width, height] = CalculateDrawRect(display_width, display_height, 0, false); - RenderDisplay(left, top, width, height, m_display_texture_handle, m_display_texture_width, m_display_texture_height, - m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width, - m_display_texture_view_height, m_display_linear_filtering); - } - - if (HasSoftwareCursor()) - { - // TODO: Scale mouse x/y - const auto [left, top, width, height] = CalculateSoftwareCursorDrawRect(m_mouse_position_x, m_mouse_position_y); - RenderSoftwareCursor(left, top, width, height, m_cursor_texture.get()); - } - - vkCmdEndRenderPass(cmdbuffer); - m_frame_texture.TransitionToLayout(cmdbuffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - m_frame_view.image_layout = m_frame_texture.GetLayout(); - m_ri->set_image(m_ri->handle, &m_frame_view, 0, nullptr, VK_QUEUE_FAMILY_IGNORED); - - // TODO: We can't use this because it doesn't support passing fences... - // m_ri.set_command_buffers(m_ri.handle, 1, &cmdbuffer); - m_ri->lock_queue(m_ri->handle); - g_vulkan_context->SubmitCommandBuffer(); - m_ri->unlock_queue(m_ri->handle); - g_vulkan_context->MoveToNextCommandBuffer(); - - g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, display_width, display_height, 0); - return true; -} - -bool LibretroVulkanHostDisplay::CheckFramebufferSize(u32 width, u32 height) -{ - static constexpr VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - static constexpr VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D; - static constexpr VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; - - if (m_frame_texture.GetWidth() == width && m_frame_texture.GetHeight() == height) - return true; - - g_vulkan_context->DeferFramebufferDestruction(m_frame_framebuffer); - m_frame_texture.Destroy(true); - - if (!m_frame_texture.Create(width, height, 1, 1, FRAMEBUFFER_FORMAT, VK_SAMPLE_COUNT_1_BIT, view_type, tiling, usage)) - return false; - - VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer(); - m_frame_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - static constexpr VkClearColorValue cc = {}; - static constexpr VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - vkCmdClearColorImage(cmdbuf, m_frame_texture.GetImage(), m_frame_texture.GetLayout(), &cc, 1, &range); - - Vulkan::FramebufferBuilder fbb; - fbb.SetRenderPass(m_frame_render_pass); - fbb.AddAttachment(m_frame_texture.GetView()); - fbb.SetSize(width, height, 1); - m_frame_framebuffer = fbb.Create(g_vulkan_context->GetDevice(), false); - if (m_frame_framebuffer == VK_NULL_HANDLE) - return false; - - m_frame_view = {}; - m_frame_view.image_view = m_frame_texture.GetView(); - m_frame_view.image_layout = m_frame_texture.GetLayout(); - m_frame_view.create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - m_frame_view.create_info.image = m_frame_texture.GetImage(); - m_frame_view.create_info.viewType = view_type; - m_frame_view.create_info.format = FRAMEBUFFER_FORMAT; - m_frame_view.create_info.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, - VK_COMPONENT_SWIZZLE_A}; - m_frame_view.create_info.subresourceRange = range; - return true; -} diff --git a/src/duckstation-libretro/libretro_vulkan_host_display.h b/src/duckstation-libretro/libretro_vulkan_host_display.h deleted file mode 100644 index afea255fe..000000000 --- a/src/duckstation-libretro/libretro_vulkan_host_display.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once -#include "common/vulkan/texture.h" -#include "frontend-common/vulkan_host_display.h" -#include "libretro.h" - -#define HAVE_VULKAN -#include "libretro_vulkan.h" - -class LibretroVulkanHostDisplay final : public FrontendCommon::VulkanHostDisplay -{ -public: - LibretroVulkanHostDisplay(); - ~LibretroVulkanHostDisplay(); - - static bool RequestHardwareRendererContext(retro_hw_render_callback* cb); - - bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device, - bool threaded_presentation) override; - void DestroyRenderDevice() override; - - void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) override; - bool ChangeRenderWindow(const WindowInfo& new_wi) override; - - void SetVSync(bool enabled) override; - - bool Render() override; - -protected: - bool CreateResources() override; - void DestroyResources() override; - VkRenderPass GetRenderPassForDisplay() const override; - -private: - static constexpr VkFormat FRAMEBUFFER_FORMAT = VK_FORMAT_R8G8B8A8_UNORM; - - bool CheckFramebufferSize(u32 width, u32 height); - - retro_hw_render_interface_vulkan* m_ri = nullptr; - - Vulkan::Texture m_frame_texture; - retro_vulkan_image m_frame_view = {}; - VkFramebuffer m_frame_framebuffer = VK_NULL_HANDLE; - VkRenderPass m_frame_render_pass = VK_NULL_HANDLE; -}; diff --git a/src/duckstation-libretro/main.cpp b/src/duckstation-libretro/main.cpp deleted file mode 100644 index a644273b8..000000000 --- a/src/duckstation-libretro/main.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "common/assert.h" -#include "common/log.h" -#include "libretro_host_interface.h" -#include "scmversion/scmversion.h" -Log_SetChannel(Main); - -RETRO_API unsigned retro_api_version(void) -{ - return RETRO_API_VERSION; -} - -RETRO_API void retro_init(void) -{ - // default log to stdout until we get an interface - Log::SetConsoleOutputParams(true, nullptr, LOGLEVEL_INFO); - - if (!g_libretro_host_interface.Initialize()) - Panic("Host interface initialization failed"); -} - -RETRO_API void retro_deinit(void) -{ - g_libretro_host_interface.Shutdown(); -} - -RETRO_API void retro_get_system_info(struct retro_system_info* info) -{ - std::memset(info, 0, sizeof(*info)); - -#if defined(_DEBUGFAST) - info->library_name = "DuckStation DebugFast"; -#elif defined(_DEBUG) - info->library_name = "DuckStation Debug"; -#else - info->library_name = "DuckStation"; -#endif - - info->library_version = g_scm_tag_str; - info->valid_extensions = "exe|cue|bin|chd|psf|m3u"; - info->need_fullpath = true; - info->block_extract = false; -} - -RETRO_API void retro_get_system_av_info(struct retro_system_av_info* info) -{ - g_libretro_host_interface.retro_get_system_av_info(info); -} - -RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device) -{ - Log_ErrorPrintf("retro_set_controller_port_device(%u, %u)", port, device); -} - -RETRO_API void retro_reset(void) -{ - Log_InfoPrint("retro_reset()"); - g_libretro_host_interface.ResetSystem(); -} - -RETRO_API void retro_run(void) -{ - g_libretro_host_interface.retro_run_frame(); -} - -RETRO_API size_t retro_serialize_size(void) -{ - return g_libretro_host_interface.retro_serialize_size(); -} - -RETRO_API bool retro_serialize(void* data, size_t size) -{ - return g_libretro_host_interface.retro_serialize(data, size); -} - -RETRO_API bool retro_unserialize(const void* data, size_t size) -{ - return g_libretro_host_interface.retro_unserialize(data, size); -} - -RETRO_API void retro_cheat_reset(void) -{ - Log_InfoPrint("retro_cheat_reset()"); - g_libretro_host_interface.retro_cheat_reset(); -} - -RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char* code) -{ - Log_InfoPrintf("retro_cheat_set(%u, %u, %s)", index, enabled, code); - g_libretro_host_interface.retro_cheat_set(index, enabled, code); -} - -RETRO_API bool retro_load_game(const struct retro_game_info* game) -{ - Log_InfoPrintf("retro_load_game(%s)", game->path); - return g_libretro_host_interface.retro_load_game(game); -} - -RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_game_info* info, size_t num_info) -{ - Log_ErrorPrintf("retro_load_game_special()"); - return false; -} - -RETRO_API void retro_unload_game(void) -{ - g_libretro_host_interface.DestroySystem(); -} - -RETRO_API unsigned retro_get_region(void) -{ - return g_libretro_host_interface.retro_get_region(); -} - -RETRO_API void* retro_get_memory_data(unsigned id) -{ - return g_libretro_host_interface.retro_get_memory_data(id); -} - -RETRO_API size_t retro_get_memory_size(unsigned id) -{ - return g_libretro_host_interface.retro_get_memory_size(id); -} - -RETRO_API void retro_set_environment(retro_environment_t f) -{ - g_retro_environment_callback = f; - g_libretro_host_interface.retro_set_environment(); -} - -RETRO_API void retro_set_video_refresh(retro_video_refresh_t f) -{ - g_retro_video_refresh_callback = f; -} - -RETRO_API void retro_set_audio_sample(retro_audio_sample_t f) -{ - g_retro_audio_sample_callback = f; -} - -RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t f) -{ - g_retro_audio_sample_batch_callback = f; -} - -RETRO_API void retro_set_input_poll(retro_input_poll_t f) -{ - g_retro_input_poll_callback = f; -} - -RETRO_API void retro_set_input_state(retro_input_state_t f) -{ - g_retro_input_state_callback = f; -} diff --git a/src/frontend-common/CMakeLists.txt b/src/frontend-common/CMakeLists.txt index d4d323aa0..c83ee4298 100644 --- a/src/frontend-common/CMakeLists.txt +++ b/src/frontend-common/CMakeLists.txt @@ -1,6 +1,24 @@ add_library(frontend-common + common_host_interface.cpp + common_host_interface.h + controller_interface.cpp + controller_interface.h + cubeb_audio_stream.cpp + cubeb_audio_stream.h + game_list.cpp + game_list.h game_settings.cpp game_settings.h + icon.cpp + icon.h + ini_settings_interface.cpp + ini_settings_interface.h + imgui_impl_opengl3.cpp + imgui_impl_opengl3.h + imgui_impl_vulkan.cpp + imgui_impl_vulkan.h + imgui_styles.cpp + imgui_styles.h opengl_host_display.cpp opengl_host_display.h postprocessing_chain.cpp @@ -9,97 +27,55 @@ add_library(frontend-common postprocessing_shader.h postprocessing_shadergen.cpp postprocessing_shadergen.h + save_state_selector_ui.cpp + save_state_selector_ui.h vulkan_host_display.cpp vulkan_host_display.h ) -target_link_libraries(frontend-common PUBLIC core common glad vulkan-loader) +target_compile_definitions(frontend-common PRIVATE "WITH_IMGUI=1") +target_link_libraries(frontend-common PUBLIC core common glad vulkan-loader cubeb imgui simpleini tinyxml2 scmversion) if(WIN32) target_sources(frontend-common PRIVATE d3d11_host_display.cpp d3d11_host_display.h + dinput_controller_interface.cpp + dinput_controller_interface.h + imgui_impl_dx11.cpp + imgui_impl_dx11.h + xinput_controller_interface.cpp + xinput_controller_interface.h ) target_link_libraries(frontend-common PRIVATE d3d11.lib dxgi.lib) endif() -if(NOT BUILD_LIBRETRO_CORE) - target_sources(frontend-common PRIVATE - imgui_impl_opengl3.h - imgui_impl_opengl3.cpp - ) - - target_sources(frontend-common PRIVATE - imgui_impl_vulkan.h - imgui_impl_vulkan.cpp +if(SDL2_FOUND) + target_sources(frontend-common PRIVATE + sdl_audio_stream.cpp + sdl_audio_stream.h + sdl_controller_interface.cpp + sdl_controller_interface.h + sdl_initializer.cpp + sdl_initializer.h ) + target_compile_definitions(frontend-common PUBLIC "WITH_SDL2=1") + target_include_directories(frontend-common PRIVATE ${SDL2_INCLUDE_DIRS}) + target_link_libraries(frontend-common PRIVATE ${SDL2_LIBRARIES}) + # Copy bundled SDL2 to output on Windows. if(WIN32) - target_sources(frontend-common PRIVATE - imgui_impl_dx11.h - imgui_impl_dx11.cpp - ) + add_custom_command(TARGET frontend-common POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_DLL_PATH}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/SDL2.dll") endif() - - target_sources(frontend-common PRIVATE - common_host_interface.cpp - common_host_interface.h - controller_interface.cpp - controller_interface.h - cubeb_audio_stream.cpp - cubeb_audio_stream.h - game_list.cpp - game_list.h - icon.cpp - icon.h - imgui_styles.cpp - imgui_styles.h - ini_settings_interface.cpp - ini_settings_interface.h - save_state_selector_ui.cpp - save_state_selector_ui.h - ) - - if(WIN32) - target_sources(frontend-common PRIVATE - dinput_controller_interface.cpp - dinput_controller_interface.h - xinput_controller_interface.cpp - xinput_controller_interface.h - ) - endif() - - target_compile_definitions(frontend-common PRIVATE "WITH_IMGUI=1") - target_link_libraries(frontend-common PUBLIC cubeb imgui simpleini tinyxml2 scmversion) - - if(SDL2_FOUND) - target_sources(frontend-common PRIVATE - sdl_audio_stream.cpp - sdl_audio_stream.h - sdl_controller_interface.cpp - sdl_controller_interface.h - sdl_initializer.cpp - sdl_initializer.h - ) - target_compile_definitions(frontend-common PUBLIC "WITH_SDL2=1") - target_include_directories(frontend-common PRIVATE ${SDL2_INCLUDE_DIRS}) - target_link_libraries(frontend-common PRIVATE ${SDL2_LIBRARIES}) - - # Copy bundled SDL2 to output on Windows. - if(WIN32) - add_custom_command(TARGET frontend-common POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SDL2_DLL_PATH}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/SDL2.dll") - endif() - endif() - - if(ENABLE_DISCORD_PRESENCE AND NOT BUILD_LIBRETRO_CORE) - target_compile_definitions(frontend-common PUBLIC -DWITH_DISCORD_PRESENCE=1) - target_link_libraries(frontend-common PRIVATE discord-rpc) - endif() - - # Copy the provided data directory to the output directory. - add_custom_command(TARGET frontend-common POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/data" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - ) endif() +if(ENABLE_DISCORD_PRESENCE) + target_compile_definitions(frontend-common PUBLIC -DWITH_DISCORD_PRESENCE=1) + target_link_libraries(frontend-common PRIVATE discord-rpc) +endif() + +# Copy the provided data directory to the output directory. +add_custom_command(TARGET frontend-common POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/data" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" +) diff --git a/src/frontend-common/d3d11_host_display.cpp b/src/frontend-common/d3d11_host_display.cpp index 43443da6b..2381b4594 100644 --- a/src/frontend-common/d3d11_host_display.cpp +++ b/src/frontend-common/d3d11_host_display.cpp @@ -344,11 +344,8 @@ bool D3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::string_view bool D3D11HostDisplay::InitializeRenderDevice(std::string_view shader_cache_directory, bool debug_device, bool threaded_presentation) { - if (m_window_info.type != WindowInfo::Type::Surfaceless && m_window_info.type != WindowInfo::Type::Libretro && - !CreateSwapChain(nullptr)) - { + if (m_window_info.type != WindowInfo::Type::Surfaceless && !CreateSwapChain(nullptr)) return false; - } if (!CreateResources()) return false; diff --git a/src/frontend-common/game_settings.cpp b/src/frontend-common/game_settings.cpp index 2c181d116..f7b47a912 100644 --- a/src/frontend-common/game_settings.cpp +++ b/src/frontend-common/game_settings.cpp @@ -11,12 +11,10 @@ #include Log_SetChannel(GameSettings); -#ifndef LIBRETRO #ifdef WIN32 #include "common/windows_headers.h" #endif #include "SimpleIni.h" -#endif namespace GameSettings { @@ -183,8 +181,6 @@ bool Entry::SaveToStream(ByteStream* stream) const WriteStringToStream(stream, memory_card_2_shared_path) && WriteStringToStream(stream, input_profile_name); } -#ifndef LIBRETRO - static void ParseIniSection(Entry* entry, const char* section, const CSimpleIniA& ini) { for (u32 trait = 0; trait < static_cast(Trait::Count); trait++) @@ -897,8 +893,6 @@ void Entry::SetValueForKey(const std::string_view& key, const std::optional& value); }; -#ifndef LIBRETRO - class Database { public: @@ -110,6 +108,4 @@ private: std::unordered_map m_entries; }; -#endif - }; // namespace GameSettings \ No newline at end of file diff --git a/src/frontend-common/opengl_host_display.cpp b/src/frontend-common/opengl_host_display.cpp index b6bce7f06..d0826d4bb 100644 --- a/src/frontend-common/opengl_host_display.cpp +++ b/src/frontend-common/opengl_host_display.cpp @@ -9,7 +9,7 @@ #include "imgui_impl_opengl3.h" #endif #include "postprocessing_shadergen.h" -Log_SetChannel(LibretroOpenGLHostDisplay); +Log_SetChannel(OpenGLHostDisplay); namespace FrontendCommon { diff --git a/src/frontend-common/vulkan_host_display.cpp b/src/frontend-common/vulkan_host_display.cpp index 303ae60f0..3fb7dba92 100644 --- a/src/frontend-common/vulkan_host_display.cpp +++ b/src/frontend-common/vulkan_host_display.cpp @@ -499,7 +499,6 @@ void main() void VulkanHostDisplay::DestroyResources() { -#ifndef LIBRETRO Vulkan::Util::SafeDestroyPipelineLayout(m_post_process_pipeline_layout); Vulkan::Util::SafeDestroyPipelineLayout(m_post_process_ubo_pipeline_layout); Vulkan::Util::SafeDestroyDescriptorSetLayout(m_post_process_descriptor_set_layout); @@ -509,7 +508,6 @@ void VulkanHostDisplay::DestroyResources() m_post_processing_stages.clear(); m_post_processing_ubo.Destroy(true); m_post_processing_chain.ClearStages(); -#endif m_display_pixels_texture.Destroy(false); m_readback_staging_texture.Destroy(false);