From 409ec5a8d06c38725d70bef8b6ec6e4be4b41237 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Sun, 29 Dec 2019 17:35:52 +0100 Subject: [PATCH 01/41] allow GS to run in non-/threaded mode --- Source/gs/GSH_OpenGL/GSH_OpenGL.cpp | 7 ++-- Source/gs/GSH_OpenGL/GSH_OpenGL.h | 2 +- Source/gs/GSHandler.cpp | 61 ++++++++++++++++++++++------- Source/gs/GSHandler.h | 11 +++++- 4 files changed, 60 insertions(+), 21 deletions(-) diff --git a/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp b/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp index af018448..e31d623b 100644 --- a/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp +++ b/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp @@ -56,8 +56,9 @@ static uint32 MakeColor(uint8 r, uint8 g, uint8 b, uint8 a) return (a << 24) | (b << 16) | (g << 8) | (r); } -CGSH_OpenGL::CGSH_OpenGL() - : m_pCvtBuffer(nullptr) +CGSH_OpenGL::CGSH_OpenGL(bool gsThreaded) + : CGSHandler(gsThreaded) + , m_pCvtBuffer(nullptr) { RegisterPreferences(); LoadPreferences(); @@ -292,7 +293,7 @@ void CGSH_OpenGL::FlipImpl() void CGSH_OpenGL::LoadState(Framework::CZipArchiveReader& archive) { CGSHandler::LoadState(archive); - m_mailBox.SendCall( + SendGSCall( [this]() { m_textureCache.InvalidateRange(0, RAMSIZE); }); diff --git a/Source/gs/GSH_OpenGL/GSH_OpenGL.h b/Source/gs/GSH_OpenGL/GSH_OpenGL.h index 5140bfcb..9bce1b1c 100644 --- a/Source/gs/GSH_OpenGL/GSH_OpenGL.h +++ b/Source/gs/GSH_OpenGL/GSH_OpenGL.h @@ -22,7 +22,7 @@ class CGSH_OpenGL : public CGSHandler { public: - CGSH_OpenGL(); + CGSH_OpenGL(bool = true); virtual ~CGSH_OpenGL(); static void RegisterPreferences(); diff --git a/Source/gs/GSHandler.cpp b/Source/gs/GSHandler.cpp index 612b87e4..d834bb25 100644 --- a/Source/gs/GSHandler.cpp +++ b/Source/gs/GSHandler.cpp @@ -62,13 +62,14 @@ struct MASSIVEWRITE_INFO CGSHandler::RegisterWriteList writes; }; -CGSHandler::CGSHandler() +CGSHandler::CGSHandler(bool gsThreaded) : m_threadDone(false) , m_drawCallCount(0) , m_pCLUT(nullptr) , m_pRAM(nullptr) , m_frameDump(nullptr) , m_loggingEnabled(true) + , m_gsThreaded(gsThreaded) { RegisterPreferences(); @@ -100,13 +101,19 @@ CGSHandler::CGSHandler() ResetBase(); - m_thread = std::thread([&]() { ThreadProc(); }); + if(m_gsThreaded) + { + m_thread = std::thread([&]() { ThreadProc(); }); + } } CGSHandler::~CGSHandler() { - m_mailBox.SendCall([this]() { m_threadDone = true; }); - m_thread.join(); + if(m_gsThreaded) + { + SendGSCall([this]() { m_threadDone = true; }); + m_thread.join(); + } delete[] m_pRAM; delete[] m_pCLUT; } @@ -118,7 +125,7 @@ void CGSHandler::RegisterPreferences() void CGSHandler::NotifyPreferencesChanged() { - m_mailBox.SendCall([this]() { NotifyPreferencesChangedImpl(); }); + SendGSCall([this]() { NotifyPreferencesChangedImpl(); }); } void CGSHandler::SetIntc(CINTC* intc) @@ -129,7 +136,7 @@ void CGSHandler::SetIntc(CINTC* intc) void CGSHandler::Reset() { ResetBase(); - m_mailBox.SendCall(std::bind(&CGSHandler::ResetImpl, this), true); + SendGSCall(std::bind(&CGSHandler::ResetImpl, this), true); } void CGSHandler::ResetBase() @@ -374,27 +381,28 @@ void CGSHandler::WritePrivRegister(uint32 nAddress, uint32 nData) void CGSHandler::Initialize() { - m_mailBox.SendCall(std::bind(&CGSHandler::InitializeImpl, this), true); + SendGSCall(std::bind(&CGSHandler::InitializeImpl, this), true); } void CGSHandler::Release() { - m_mailBox.SendCall(std::bind(&CGSHandler::ReleaseImpl, this), true); + SendGSCall(std::bind(&CGSHandler::ReleaseImpl, this), true); } void CGSHandler::Flip(bool showOnly) { if(!showOnly) { - m_mailBox.FlushCalls(); - m_mailBox.SendCall(std::bind(&CGSHandler::MarkNewFrame, this)); + SendGSCall([]() {}, true); + SendGSCall(std::bind(&CGSHandler::MarkNewFrame, this)); } - m_mailBox.SendCall(std::bind(&CGSHandler::FlipImpl, this), true); + SendGSCall(std::bind(&CGSHandler::FlipImpl, this), true, true); } void CGSHandler::FlipImpl() { OnFlipComplete(); + m_flipped = true; } void CGSHandler::MarkNewFrame() @@ -428,7 +436,7 @@ void CGSHandler::SetSMODE2(uint64 value) void CGSHandler::WriteRegister(uint8 registerId, uint64 value) { - m_mailBox.SendCall(std::bind(&CGSHandler::WriteRegisterImpl, this, registerId, value)); + SendGSCall(std::bind(&CGSHandler::WriteRegisterImpl, this, registerId, value)); } void CGSHandler::FeedImageData(const void* data, uint32 length) @@ -440,7 +448,7 @@ void CGSHandler::FeedImageData(const void* data, uint32 length) std::vector imageData(length + 0x10); memcpy(imageData.data(), data, length); - m_mailBox.SendCall( + SendGSCall( [this, imageData = std::move(imageData), length]() { FeedImageDataImpl(imageData.data(), length); }); @@ -448,7 +456,7 @@ void CGSHandler::FeedImageData(const void* data, uint32 length) void CGSHandler::ReadImageData(void* data, uint32 length) { - m_mailBox.SendCall([this, data, length]() { ReadImageDataImpl(data, length); }, true); + SendGSCall([this, data, length]() { ReadImageDataImpl(data, length); }, true); } void CGSHandler::WriteRegisterMassively(RegisterWriteList registerWrites, const CGsPacketMetadata* metadata) @@ -500,7 +508,7 @@ void CGSHandler::WriteRegisterMassively(RegisterWriteList registerWrites, const } #endif - m_mailBox.SendCall( + SendGSCall( [this, massiveWrite = std::move(massiveWrite)]() { WriteRegisterMassivelyImpl(massiveWrite); }); @@ -1728,6 +1736,29 @@ void CGSHandler::ThreadProc() } } +void CGSHandler::SendGSCall(const CMailBox::FunctionType& function, bool waitForCompletion, bool forceWaitForCompletion) +{ + if(!m_gsThreaded) + { + waitForCompletion = false; + } + m_mailBox.SendCall(function, waitForCompletion); +} + +void CGSHandler::ProcessSingleFrame() +{ + assert(!m_gsThreaded); + while(!m_flipped) + { + m_mailBox.WaitForCall(); + while(m_mailBox.IsPending()) + { + m_mailBox.ReceiveCall(); + } + } + m_flipped = false; +} + Framework::CBitmap CGSHandler::GetScreenshot() { throw std::runtime_error("Screenshot feature is not implemented in current backend."); diff --git a/Source/gs/GSHandler.h b/Source/gs/GSHandler.h index 6819d2f0..8abfc878 100644 --- a/Source/gs/GSHandler.h +++ b/Source/gs/GSHandler.h @@ -704,7 +704,7 @@ public: typedef Framework::CSignal FlipCompleteEvent; typedef Framework::CSignal NewFrameEvent; - CGSHandler(); + CGSHandler(bool = true); virtual ~CGSHandler(); static void RegisterPreferences(); @@ -952,6 +952,8 @@ protected: void ReadCLUT8(const TEX0&); static bool IsCompatibleFramebufferPSM(unsigned int, unsigned int); + void SendGSCall(const CMailBox::FunctionType&, bool = false, bool = false); + void ProcessSingleFrame(); bool m_loggingEnabled; @@ -983,9 +985,14 @@ protected: std::thread m_thread; std::recursive_mutex m_registerMutex; std::atomic m_transferCount; - CMailBox m_mailBox; bool m_threadDone; CFrameDump* m_frameDump; bool m_drawEnabled = true; CINTC* m_intc = nullptr; + bool m_gsThreaded = true; + bool m_flipped = false; + +private: + CMailBox m_mailBox; + }; From b4c7777b848735df5cffed36d6cdf17da0c405eb Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 31 Dec 2019 21:02:35 +0100 Subject: [PATCH 02/41] Initial Libretro implementation --- CMakeLists.txt | 8 + Source/gs/GSHandler.cpp | 3 +- Source/gs/GSHandler.h | 2 +- Source/ui_libretro/CMakeLists.txt | 71 + Source/ui_libretro/GSH_OpenGL_Libretro.cpp | 114 + Source/ui_libretro/GSH_OpenGL_Libretro.h | 27 + Source/ui_libretro/PH_Libretro_Input.cpp | 48 + Source/ui_libretro/PH_Libretro_Input.h | 18 + Source/ui_libretro/SH_LibreAudio.h | 37 + Source/ui_libretro/libretro.h | 2537 ++++++++++++++++++++ Source/ui_libretro/main_libretro.cpp | 481 ++++ 11 files changed, 3344 insertions(+), 2 deletions(-) create mode 100644 Source/ui_libretro/CMakeLists.txt create mode 100644 Source/ui_libretro/GSH_OpenGL_Libretro.cpp create mode 100644 Source/ui_libretro/GSH_OpenGL_Libretro.h create mode 100644 Source/ui_libretro/PH_Libretro_Input.cpp create mode 100644 Source/ui_libretro/PH_Libretro_Input.h create mode 100644 Source/ui_libretro/SH_LibreAudio.h create mode 100644 Source/ui_libretro/libretro.h create mode 100644 Source/ui_libretro/main_libretro.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b9a9fcd6..3a51dc15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ set(BUILD_PSFPLAYER OFF CACHE BOOL "Build PsfPlayer") set(BUILD_TESTS ON CACHE BOOL "Build Tests") set(USE_AOT_CACHE OFF CACHE BOOL "Use AOT block cache") set(BUILD_AOT_CACHE OFF CACHE BOOL "Build AOT block cache (for PsfPlayer only)") +set(BUILD_LIBRETRO_CORE OFF CACHE BOOL "Build Libretro Core") set(PROJECT_NAME "Play!") set(PROJECT_Version 0.30) @@ -49,6 +50,13 @@ if(BUILD_PLAY) add_subdirectory(Source/ui_android/) endif(TARGET_PLATFORM_ANDROID) endif() + + if(BUILD_LIBRETRO_CORE) + if(NOT MSVC) + add_compile_options(-fPIC) + endif() + add_subdirectory(Source/ui_libretro) + endif() endif(BUILD_PLAY) if(BUILD_TESTS) diff --git a/Source/gs/GSHandler.cpp b/Source/gs/GSHandler.cpp index d834bb25..70dbb29d 100644 --- a/Source/gs/GSHandler.cpp +++ b/Source/gs/GSHandler.cpp @@ -1742,6 +1742,7 @@ void CGSHandler::SendGSCall(const CMailBox::FunctionType& function, bool waitFor { waitForCompletion = false; } + waitForCompletion |= forceWaitForCompletion; m_mailBox.SendCall(function, waitForCompletion); } @@ -1751,7 +1752,7 @@ void CGSHandler::ProcessSingleFrame() while(!m_flipped) { m_mailBox.WaitForCall(); - while(m_mailBox.IsPending()) + while(m_mailBox.IsPending() && !m_flipped) { m_mailBox.ReceiveCall(); } diff --git a/Source/gs/GSHandler.h b/Source/gs/GSHandler.h index 8abfc878..7eb88d30 100644 --- a/Source/gs/GSHandler.h +++ b/Source/gs/GSHandler.h @@ -763,6 +763,7 @@ public: bool GetCrtIsFrameMode() const; virtual Framework::CBitmap GetScreenshot(); + void ProcessSingleFrame(); FlipCompleteEvent OnFlipComplete; NewFrameEvent OnNewFrame; @@ -953,7 +954,6 @@ protected: static bool IsCompatibleFramebufferPSM(unsigned int, unsigned int); void SendGSCall(const CMailBox::FunctionType&, bool = false, bool = false); - void ProcessSingleFrame(); bool m_loggingEnabled; diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt new file mode 100644 index 00000000..ad01d6d7 --- /dev/null +++ b/Source/ui_libretro/CMakeLists.txt @@ -0,0 +1,71 @@ +cmake_minimum_required(VERSION 3.5) + +set(CMAKE_MODULE_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/../../../Dependencies/cmake-modules + ${CMAKE_MODULE_PATH} +) +include(Header) + +project(Play_Libretro_Core) + +add_definitions(-DPLAY_VERSION="${PROJECT_Version}") + +if(NOT TARGET PlayCore) + add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/../ + ${CMAKE_CURRENT_BINARY_DIR}/Source + ) +endif() +list(APPEND PROJECT_LIBS PlayCore) + +if(NOT TARGET gsh_opengl) + add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/../gs/GSH_OpenGL + ${CMAKE_CURRENT_BINARY_DIR}/gs/GSH_OpenGL + ) +endif() +list(INSERT PROJECT_LIBS 0 gsh_opengl) + +if(NOT TARGET_PLATFORM_UNIX_AARCH64) + if (NOT TARGET glew_s) + add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/../../../Dependencies/glew-2.0.0 + ${CMAKE_CURRENT_BINARY_DIR}/glew-2.0.0 + ) + endif() + list(APPEND PROJECT_LIBS glew_s) +endif() + +if(TARGET_PLATFORM_MACOS OR TARGET_PLATFORM_UNIX) + if(NOT TARGET sh_openal) + add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/PsfPlayer/Source/SH_OpenAL + ${CMAKE_CURRENT_BINARY_DIR}/SH_OpenAL + ) + endif() + list(APPEND PROJECT_LIBS sh_openal) +endif() + +set(SRC + main_libretro.cpp + GSH_OpenGL_Libretro.cpp + GSH_OpenGL_Libretro.h + PH_Libretro_Input.cpp + PH_Libretro_Input.h + SH_LibreAudio.h +) + +if(TARGET_PLATFORM_WIN32) + set(SRC + ${SRC} + ../../tools/PsfPlayer/Source/win32_ui/SH_WaveOut.cpp + ) +endif() + +add_library(play_libretro SHARED ${SRC}) +target_include_directories(play_libretro PRIVATE + ./ + ../../ + ${CMAKE_CURRENT_BINARY_DIR} +) +target_link_libraries(play_libretro ${PROJECT_LIBS} "winmm.lib") diff --git a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp new file mode 100644 index 00000000..3748887b --- /dev/null +++ b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp @@ -0,0 +1,114 @@ +#include "GSH_OpenGL_Libretro.h" +#include "Log.h" + +#define LOG_NAME "LIBRETRO" + +extern int g_res_factor; +extern CGSHandler::PRESENTATION_MODE g_presentation_mode; +extern retro_video_refresh_t g_video_cb; +extern struct retro_hw_render_callback g_hw_render; + +CGSH_OpenGL_Libretro::CGSH_OpenGL_Libretro() + : CGSH_OpenGL(false) +{ +} + +CGSH_OpenGL_Libretro::~CGSH_OpenGL_Libretro() +{ +} + +CGSH_OpenGL::FactoryFunction CGSH_OpenGL_Libretro::GetFactoryFunction() +{ + return []() { return new CGSH_OpenGL_Libretro(); }; +} + +void CGSH_OpenGL_Libretro::InitializeImpl() +{ + fprintf(stderr, "%s\n", __FUNCTION__); + +#if defined(USE_GLEW) + glewExperimental = GL_TRUE; + auto result = glewInit(); + CLog::GetInstance().Warn(LOG_NAME, "glewInit %d\n", result == GLEW_OK); + assert(result == GLEW_OK); + if(result != GLEW_OK) + { + fprintf(stderr, "Error: %s\n", glewGetErrorString(result)); + CLog::GetInstance().Warn(LOG_NAME, "Error: %s\n", glewGetErrorString(result)); + return; + } + +#endif + + if(g_hw_render.get_current_framebuffer) + m_presentFramebuffer = g_hw_render.get_current_framebuffer(); + + UpdatePresentationImpl(); + + CGSH_OpenGL::InitializeImpl(); +} + +void CGSH_OpenGL_Libretro::UpdatePresentation() +{ + SendGSCall([this]() { UpdatePresentationImpl(); }); +} + +void CGSH_OpenGL_Libretro::UpdatePresentationImpl() +{ + PRESENTATION_PARAMS presentationParams; + presentationParams.mode = g_presentation_mode; + presentationParams.windowWidth = m_framebufferWidth * g_res_factor; + presentationParams.windowHeight = (3.0 / 4.0) * m_framebufferHeight * g_res_factor; + + SetPresentationParams(presentationParams); + NotifyPreferencesChanged(); +} + +void CGSH_OpenGL_Libretro::FlushMailBox() +{ + bool isFlushed = false; + SendGSCall([&]() { + isFlushed = true; + }, true); + while(!isFlushed) + { + // Wait for flush to complete + ProcessSingleFrame(); + } +} + +void CGSH_OpenGL_Libretro::Reset() +{ + FlushMailBox(); + ResetBase(); + CGSH_OpenGL::ReleaseImpl(); + InitializeImpl(); +} + +void CGSH_OpenGL_Libretro::Release() +{ + FlushMailBox(); + ResetBase(); + CGSH_OpenGL::ReleaseImpl(); +} + +void CGSH_OpenGL_Libretro::FlipImpl() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(g_hw_render.get_current_framebuffer) + m_presentFramebuffer = g_hw_render.get_current_framebuffer(); + else + return; + + CGSH_OpenGL::FlipImpl(); +} + +void CGSH_OpenGL_Libretro::PresentBackbuffer() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(g_video_cb) + g_video_cb(RETRO_HW_FRAME_BUFFER_VALID, m_framebufferWidth * g_res_factor, (3.0 / 4.0) * m_framebufferHeight * g_res_factor, 0); + +} diff --git a/Source/ui_libretro/GSH_OpenGL_Libretro.h b/Source/ui_libretro/GSH_OpenGL_Libretro.h new file mode 100644 index 00000000..02203d5a --- /dev/null +++ b/Source/ui_libretro/GSH_OpenGL_Libretro.h @@ -0,0 +1,27 @@ +#pragma once + +#include "gs/GSH_OpenGL/GSH_OpenGL.h" +#include "libretro.h" + +class CGSH_OpenGL_Libretro : public CGSH_OpenGL +{ +public: + CGSH_OpenGL_Libretro(); + virtual ~CGSH_OpenGL_Libretro(); + + static FactoryFunction GetFactoryFunction(); + + void InitializeImpl() override; + void FlipImpl() override; + void Reset(); + void Release(); + void PresentBackbuffer() override; + void UpdatePresentation(); + void FlushMailBox(); + +private: + void UpdatePresentationImpl(); + + GLint m_framebufferWidth = 512; + GLint m_framebufferHeight = 512; +}; diff --git a/Source/ui_libretro/PH_Libretro_Input.cpp b/Source/ui_libretro/PH_Libretro_Input.cpp new file mode 100644 index 00000000..803b4908 --- /dev/null +++ b/Source/ui_libretro/PH_Libretro_Input.cpp @@ -0,0 +1,48 @@ +#include "PH_Libretro_Input.h" + +extern retro_input_poll_t g_input_poll_cb; +extern retro_input_state_t g_input_state_cb; +extern std::map g_ds2_to_retro_btn_map; + +void CPH_Libretro_Input::Update(uint8* ram) +{ + if(!g_input_poll_cb || !g_input_state_cb || g_ds2_to_retro_btn_map.size() == 0) + return; + + g_input_poll_cb(); + + for(auto* listener : m_listeners) + { + for(unsigned int i = 0; i < PS2::CControllerInfo::MAX_BUTTONS; i++) + { + auto button = static_cast(i); + auto itr = g_ds2_to_retro_btn_map.find(button); + + if(itr == g_ds2_to_retro_btn_map.end()) return; + + auto currentButtonId = static_cast(i); + if(PS2::CControllerInfo::IsAxis(currentButtonId)) + { + int index; + if(i < 2) + index = RETRO_DEVICE_INDEX_ANALOG_LEFT; + else + index = RETRO_DEVICE_INDEX_ANALOG_RIGHT; + + float value = g_input_state_cb(0, RETRO_DEVICE_ANALOG, index, itr->second); + uint8 val = static_cast((value / 0xFF) + 0.5) + 0x7F; + listener->SetAxisState(0, currentButtonId, val, ram); + } + else + { + uint32 value = g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, itr->second); + listener->SetButtonState(0, currentButtonId, value != 0, ram); + } + } + } +} + +CPadHandler::FactoryFunction CPH_Libretro_Input::GetFactoryFunction() +{ + return []() { return new CPH_Libretro_Input(); }; +} diff --git a/Source/ui_libretro/PH_Libretro_Input.h b/Source/ui_libretro/PH_Libretro_Input.h new file mode 100644 index 00000000..6ab70068 --- /dev/null +++ b/Source/ui_libretro/PH_Libretro_Input.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include "PadHandler.h" +// #include "InputBindingManager.h" +#include "libretro.h" + + +class CPH_Libretro_Input : public CPadHandler +{ +public: + CPH_Libretro_Input() = default; + virtual ~CPH_Libretro_Input() = default; + + void Update(uint8*) override; + + static FactoryFunction GetFactoryFunction(); +}; diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h new file mode 100644 index 00000000..88748f08 --- /dev/null +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -0,0 +1,37 @@ +#pragma once + +#ifdef _WIN32 +#include "../../tools/PsfPlayer/Source/win32_ui/SH_WaveOut.h" +#else +#include "tools/PsfPlayer/Source/SH_OpenAL.h" +#endif + +extern bool g_audioEnabled; + + +#ifdef _WIN32 +class CSH_LibreAudio : public CSH_WaveOut +#else +class CSH_LibreAudio : public CSH_OpenAL +#endif +{ +public: + CSH_LibreAudio() = default; + + static CSoundHandler* HandlerFactory() + { + return new CSH_LibreAudio(); + } + + void Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) override + { + if(g_audioEnabled) + { +#ifdef _WIN32 + CSH_WaveOut::Write(buffer, sampleCount, sampleRate); +#else + CSH_OpenAL::Write(buffer, sampleCount, sampleRate); +#endif + } + }; +}; diff --git a/Source/ui_libretro/libretro.h b/Source/ui_libretro/libretro.h new file mode 100644 index 00000000..c3a7d40e --- /dev/null +++ b/Source/ui_libretro/libretro.h @@ -0,0 +1,2537 @@ +/* Copyright (C) 2010-2018 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 + +/* 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 + +/* 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. + */ + +/* 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_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 + +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. + * 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); + +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; +}; + +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_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/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp new file mode 100644 index 00000000..599a716f --- /dev/null +++ b/Source/ui_libretro/main_libretro.cpp @@ -0,0 +1,481 @@ +#include "libretro.h" + +#include "Log.h" +#include "AppConfig.h" +#include "PS2VM.h" + +#include "PS2VM_Preferences.h" +#include "GSH_OpenGL_Libretro.h" +#include "SH_LibreAudio.h" +#include "PH_Libretro_Input.h" + +#include "filesystem_def.h" +#include +#include + +#define LOG_NAME "LIBRETRO" + +static CPS2VM* m_virtualMachine = nullptr; +static bool first_run = false; + +retro_video_refresh_t g_video_cb; +retro_environment_t g_environ_cb; +retro_input_poll_t g_input_poll_cb; +retro_input_state_t g_input_state_cb; + +std::map g_ds2_to_retro_btn_map; +struct retro_hw_render_callback g_hw_render {}; + +int g_res_factor = 1; +CGSHandler::PRESENTATION_MODE g_presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FIT; +bool g_forceBilinearTextures = false; +bool g_audioEnabled = true; + +static std::vector m_vars = +{ + {"play_res_multi", "Resolution Multiplier; 1x|2x|4x|8x|16x" }, + {"play_presentation_mode", "Presentation Mode; Fit Screen|Fill Screen|Original Size"}, + {"play_bilinear_filtering", "Force Bilinear Filtering; false|true"}, + {"audio_enable", "Enable Audio; true|false" }, + {NULL, NULL}, +}; + +unsigned retro_api_version() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + return RETRO_API_VERSION; +} + +void SetupVideoHandler() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + auto gsHandler = m_virtualMachine->GetGSHandler(); + if(!gsHandler) + { + m_virtualMachine->CreateGSHandler(CGSH_OpenGL_Libretro::GetFactoryFunction()); + } + else + { + auto retro_gs = static_cast(gsHandler); + retro_gs->Reset(); + } + +} + +static void retro_context_destroy() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); +} + +static void retro_context_reset() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(m_virtualMachine) + { + SetupVideoHandler(); + } +} + +void SetupSoundHandler() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(m_virtualMachine) + { + m_virtualMachine->CreateSoundHandler(&CSH_LibreAudio::HandlerFactory); + } +} + +void SetupInputHandler() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(!m_virtualMachine->GetPadHandler()) + { + static struct retro_input_descriptor descDS2[] = + { + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Stick X"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Stick Y"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Stick X"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Stick Y"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Tringle"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3"}, + {0}, + }; + + g_environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, descDS2); + + static const struct retro_controller_description controllers[] = { + { "PS2 DualShock2", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) }, + }; + + static const struct retro_controller_info ports[] = { + { controllers, 1 }, + { NULL, 0 }, + }; + + g_environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); + + for(unsigned int i = 0; i < PS2::CControllerInfo::MAX_BUTTONS; i++) + { + auto ds2_button = static_cast(i); + auto retro_button = descDS2[i].id; + g_ds2_to_retro_btn_map[ds2_button] = retro_button; + } + + + m_virtualMachine->CreatePadHandler(CPH_Libretro_Input::GetFactoryFunction()); + } +} + +void retro_get_system_info(struct retro_system_info *info) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + *info = {}; + info->library_name = "Play!"; + info->library_version = PLAY_VERSION; + info->need_fullpath = true; + info->valid_extensions = "elf|iso|bin"; +} + +void retro_get_system_av_info(struct retro_system_av_info* info) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + *info = {}; + info->timing.fps = 60.0; + info->timing.sample_rate = 0; + info->geometry.base_width = 512 * 1; + info->geometry.base_height = (3.0 / 4.0) * 512; + info->geometry.max_width = 512 * 8; + info->geometry.max_height = (3.0 / 4.0) * (512 * 8); + info->geometry.aspect_ratio = 4.0 / 3.0; +} + + +void retro_set_video_refresh(retro_video_refresh_t cb) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + g_video_cb = cb; +} + +void retro_set_environment(retro_environment_t cb) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + g_environ_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + g_input_poll_cb = cb; +} + +void retro_set_input_state(retro_input_state_t cb) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + g_input_state_cb = cb; +} + +void retro_set_controller_port_device(unsigned port, unsigned device) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); +} + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); +} + +void retro_set_audio_sample(retro_audio_sample_t) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); +} + +unsigned retro_get_region(void) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + return RETRO_REGION_NTSC; +} + +size_t retro_serialize_size(void) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + return 0; +} + +bool retro_serialize(void *data, size_t size) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + (void)data; + (void)size; + return false; +} + +bool retro_unserialize(const void *data, size_t size) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + (void)data; + (void)size; + return false; +} + +void *retro_get_memory_data(unsigned id) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + (void)id; + return NULL; +} + +size_t retro_get_memory_size(unsigned id) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + (void)id; + return 0; +} + +void retro_cheat_reset(void) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + +} + +void retro_cheat_set(unsigned index, bool enabled, const char *code) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + (void)index; + (void)enabled; + (void)code; +} + + +void updateVars() +{ + for(int i = 0; i < m_vars.size() - 1; ++i) + { + auto item = m_vars[i]; + if(!item.key) + continue; + + + struct retro_variable var = {nullptr}; + var.key = item.key; + if(g_environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + bool videoUpdate = false; + switch(i) + { + case 0: + { + std::string val = var.value; + auto res_factor = std::atoi(val.substr(0, 1).c_str()); + if(res_factor != g_res_factor) + { + g_res_factor = res_factor; + CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSH_OPENGL_RESOLUTION_FACTOR, res_factor); + videoUpdate = true; + } + } + break; + case 1: + { + CGSHandler::PRESENTATION_MODE presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FIT; + + std::string val(var.value); + if(val == "Fill Screen") + presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FILL; + else if(val == "Original Size") + presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_ORIGINAL; + + if(presentation_mode != g_presentation_mode) + { + g_presentation_mode = presentation_mode; + CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSHANDLER_PRESENTATION_MODE, presentation_mode); + videoUpdate = true; + } + } + break; + case 2: + { + bool forceBilinearTextures = (std::string(var.value) == "true"); + if(forceBilinearTextures != g_forceBilinearTextures) + { + g_forceBilinearTextures = forceBilinearTextures; + CAppConfig::GetInstance().SetPreferenceBoolean(PREF_CGSH_OPENGL_FORCEBILINEARTEXTURES, forceBilinearTextures); + videoUpdate = true; + } + } + break; + case 3: + bool audioEnabled = (std::string(var.value) == "true"); + if(audioEnabled != g_audioEnabled) + { + g_audioEnabled = audioEnabled; + } + break; + } + + if(videoUpdate) + { + if(m_virtualMachine) + if(m_virtualMachine->GetGSHandler()) + static_cast(m_virtualMachine->GetGSHandler())->UpdatePresentation(); + } + } + } +} + +void checkVarsUpdates() +{ + static bool updates = true; + if(!updates) + g_environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updates); + + if(updates) + { + updateVars(); + } + updates = false; +} + +void retro_run() +{ + // CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + checkVarsUpdates(); + + if(!first_run) + { + if(m_virtualMachine) + { + // m_virtualMachine->Pause(); + m_virtualMachine->Reset(); + m_virtualMachine->m_ee->m_os->BootFromCDROM(); + m_virtualMachine->Resume(); + first_run = true; + CLog::GetInstance().Print(LOG_NAME, "%s\n", "Start Game"); + } + } + + if(m_virtualMachine) + if(m_virtualMachine->GetGSHandler()) + m_virtualMachine->GetGSHandler()->ProcessSingleFrame(); + +} + +void retro_reset(void) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(m_virtualMachine) + { + // m_virtualMachine->Pause(); + m_virtualMachine->Reset(); + m_virtualMachine->m_ee->m_os->BootFromCDROM(); + m_virtualMachine->Resume(); + CLog::GetInstance().Print(LOG_NAME, "%s\n", "Reset Game"); + } + first_run = false; +} + +bool retro_load_game(const retro_game_info* info) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + fs::path filePath = info->path; + CAppConfig::GetInstance().SetPreferencePath(PREF_PS2_CDROM0_PATH, filePath); + CAppConfig::GetInstance().Save(); + first_run = false; + + auto rgb = RETRO_PIXEL_FORMAT_XRGB8888; + g_environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb); + + g_hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; + g_hw_render.version_major = 3; + g_hw_render.version_minor = 2; + g_hw_render.context_reset = retro_context_reset; + g_hw_render.context_destroy = retro_context_destroy; + g_hw_render.cache_context = false; + g_hw_render.bottom_left_origin = true; + g_hw_render.depth = true; + g_environ_cb(RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT, nullptr); + + g_environ_cb(RETRO_ENVIRONMENT_SET_HW_RENDER, &g_hw_render); + + g_environ_cb(RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT, nullptr); + + g_environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)m_vars.data()); + + return true; +} + +void retro_unload_game(void) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); +} + +bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + return false; +} + +void retro_init() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + m_virtualMachine = new CPS2VM(); + m_virtualMachine->Initialize(); + + SetupInputHandler(); + SetupSoundHandler(); + first_run = false; +} + +void retro_deinit() +{ + CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + + if(m_virtualMachine) + { + // Note: since we're forced GS into running on this thread + // we need to clear its queue, to prevent it freezing the reset of the system during delete + auto gsHandler = m_virtualMachine->GetGSHandler(); + if(gsHandler) + static_cast(gsHandler)->Release(); + + m_virtualMachine->Pause(); + m_virtualMachine->DestroyPadHandler(); + m_virtualMachine->DestroyGSHandler(); + m_virtualMachine->DestroySoundHandler(); + m_virtualMachine->Destroy(); + delete m_virtualMachine; + m_virtualMachine = nullptr; + } +} From d3308e727b93e442cf801adfe5d5b00f4b3550fc Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:22:43 +0100 Subject: [PATCH 03/41] Cleanup: fix multiplier selection, set base resolution to PS2 default, use internal rendering resolution before rendering --- Source/ui_libretro/GSH_OpenGL_Libretro.cpp | 6 +++--- Source/ui_libretro/GSH_OpenGL_Libretro.h | 3 --- Source/ui_libretro/main_libretro.cpp | 12 ++++++------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp index 3748887b..e89a5b9a 100644 --- a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp +++ b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp @@ -57,8 +57,8 @@ void CGSH_OpenGL_Libretro::UpdatePresentationImpl() { PRESENTATION_PARAMS presentationParams; presentationParams.mode = g_presentation_mode; - presentationParams.windowWidth = m_framebufferWidth * g_res_factor; - presentationParams.windowHeight = (3.0 / 4.0) * m_framebufferHeight * g_res_factor; + presentationParams.windowWidth = GetCrtWidth() * g_res_factor; + presentationParams.windowHeight = GetCrtHeight() * g_res_factor; SetPresentationParams(presentationParams); NotifyPreferencesChanged(); @@ -109,6 +109,6 @@ void CGSH_OpenGL_Libretro::PresentBackbuffer() CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); if(g_video_cb) - g_video_cb(RETRO_HW_FRAME_BUFFER_VALID, m_framebufferWidth * g_res_factor, (3.0 / 4.0) * m_framebufferHeight * g_res_factor, 0); + g_video_cb(RETRO_HW_FRAME_BUFFER_VALID,GetCrtWidth() * g_res_factor, GetCrtHeight() * g_res_factor, 0); } diff --git a/Source/ui_libretro/GSH_OpenGL_Libretro.h b/Source/ui_libretro/GSH_OpenGL_Libretro.h index 02203d5a..99efbb42 100644 --- a/Source/ui_libretro/GSH_OpenGL_Libretro.h +++ b/Source/ui_libretro/GSH_OpenGL_Libretro.h @@ -21,7 +21,4 @@ public: private: void UpdatePresentationImpl(); - - GLint m_framebufferWidth = 512; - GLint m_framebufferHeight = 512; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 599a716f..397e89ff 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -33,7 +33,7 @@ bool g_audioEnabled = true; static std::vector m_vars = { - {"play_res_multi", "Resolution Multiplier; 1x|2x|4x|8x|16x" }, + {"play_res_multi", "Resolution Multiplier; 1x|2x|4x|8x" }, {"play_presentation_mode", "Presentation Mode; Fit Screen|Fill Screen|Original Size"}, {"play_bilinear_filtering", "Force Bilinear Filtering; false|true"}, {"audio_enable", "Enable Audio; true|false" }, @@ -163,10 +163,10 @@ void retro_get_system_av_info(struct retro_system_av_info* info) *info = {}; info->timing.fps = 60.0; info->timing.sample_rate = 0; - info->geometry.base_width = 512 * 1; - info->geometry.base_height = (3.0 / 4.0) * 512; - info->geometry.max_width = 512 * 8; - info->geometry.max_height = (3.0 / 4.0) * (512 * 8); + info->geometry.base_width = 640; + info->geometry.base_height = 448; + info->geometry.max_width = 640 * 8; + info->geometry.max_height = 448 * 8; info->geometry.aspect_ratio = 4.0 / 3.0; } @@ -293,7 +293,7 @@ void updateVars() case 0: { std::string val = var.value; - auto res_factor = std::atoi(val.substr(0, 1).c_str()); + auto res_factor = std::atoi(val.substr(0, -1).c_str()); if(res_factor != g_res_factor) { g_res_factor = res_factor; From 7b4ff10de1159b158b0d67fa8df9058ad7cd8b4b Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 21:35:52 +0100 Subject: [PATCH 04/41] libretro: pass ram, for cheat system --- Source/ui_libretro/main_libretro.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 397e89ff..b11c7cd2 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -246,7 +246,10 @@ void *retro_get_memory_data(unsigned id) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - (void)id; + if(id == RETRO_MEMORY_SYSTEM_RAM) + { + return m_virtualMachine->m_ee->m_ram; + } return NULL; } @@ -254,7 +257,10 @@ size_t retro_get_memory_size(unsigned id) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - (void)id; + if(id == RETRO_MEMORY_SYSTEM_RAM) + { + return PS2::EE_RAM_SIZE; + } return 0; } From 148bcf95fd7ada0ee8dc605cc7cd0ad3bc6403a4 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 21:58:58 +0100 Subject: [PATCH 05/41] libretro: add save state support --- Source/ui_libretro/main_libretro.cpp | 55 ++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index b11c7cd2..d4a70db3 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -9,6 +9,10 @@ #include "SH_LibreAudio.h" #include "PH_Libretro_Input.h" +#include "PathUtils.h" +#include "PtrStream.h" +#include "MemStream.h" + #include "filesystem_def.h" #include #include @@ -221,25 +225,62 @@ size_t retro_serialize_size(void) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - return 0; + return 40 * 1024 * 1024; } bool retro_serialize(void *data, size_t size) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - (void)data; - (void)size; - return false; + try + { + Framework::CMemStream stateStream; + Framework::CZipArchiveWriter archive; + + m_virtualMachine->m_ee->SaveState(archive); + m_virtualMachine->m_iop->SaveState(archive); + m_virtualMachine->m_ee->m_gs->SaveState(archive); + + archive.Write(stateStream); + stateStream.Seek(0, Framework::STREAM_SEEK_DIRECTION::STREAM_SEEK_SET); + stateStream.Read(data, size); + } + catch(...) + { + return false; + } + + return true; } bool retro_unserialize(const void *data, size_t size) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - (void)data; - (void)size; - return false; + try + { + Framework::CPtrStream stateStream(data, size); + Framework::CZipArchiveReader archive(stateStream); + + try + { + m_virtualMachine->m_ee->LoadState(archive); + m_virtualMachine->m_iop->LoadState(archive); + m_virtualMachine->m_ee->m_gs->LoadState(archive); + } + catch(...) + { + //Any error that occurs in the previous block is critical + throw; + } + } + catch(...) + { + return false; + } + + m_virtualMachine->OnMachineStateChange(); + return true; } void *retro_get_memory_data(unsigned id) From af14520c15ed7a96ffb9c6cf5e6a19fa6c820d87 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 21:38:32 +0100 Subject: [PATCH 06/41] Prepare for non windows builds --- Source/ui_libretro/CMakeLists.txt | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index ad01d6d7..c87b8008 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -36,16 +36,6 @@ if(NOT TARGET_PLATFORM_UNIX_AARCH64) list(APPEND PROJECT_LIBS glew_s) endif() -if(TARGET_PLATFORM_MACOS OR TARGET_PLATFORM_UNIX) - if(NOT TARGET sh_openal) - add_subdirectory( - ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/PsfPlayer/Source/SH_OpenAL - ${CMAKE_CURRENT_BINARY_DIR}/SH_OpenAL - ) - endif() - list(APPEND PROJECT_LIBS sh_openal) -endif() - set(SRC main_libretro.cpp GSH_OpenGL_Libretro.cpp @@ -55,11 +45,20 @@ set(SRC SH_LibreAudio.h ) -if(TARGET_PLATFORM_WIN32) +if(TARGET_PLATFORM_MACOS OR TARGET_PLATFORM_UNIX OR TARGET_PLATFORM_IOS) + if(NOT TARGET sh_openal) + add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/PsfPlayer/Source/SH_OpenAL + ${CMAKE_CURRENT_BINARY_DIR}/SH_OpenAL + ) + endif() + list(APPEND PROJECT_LIBS sh_openal) +elseif(TARGET_PLATFORM_WIN32) set(SRC ${SRC} ../../tools/PsfPlayer/Source/win32_ui/SH_WaveOut.cpp ) + list(APPEND PROJECT_LIBS "winmm.lib") endif() add_library(play_libretro SHARED ${SRC}) @@ -68,4 +67,4 @@ target_include_directories(play_libretro PRIVATE ../../ ${CMAKE_CURRENT_BINARY_DIR} ) -target_link_libraries(play_libretro ${PROJECT_LIBS} "winmm.lib") +target_link_libraries(play_libretro ${PROJECT_LIBS}) From 46d5203decee42db2bfcda0f930ddd706dd86d03 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:24:41 +0100 Subject: [PATCH 07/41] Update CMakelists.txt --- Source/ui_libretro/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index c87b8008..cc564c07 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -26,7 +26,7 @@ if(NOT TARGET gsh_opengl) endif() list(INSERT PROJECT_LIBS 0 gsh_opengl) -if(NOT TARGET_PLATFORM_UNIX_AARCH64) +if(NOT TARGET_PLATFORM_UNIX_AARCH64 AND (TARGET_PLATFORM_UNIX OR TARGET_PLATFORM_WIN32)) if (NOT TARGET glew_s) add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/../../../Dependencies/glew-2.0.0 @@ -67,4 +67,10 @@ target_include_directories(play_libretro PRIVATE ../../ ${CMAKE_CURRENT_BINARY_DIR} ) + target_link_libraries(play_libretro ${PROJECT_LIBS}) + +if(NOT MSVC) + add_compile_options("-fPIC") +endif() +set_target_properties(play_libretro PROPERTIES PREFIX "") From d2731a3a30056f6c4ffdcd2be38aa2bf5b756ae1 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:25:22 +0100 Subject: [PATCH 08/41] Prepare CMakeLists.txt for Android/iOS builds --- Source/ui_libretro/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index cc564c07..94635a13 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -68,6 +68,14 @@ target_include_directories(play_libretro PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +if(TARGET_PLATFORM_ANDROID) + list(APPEND PROJECT_LIBS android log OpenSLES GLESv3 EGL) +endif() + +if(TARGET_PLATFORM_IOS) + target_link_libraries(Play ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES -framework OpenAL") +endif() + target_link_libraries(play_libretro ${PROJECT_LIBS}) if(NOT MSVC) From bc51c5c0e83c54808998d2d10e911091277ba0e6 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:26:08 +0100 Subject: [PATCH 09/41] Cleanup --- Source/ui_libretro/SH_LibreAudio.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index 88748f08..23dcb66f 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -8,12 +8,13 @@ extern bool g_audioEnabled; - #ifdef _WIN32 -class CSH_LibreAudio : public CSH_WaveOut +#define _CSH_PARENT_ CSH_WaveOut #else -class CSH_LibreAudio : public CSH_OpenAL +#define _CSH_PARENT_ CSH_OpenAL #endif + +class CSH_LibreAudio : public _CSH_PARENT_ { public: CSH_LibreAudio() = default; @@ -27,11 +28,7 @@ public: { if(g_audioEnabled) { -#ifdef _WIN32 - CSH_WaveOut::Write(buffer, sampleCount, sampleRate); -#else - CSH_OpenAL::Write(buffer, sampleCount, sampleRate); -#endif + _CSH_PARENT_::Write(buffer, sampleCount, sampleRate); } }; }; From b8c5eefdac4ea9b6cc273dad32e5ee93d9755e89 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:26:58 +0100 Subject: [PATCH 10/41] Add Android Audio support --- Source/ui_libretro/SH_LibreAudio.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index 23dcb66f..ad2b74d2 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -2,6 +2,8 @@ #ifdef _WIN32 #include "../../tools/PsfPlayer/Source/win32_ui/SH_WaveOut.h" +#elif defined(__ANDROID__) +#include "../ui_android/SH_OpenSL.h" #else #include "tools/PsfPlayer/Source/SH_OpenAL.h" #endif @@ -10,6 +12,8 @@ extern bool g_audioEnabled; #ifdef _WIN32 #define _CSH_PARENT_ CSH_WaveOut +#elif defined(__ANDROID__) +#define _CSH_PARENT_ CSH_OpenSL #else #define _CSH_PARENT_ CSH_OpenAL #endif From 4ec4e59e7a3c15900f48dedd516e6f966e671557 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:35:40 +0100 Subject: [PATCH 11/41] Select correct OpenGL version --- Source/ui_libretro/main_libretro.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index d4a70db3..bdcec859 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -462,7 +462,12 @@ bool retro_load_game(const retro_game_info* info) auto rgb = RETRO_PIXEL_FORMAT_XRGB8888; g_environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb); +#ifdef GLES_COMPATIBILITY + g_hw_render.context_type = RETRO_HW_CONTEXT_OPENGLES3; +#else g_hw_render.context_type = RETRO_HW_CONTEXT_OPENGL_CORE; +#endif + g_hw_render.version_major = 3; g_hw_render.version_minor = 2; g_hw_render.context_reset = retro_context_reset; From 2c8444b45321144ee491bd8279f8bc75f6b796b3 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 12:39:28 +0100 Subject: [PATCH 12/41] Fix Android build --- Source/ui_libretro/CMakeLists.txt | 10 ++++++---- Source/ui_libretro/main_libretro.cpp | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index 94635a13..c69c748e 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -53,6 +53,12 @@ if(TARGET_PLATFORM_MACOS OR TARGET_PLATFORM_UNIX OR TARGET_PLATFORM_IOS) ) endif() list(APPEND PROJECT_LIBS sh_openal) +elseif(TARGET_PLATFORM_ANDROID) + set(SRC + ${SRC} + ${CMAKE_CURRENT_SOURCE_DIR}/../ui_android/SH_OpenSL.cpp + ) + list(APPEND PROJECT_LIBS android log OpenSLES GLESv3 EGL) elseif(TARGET_PLATFORM_WIN32) set(SRC ${SRC} @@ -68,10 +74,6 @@ target_include_directories(play_libretro PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) -if(TARGET_PLATFORM_ANDROID) - list(APPEND PROJECT_LIBS android log OpenSLES GLESv3 EGL) -endif() - if(TARGET_PLATFORM_IOS) target_link_libraries(Play ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES -framework OpenAL") endif() diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index bdcec859..2ac61c7b 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -441,6 +441,8 @@ void retro_reset(void) if(m_virtualMachine) { + if(!m_virtualMachine->GetGSHandler()) + SetupVideoHandler(); // m_virtualMachine->Pause(); m_virtualMachine->Reset(); m_virtualMachine->m_ee->m_os->BootFromCDROM(); From 1421ae2d274c771653d50ebf33002c37889ad73a Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 14:08:36 +0100 Subject: [PATCH 13/41] Fix iOS build --- Source/ui_libretro/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index c69c748e..526d725d 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -75,7 +75,7 @@ target_include_directories(play_libretro PRIVATE ) if(TARGET_PLATFORM_IOS) - target_link_libraries(Play ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES -framework OpenAL") + target_link_libraries(play_libretro ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES -framework OpenAL") endif() target_link_libraries(play_libretro ${PROJECT_LIBS}) From aab8dcab4bebfe3f9f96583740975805b052c4ae Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 20:59:56 +0100 Subject: [PATCH 14/41] Travis: build libretro cores --- .travis.sh | 37 +++++++++++++++++++++++++----------- .travis.yml | 14 ++++++++++++++ CMakeLists.txt | 11 ++++------- build_retro/android_build.sh | 29 ++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 build_retro/android_build.sh diff --git a/.travis.sh b/.travis.sh index b33a7071..6bb6b46b 100644 --- a/.travis.sh +++ b/.travis.sh @@ -42,10 +42,18 @@ travis_before_install() travis_script() { if [ "$TARGET_OS" = "Android" ]; then - pushd build_android - ./gradlew - ./gradlew assembleRelease - popd + if [ "$BUILD_LIBRETRO" = "yes" ]; then + export PATH=/opt/cmake-3.8.1-Linux-x86_64/bin/:$PATH + export ANDROID_NDK=/usr/local/android-sdk/ndk-bundle + pushd build_retro + bash android_build.sh + popd + else + pushd build_android + ./gradlew + ./gradlew assembleRelease + popd + fi elif [ "$TARGET_OS" = "Linux_Clang_Format" ]; then set +e find ./Source/ ./tools/ -iname *.h -o -iname *.cpp -o -iname *.m -iname *.mm | xargs clang-format-6.0 -i @@ -69,7 +77,7 @@ travis_script() if [ "$CXX" = "g++" ]; then export CXX="g++-9" CC="gcc-9"; fi source /opt/qt512/bin/qt512-env.sh || true export PATH=$PATH:/opt/qt512/lib/cmake - cmake .. -G"$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX=./appdir/usr; + cmake .. -G"$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX=./appdir/usr -DBUILD_LIBRETRO_CORE=yes; cmake --build . ctest cmake --build . --target install @@ -91,13 +99,13 @@ travis_script() fi elif [ "$TARGET_OS" = "OSX" ]; then export CMAKE_PREFIX_PATH="$(brew --prefix qt5)" - cmake .. -G"$BUILD_TYPE" + cmake .. -G"$BUILD_TYPE" -DBUILD_LIBRETRO_CORE=yes cmake --build . --config Release ctest -C Release $(brew --prefix qt5)/bin/macdeployqt Source/ui_qt/Release/Play.app appdmg ../installer_macosx/spec.json Play.dmg elif [ "$TARGET_OS" = "IOS" ]; then - cmake .. -G"$BUILD_TYPE" -DCMAKE_TOOLCHAIN_FILE=../deps/Dependencies/cmake-ios/ios.cmake -DTARGET_IOS=ON -DBUILD_PSFPLAYER=ON + cmake .. -G"$BUILD_TYPE" -DCMAKE_TOOLCHAIN_FILE=../deps/Dependencies/cmake-ios/ios.cmake -DTARGET_IOS=ON -DBUILD_PSFPLAYER=ON -DBUILD_LIBRETRO_CORE=yes cmake --build . --config Release codesign -s "-" Source/ui_ios/Release-iphoneos/Play.app pushd .. @@ -125,21 +133,28 @@ travis_before_deploy() if [ "$TARGET_OS" = "Linux" ]; then if [ "$TARGET_ARCH" = "x86_64" ]; then cp ../../build/Play*.AppImage . + cp ../../build/Source/ui_libretro/play_libretro.so play_libretro_linux-x86_64.so fi; fi; if [ "$TARGET_OS" = "Android" ]; then - cp ../../build_android/build/outputs/apk/release/Play-release-unsigned.apk . - export ANDROID_BUILD_TOOLS=$ANDROID_HOME/build-tools/28.0.3 - $ANDROID_BUILD_TOOLS/zipalign -v -p 4 Play-release-unsigned.apk Play-release.apk - $ANDROID_BUILD_TOOLS/apksigner sign --ks ../../installer_android/deploy.keystore --ks-key-alias deploy --ks-pass env:ANDROID_KEYSTORE_PASS --key-pass env:ANDROID_KEYSTORE_PASS Play-release.apk + if [ "$BUILD_LIBRETRO" = "yes" ]; then + cp ../../build_retro/play_* . + else + cp ../../build_android/build/outputs/apk/release/Play-release-unsigned.apk . + export ANDROID_BUILD_TOOLS=$ANDROID_HOME/build-tools/28.0.3 + $ANDROID_BUILD_TOOLS/zipalign -v -p 4 Play-release-unsigned.apk Play-release.apk + $ANDROID_BUILD_TOOLS/apksigner sign --ks ../../installer_android/deploy.keystore --ks-key-alias deploy --ks-pass env:ANDROID_KEYSTORE_PASS --key-pass env:ANDROID_KEYSTORE_PASS Play-release.apk + fi fi; if [ "$TARGET_OS" = "OSX" ]; then cp ../../build/Play.dmg . + cp ../../build/Source/ui_libretro/play_libretro.dylib play_libretro_macOS-x86_64.dylib fi; if [ "$TARGET_OS" = "IOS" ]; then cp ../../installer_ios/Play.ipa . cp ../../installer_ios/Play.deb . cp ../../installer_ios/Packages.bz2 . + cp ../../build/Source/ui_libretro/play_libretro.dylib play_libretro_iOS-FAT.dylib fi; popd popd diff --git a/.travis.yml b/.travis.yml index 5452fa6a..c7ea6333 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,20 @@ matrix: - build-tools-28.0.3 - android-28 - extra-android-m2repository + - os: linux + dist: trusty + language: android + sudo: required + env: + - TARGET_OS=Android + - BUILD_LIBRETRO=yes + android: + components: + - tools + - platform-tools + - build-tools-28.0.3 + - android-28 + - extra-android-m2repository language: cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a51dc15..97b82d37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,15 +50,12 @@ if(BUILD_PLAY) add_subdirectory(Source/ui_android/) endif(TARGET_PLATFORM_ANDROID) endif() - - if(BUILD_LIBRETRO_CORE) - if(NOT MSVC) - add_compile_options(-fPIC) - endif() - add_subdirectory(Source/ui_libretro) - endif() endif(BUILD_PLAY) +if(BUILD_LIBRETRO_CORE) + add_subdirectory(Source/ui_libretro) +endif() + if(BUILD_TESTS) enable_testing() diff --git a/build_retro/android_build.sh b/build_retro/android_build.sh new file mode 100644 index 00000000..22148cc7 --- /dev/null +++ b/build_retro/android_build.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +if [ -z "$ANDROID_NDK" ] +then + echo "Please set ANDROID_NDK and run again" + exit -1 +fi + +STRIP="${ANDROID_NDK}/toolchains/llvm/prebuilt/*/bin/llvm-strip" +ABI_LIST="arm64-v8a armeabi-v7a x86 x86_64" +for ABI in $ABI_LIST +do + mkdir "build_$ABI" + pushd "build_$ABI" + cmake ../.. -DBUILD_LIBRETRO_CORE=yes -DBUILD_PLAY=off \ + -GNinja \ + -DANDROID_ABI="${ABI}" \ + -DANDROID_NDK=${ANDROID_NDK} \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ + -DANDROID_NATIVE_API_LEVEL=23 \ + -DANDROID_TOOLCHAIN=clang + + cmake --build . --target play_libretro + + mv Source/ui_libretro/play_libretro.so ../play_libretro_${ABI}.so + ${STRIP} -strip-all ../play_libretro_${ABI}.so ../play_libretro_${ABI}_stripped.so + popd +done \ No newline at end of file From b165572ad5d8e18225bee8409693c8144d777761 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 21:00:19 +0100 Subject: [PATCH 15/41] Appveyor: Build an deploy Windows Libretro Core --- appveyor.yml | 2 ++ appveyor_build.cmd | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 08213a20..e83c8925 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,6 +30,8 @@ build_script: artifacts: - path: $(REPO_COMMIT_SHORT)\*.exe name: Binaries +- path: $(REPO_COMMIT_SHORT)\play_libretro.dll + name: Libretro_Core deploy: - provider: S3 access_key_id: AKIAJGVKEDYESR2BIP7Q diff --git a/appveyor_build.cmd b/appveyor_build.cmd index 0919e011..6a58a460 100644 --- a/appveyor_build.cmd +++ b/appveyor_build.cmd @@ -5,7 +5,8 @@ mkdir build cd build if "%BUILD_PLAY%" == "ON" ( - cmake .. -G"%BUILD_TYPE%" -T v141_xp -DUSE_QT=on -DCMAKE_PREFIX_PATH="C:\Qt\5.12\%QT_FLAVOR%" + set BUILD_DIR=%cd% + cmake .. -G"%BUILD_TYPE%" -T v141_xp -DUSE_QT=on -DBUILD_LIBRETRO_CORE=yes -DCMAKE_PREFIX_PATH="C:\Qt\5.12\%QT_FLAVOR%" if !errorlevel! neq 0 exit /b !errorlevel! cmake --build . --config %CONFIG_TYPE% @@ -21,6 +22,7 @@ if "%BUILD_PLAY%" == "ON" ( mkdir %REPO_COMMIT_SHORT% move installer_win32\*.exe %REPO_COMMIT_SHORT% + move build\Source\ui_libretro\Release\play_libretro.dll %REPO_COMMIT_SHORT% ) if "%BUILD_PSFPLAYER%" == "ON" ( From 282b6db31ac717dcbf70617b7f3854e038208af8 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 19:18:20 +0100 Subject: [PATCH 16/41] compile with PIC when building libretro cores... maybe enable it by default? --- CMakeLists.txt | 11 +++++++---- Source/ui_libretro/CMakeLists.txt | 4 ---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 97b82d37..0ef892af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,13 @@ set(PROJECT_LIBS) include(PrecompiledHeader) +if(BUILD_LIBRETRO_CORE) + if(NOT MSVC) + add_compile_options("-fPIC") + endif() + add_subdirectory(Source/ui_libretro) +endif() + if(BUILD_PLAY) if(TARGET_PLATFORM_UNIX OR TARGET_PLATFORM_MACOS OR TARGET_PLATFORM_WIN32 OR USE_QT) add_subdirectory(Source/ui_qt/) @@ -52,10 +59,6 @@ if(BUILD_PLAY) endif() endif(BUILD_PLAY) -if(BUILD_LIBRETRO_CORE) - add_subdirectory(Source/ui_libretro) -endif() - if(BUILD_TESTS) enable_testing() diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index 526d725d..f660e17e 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -79,8 +79,4 @@ if(TARGET_PLATFORM_IOS) endif() target_link_libraries(play_libretro ${PROJECT_LIBS}) - -if(NOT MSVC) - add_compile_options("-fPIC") -endif() set_target_properties(play_libretro PROPERTIES PREFIX "") From ab26440574614d30d28045e6dc6e3d1f073b7737 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 25 Jun 2019 19:04:04 +0100 Subject: [PATCH 17/41] Code style fixes. --- Source/ui_libretro/GSH_OpenGL_Libretro.cpp | 13 +- Source/ui_libretro/PH_Libretro_Input.cpp | 2 +- Source/ui_libretro/PH_Libretro_Input.h | 1 - Source/ui_libretro/SH_LibreAudio.h | 2 +- Source/ui_libretro/libretro.h | 2002 ++++++++++---------- Source/ui_libretro/main_libretro.cpp | 181 +- 6 files changed, 1097 insertions(+), 1104 deletions(-) diff --git a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp index e89a5b9a..00eac76d 100644 --- a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp +++ b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp @@ -5,7 +5,7 @@ extern int g_res_factor; extern CGSHandler::PRESENTATION_MODE g_presentation_mode; -extern retro_video_refresh_t g_video_cb; +extern retro_video_refresh_t g_video_cb; extern struct retro_hw_render_callback g_hw_render; CGSH_OpenGL_Libretro::CGSH_OpenGL_Libretro() @@ -39,9 +39,9 @@ void CGSH_OpenGL_Libretro::InitializeImpl() } #endif - + if(g_hw_render.get_current_framebuffer) - m_presentFramebuffer = g_hw_render.get_current_framebuffer(); + m_presentFramebuffer = g_hw_render.get_current_framebuffer(); UpdatePresentationImpl(); @@ -58,7 +58,7 @@ void CGSH_OpenGL_Libretro::UpdatePresentationImpl() PRESENTATION_PARAMS presentationParams; presentationParams.mode = g_presentation_mode; presentationParams.windowWidth = GetCrtWidth() * g_res_factor; - presentationParams.windowHeight = GetCrtHeight() * g_res_factor; + presentationParams.windowHeight = GetCrtHeight() * g_res_factor; SetPresentationParams(presentationParams); NotifyPreferencesChanged(); @@ -97,7 +97,7 @@ void CGSH_OpenGL_Libretro::FlipImpl() CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); if(g_hw_render.get_current_framebuffer) - m_presentFramebuffer = g_hw_render.get_current_framebuffer(); + m_presentFramebuffer = g_hw_render.get_current_framebuffer(); else return; @@ -109,6 +109,5 @@ void CGSH_OpenGL_Libretro::PresentBackbuffer() CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); if(g_video_cb) - g_video_cb(RETRO_HW_FRAME_BUFFER_VALID,GetCrtWidth() * g_res_factor, GetCrtHeight() * g_res_factor, 0); - + g_video_cb(RETRO_HW_FRAME_BUFFER_VALID, GetCrtWidth() * g_res_factor, GetCrtHeight() * g_res_factor, 0); } diff --git a/Source/ui_libretro/PH_Libretro_Input.cpp b/Source/ui_libretro/PH_Libretro_Input.cpp index 803b4908..8bcf6485 100644 --- a/Source/ui_libretro/PH_Libretro_Input.cpp +++ b/Source/ui_libretro/PH_Libretro_Input.cpp @@ -6,7 +6,7 @@ extern std::map g_ds2_to_retro_btn_map; void CPH_Libretro_Input::Update(uint8* ram) { - if(!g_input_poll_cb || !g_input_state_cb || g_ds2_to_retro_btn_map.size() == 0) + if(!g_input_poll_cb || !g_input_state_cb || g_ds2_to_retro_btn_map.size() == 0) return; g_input_poll_cb(); diff --git a/Source/ui_libretro/PH_Libretro_Input.h b/Source/ui_libretro/PH_Libretro_Input.h index 6ab70068..9af814a6 100644 --- a/Source/ui_libretro/PH_Libretro_Input.h +++ b/Source/ui_libretro/PH_Libretro_Input.h @@ -5,7 +5,6 @@ // #include "InputBindingManager.h" #include "libretro.h" - class CPH_Libretro_Input : public CPadHandler { public: diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index ad2b74d2..fb62a222 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -31,7 +31,7 @@ public: void Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) override { if(g_audioEnabled) - { + { _CSH_PARENT_::Write(buffer, sampleCount, sampleRate); } }; diff --git a/Source/ui_libretro/libretro.h b/Source/ui_libretro/libretro.h index c3a7d40e..4526bee4 100644 --- a/Source/ui_libretro/libretro.h +++ b/Source/ui_libretro/libretro.h @@ -28,7 +28,8 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #ifndef __cplusplus @@ -44,46 +45,46 @@ extern "C" { #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 +#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 +#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 +#define RETRO_API_VERSION 1 -/* + /* * Libretro's fundamental device abstractions. * * Libretro's input system consists of some standardized device types, @@ -97,17 +98,17 @@ extern "C" { * correctly to arbitrary controller layouts. */ -#define RETRO_DEVICE_TYPE_SHIFT 8 -#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) +#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 +#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 +#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). @@ -116,7 +117,7 @@ extern "C" { * The frontend must make sure not to interfere with its own hardware * mouse pointer. */ -#define RETRO_DEVICE_MOUSE 2 +#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 @@ -124,7 +125,7 @@ extern "C" { * For event/text based keyboard input, see * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. */ -#define RETRO_DEVICE_KEYBOARD 3 +#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) @@ -135,7 +136,7 @@ extern "C" { * directional pad. A forced off-screen shot can be requested for * auto-reloading function in some games. */ -#define RETRO_DEVICE_LIGHTGUN 4 +#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 @@ -146,7 +147,7 @@ extern "C" { * Buttons are returned in the range [0, 0x7fff]. * Only use ANALOG type when polling for analog values. */ -#define RETRO_DEVICE_ANALOG 5 +#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 @@ -178,304 +179,304 @@ extern "C" { * 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 +#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_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 /* Index / Id values for ANALOG device. */ -#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 -#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 -#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2 -#define RETRO_DEVICE_ID_ANALOG_X 0 -#define RETRO_DEVICE_ID_ANALOG_Y 1 +#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 +#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 +#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2 +#define RETRO_DEVICE_ID_ANALOG_X 0 +#define RETRO_DEVICE_ID_ANALOG_Y 1 /* Id values for MOUSE. */ -#define RETRO_DEVICE_ID_MOUSE_X 0 -#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 +#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 +#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*/ +#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_X 0 +#define RETRO_DEVICE_ID_POINTER_Y 1 +#define RETRO_DEVICE_ID_POINTER_PRESSED 2 /* Returned from retro_get_region(). */ -#define RETRO_REGION_NTSC 0 -#define RETRO_REGION_PAL 1 +#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, + /* 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 -}; + /* 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 +#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 +#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 +#define RETRO_MEMORY_RTC 1 /* System ram lets a frontend peek into a game systems main RAM. */ -#define RETRO_MEMORY_SYSTEM_RAM 2 +#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 +#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, + /* 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_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_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_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_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_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_LAST, - RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ -}; + RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ + }; -enum retro_mod -{ - RETROKMOD_NONE = 0x0000, + enum retro_mod + { + RETROKMOD_NONE = 0x0000, - RETROKMOD_SHIFT = 0x01, - RETROKMOD_CTRL = 0x02, - RETROKMOD_ALT = 0x04, - RETROKMOD_META = 0x08, + RETROKMOD_SHIFT = 0x01, + RETROKMOD_CTRL = 0x02, + RETROKMOD_ALT = 0x04, + RETROKMOD_META = 0x08, - RETROKMOD_NUMLOCK = 0x10, - RETROKMOD_CAPSLOCK = 0x20, - RETROKMOD_SCROLLOCK = 0x40, + RETROKMOD_NUMLOCK = 0x10, + RETROKMOD_CAPSLOCK = 0x20, + RETROKMOD_SCROLLOCK = 0x40, - RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ -}; + 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. */ @@ -484,41 +485,41 @@ enum retro_mod #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. - */ +#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), + /* 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_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 * -- + /* 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 @@ -535,7 +536,7 @@ enum retro_mod * If called, it should be called in retro_load_game(). */ #define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 - /* const char ** -- + /* 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. @@ -549,7 +550,7 @@ enum retro_mod * use the new GET_SAVE_DIRECTORY. */ #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 - /* const enum retro_pixel_format * -- + /* 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). @@ -560,7 +561,7 @@ enum retro_mod * retro_get_system_av_info(). */ #define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 - /* const struct retro_input_descriptor * -- + /* 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 @@ -569,18 +570,18 @@ enum retro_mod * to call it as early as possible. */ #define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 - /* const struct retro_keyboard_callback * -- + /* 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 * -- + /* 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 * -- + /* struct retro_hw_render_callback * -- * Sets an interface to let a libretro core render with * hardware acceleration. * Should be called in retro_load_game(). @@ -592,7 +593,7 @@ enum retro_mod * NULL to retro_video_refresh_t. */ #define RETRO_ENVIRONMENT_GET_VARIABLE 15 - /* struct retro_variable * -- + /* 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 @@ -600,7 +601,7 @@ enum retro_mod * 'data' will be set to a value or NULL. */ #define RETRO_ENVIRONMENT_SET_VARIABLES 16 - /* const struct retro_variable * -- + /* const struct retro_variable * -- * Allows an implementation to signal the environment * which variables it might want to check for later using * GET_VARIABLE. @@ -638,20 +639,20 @@ enum retro_mod * generally be displayed and stored as-is by the frontend. */ #define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 - /* bool * -- + /* 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 * -- + /* 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 ** -- + /* const char ** -- * Retrieves the absolute path from where this libretro * implementation was loaded. * NULL is returned if the libretro was loaded statically @@ -661,11 +662,11 @@ enum retro_mod * be loaded without ugly hacks. */ - /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. + /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. * It was not used by any known core at the time, * and was removed from the API. */ #define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 - /* const struct retro_frame_time_callback * -- + /* 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, @@ -674,7 +675,7 @@ enum retro_mod * in frame_time_callback.. */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 - /* const struct retro_audio_callback * -- + /* 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 @@ -700,14 +701,14 @@ enum retro_mod * SET_FRAME_TIME_CALLBACK. */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 - /* struct retro_rumble_interface * -- + /* 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 * -- + /* 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 @@ -716,7 +717,7 @@ enum retro_mod * Should only be called in retro_run(). */ #define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_sensor_interface * -- + /* 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, @@ -725,7 +726,7 @@ enum retro_mod * input_state_callback API. */ #define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_camera_callback * -- + /* 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. @@ -750,7 +751,7 @@ enum retro_mod * start and stop the camera driver. */ #define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 - /* struct retro_log_callback * -- + /* 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. @@ -760,13 +761,13 @@ enum retro_mod * log to stderr as desired. */ #define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 - /* struct retro_perf_callback * -- + /* 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 * -- + /* 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, @@ -774,7 +775,7 @@ enum retro_mod */ #define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */ #define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30 - /* const char ** -- + /* const char ** -- * Returns the "core assets" directory of the frontend. * This directory can be used to store specific assets that the * core relies upon, such as art assets, @@ -784,7 +785,7 @@ enum retro_mod * and it's up to the implementation to find a suitable directory. */ #define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 - /* const char ** -- + /* 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 @@ -799,7 +800,7 @@ enum retro_mod * GET_SYSTEM_DIRECTORY. */ #define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 - /* const struct retro_system_av_info * -- + /* 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 @@ -832,7 +833,7 @@ enum retro_mod * changed av_info struct. */ #define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 - /* const struct retro_get_proc_address_interface * -- + /* 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 @@ -843,7 +844,7 @@ enum retro_mod * **MUST** be called from within retro_set_environment(). */ #define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 - /* const struct retro_subsystem_info * -- + /* 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. @@ -862,7 +863,7 @@ enum retro_mod * **MUST** be called from within retro_set_environment(). */ #define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 - /* const struct retro_controller_info * -- + /* 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(). @@ -900,7 +901,7 @@ enum retro_mod * 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 * -- + /* 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. @@ -913,7 +914,7 @@ enum retro_mod * Can be called from retro_init and retro_load_game. */ #define RETRO_ENVIRONMENT_SET_GEOMETRY 37 - /* const struct retro_game_geometry * -- + /* 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. @@ -932,7 +933,7 @@ enum retro_mod * constant time. */ #define RETRO_ENVIRONMENT_GET_USERNAME 38 - /* const char ** + /* 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. @@ -941,12 +942,12 @@ enum retro_mod * a default username should be specified by the core. */ #define RETRO_ENVIRONMENT_GET_LANGUAGE 39 - /* unsigned * -- + /* 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 * -- + /* 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 @@ -976,7 +977,7 @@ enum retro_mod * writeable (and readable). */ #define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const struct retro_hw_render_interface ** -- + /* 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 @@ -987,7 +988,7 @@ enum retro_mod * the contents of the HW_RENDER_INTERFACE are invalidated. */ #define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* const bool * -- + /* 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. @@ -995,19 +996,19 @@ enum retro_mod * 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 * -- + /* 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 * -- + /* 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) * -- + /* 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. * @@ -1018,7 +1019,7 @@ enum retro_mod * being used. */ #define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_vfs_interface_info * -- + /* 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 @@ -1026,12 +1027,12 @@ enum retro_mod * It is recomended to do so in retro_set_environment */ #define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_led_interface * -- + /* 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 * -- + /* 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. @@ -1072,18 +1073,18 @@ enum retro_mod * * State will never be saved when using Hard Disable Audio. */ #define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* struct retro_midi_interface ** -- + /* 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 * -- + /* 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 * -- * Float value that lets us know what target refresh rate * is curently in use by the frontend. * @@ -1091,9 +1092,9 @@ enum retro_mod * refresh rate/framerate. */ -/* VFS functionality */ + /* VFS functionality */ -/* File paths: + /* 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). @@ -1108,229 +1109,229 @@ enum retro_mod * 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 + /* Opaque file handle * Introduced in VFS API v1 */ -struct retro_vfs_file_handle; + struct retro_vfs_file_handle; -/* Opaque directory handle + /* Opaque directory handle * Introduced in VFS API v3 */ -struct retro_vfs_dir_handle; + 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 */ +#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) +#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) +#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 +#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) +#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 + /* 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); + 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 + /* 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); + 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. + /* 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); + 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. + /* 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); + 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 + /* 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); + 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. + /* 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); + 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. + /* 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); + 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. + /* 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); + 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. + /* 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); + 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. + /* 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); + 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 + /* 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); + typedef int(RETRO_CALLCONV* retro_vfs_remove_t)(const char* path); -/* Rename the specified file. Returns 0 on success, -1 on failure + /* 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); + 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. + /* 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); + 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. + /* 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); + 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. + /* 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); + 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. + /* 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); + 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. + /* 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); + 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). + /* 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); + 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. + /* 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); + 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 + { + /* 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, + 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; + uint32_t required_interface_version; - /* Frontend writes interface pointer here. The frontend also sets the actual + /* 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; -}; + 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 -}; + 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 + /* 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; -}; + 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; -}; + 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. + /* 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); + typedef bool(RETRO_CALLCONV* retro_midi_input_enabled_t)(void); -/* Retrieves the current state of the MIDI output. + /* 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); + typedef bool(RETRO_CALLCONV* retro_midi_output_enabled_t)(void); -/* Reads next byte from the input stream. + /* 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); + typedef bool(RETRO_CALLCONV* retro_midi_read_t)(uint8_t* byte); -/* Writes byte to the output stream. + /* 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); + typedef bool(RETRO_CALLCONV* retro_midi_write_t)(uint8_t byte, uint32_t delta_time); -/* Flushes previously written data. + /* Flushes previously written data. * Returns true if successful, false otherwise. */ -typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void); + 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; -}; + 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 -}; + 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 + /* 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; -}; + 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 @@ -1356,22 +1357,22 @@ struct retro_hw_render_context_negotiation_interface * 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; +#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. + /* 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. * @@ -1384,39 +1385,39 @@ struct retro_memory_descriptor * 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; + void* ptr; + size_t offset; - /* This is the location in the emulated address space + /* This is the location in the emulated address space * where the mapping starts. */ - size_t start; + size_t start; - /* Which bits must be same as in 'start' for this mapping to apply. + /* 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; + size_t select; - /* If this is nonzero, the set bits are assumed not connected to the + /* If this is nonzero, the set bits are assumed not connected to the * memory chip's address pins. */ - size_t disconnect; + size_t disconnect; - /* This one tells the size of the current memory area. + /* 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; + size_t len; - /* To go from emulated address to physical address, the following + /* To go from emulated address to physical address, the following * order applies: * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. */ - /* The address space name must consist of only a-zA-Z0-9_-, + /* The address space name must consist of only a-zA-Z0-9_-, * should be as short as feasible (maximum length is 8 plus the NUL), * and may not be any other address space plus one or more 0-9A-F * at the end. @@ -1441,28 +1442,28 @@ struct retro_memory_descriptor * 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; + const char* addrspace; - /* TODO: When finalizing this one, add a description field, which should be + /* 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 + /* 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 + /* 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. + /* 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 + /* 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 @@ -1471,11 +1472,11 @@ struct retro_memory_descriptor * 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 + /* TODO: Some of those flags are unused and/or don't really make sense. Clean * them up. */ -}; + }; -/* The frontend may use the largest value of 'start'+'select' in a + /* The frontend may use the largest value of 'start'+'select' in a * certain namespace to infer the size of the address space. * * If the address space is larger than that, a mapping with .ptr=NULL @@ -1513,98 +1514,98 @@ struct retro_memory_descriptor * .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_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 + 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; + const char* desc; - /* Device type passed to retro_set_controller_port_device(). If the device + /* 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; -}; + unsigned id; + }; -struct retro_controller_info -{ - const struct retro_controller_description *types; - unsigned num_types; -}; + 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; + 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 + /* The memory type for retro_get_memory(). This should be at * least 0x100 to avoid conflict with standardized * libretro memory types. */ - unsigned type; -}; + unsigned type; + }; -struct retro_subsystem_rom_info -{ - /* Describes what the content is (SGB BIOS, GB ROM, etc). */ - const char *desc; + 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(). */ + const char* valid_extensions; - /* Same definition as retro_get_system_info(). */ - bool need_fullpath; + /* Same definition as retro_get_system_info(). */ + bool need_fullpath; - /* Same definition as retro_get_system_info(). */ - bool block_extract; + /* Same definition as retro_get_system_info(). */ + bool block_extract; - /* This is set if the content is required to load a game. + /* This is set if the content is required to load a game. * If this is set to false, a zeroed-out retro_game_info can be passed. */ - bool required; + bool required; - /* Content can have multiple associated persistent + /* Content can have multiple associated persistent * memory types (retro_get_memory()). */ - const struct retro_subsystem_memory_info *memory; - unsigned num_memory; -}; + 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; + 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. + /* 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; + const char* ident; - /* Infos for each content file. The first entry is assumed to be the + /* Infos for each content file. The first entry is assumed to be the * "most significant" content for frontend purposes. * E.g. with Super GameBoy, the first content should be the GameBoy ROM, * 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; + const struct retro_subsystem_rom_info* roms; - /* Number of content files associated with a subsystem. */ - unsigned num_roms; + /* Number of content files associated with a subsystem. */ + unsigned num_roms; - /* The type passed to retro_load_game_special(). */ - unsigned id; -}; + /* The type passed to retro_load_game_special(). */ + unsigned id; + }; -typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); + typedef void(RETRO_CALLCONV* retro_proc_address_t)(void); -/* libretro API extension functions: + /* libretro API extension functions: * (None here so far). * * Get a symbol from a libretro core. @@ -1618,104 +1619,104 @@ typedef void (RETRO_CALLCONV *retro_proc_address_t)(void); * 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); + 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; -}; + 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, + enum retro_log_level + { + RETRO_LOG_DEBUG = 0, + RETRO_LOG_INFO, + RETRO_LOG_WARN, + RETRO_LOG_ERROR, - RETRO_LOG_DUMMY = INT_MAX -}; + 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, ...); + /* 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; -}; + 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) +#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; + 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; + 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; -}; + bool registered; + }; -/* Returns current time in microseconds. + /* 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); + typedef retro_time_t(RETRO_CALLCONV* retro_perf_get_time_usec_t)(void); -/* A simple counter. Usually nanoseconds, but can also be CPU cycles. + /* A simple counter. Usually nanoseconds, but can also be CPU cycles. * Can be used directly if desired (when creating a more sophisticated * performance counter system). * */ -typedef retro_perf_tick_t (RETRO_CALLCONV *retro_perf_get_counter_t)(void); + typedef retro_perf_tick_t(RETRO_CALLCONV* retro_perf_get_counter_t)(void); -/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ -typedef uint64_t (RETRO_CALLCONV *retro_get_cpu_features_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. + /* 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); + typedef void(RETRO_CALLCONV* retro_perf_log_t)(void); -/* Register a performance counter. + /* Register a performance counter. * ident field must be set with a discrete value and other values in * 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); + 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); + /* 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); + /* 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. + /* 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)) @@ -1748,73 +1749,73 @@ typedef void (RETRO_CALLCONV *retro_perf_stop_t)(struct retro_perf_counter *coun * } */ -struct retro_perf_callback -{ - retro_perf_get_time_usec_t get_time_usec; - retro_get_cpu_features_t get_cpu_features; + 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; -}; + 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. + /* 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, + enum retro_sensor_action + { + RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + RETRO_SENSOR_ACCELEROMETER_DISABLE, - RETRO_SENSOR_DUMMY = INT_MAX -}; + 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 -typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port, - enum retro_sensor_action action, unsigned rate); + 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); + 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; -}; + 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, + enum retro_camera_buffer + { + RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, + RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, - RETRO_CAMERA_BUFFER_DUMMY = INT_MAX -}; + 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); + /* 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); + /* Stops the camera driver. Can only be called in retro_run(). */ + typedef void(RETRO_CALLCONV* retro_camera_stop_t)(void); -/* Callback which signals when the camera driver is initialized + /* Callback which signals when the camera driver is initialized * and/or deinitialized. * retro_camera_start_t can be called in initialized callback. */ -typedef void (RETRO_CALLCONV *retro_camera_lifetime_status_t)(void); + typedef void(RETRO_CALLCONV* retro_camera_lifetime_status_t)(void); -/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. + /* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. * Width, height and pitch are similar to retro_video_refresh_t. * 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); + 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. + /* 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 @@ -1832,44 +1833,44 @@ typedef void (RETRO_CALLCONV *retro_camera_frame_raw_framebuffer_t)(const uint32 * 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); + 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. + 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; + uint64_t caps; - /* Desired resolution for camera. Is only used as a hint. */ - unsigned width; - unsigned height; + /* 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 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 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 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 + /* 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; + retro_camera_lifetime_status_t initialized; - /* Set by libretro core. Called right before camera driver is + /* Set by libretro core. Called right before camera driver is * deinitialized. * Can be NULL, in which this callback is not called. */ - retro_camera_lifetime_status_t deinitialized; -}; + retro_camera_lifetime_status_t deinitialized; + }; -/* Sets the interval of time and/or distance at which to update/poll + /* Sets the interval of time and/or distance at which to update/poll * location-based data. * * To ensure compatibility with all location-based implementations, @@ -1878,82 +1879,82 @@ struct retro_camera_callback * 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); + 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 + /* 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); + typedef bool(RETRO_CALLCONV* retro_location_start_t)(void); -/* Stop location services. The device will stop listening for changes + /* Stop location services. The device will stop listening for changes * to the current location. */ -typedef void (RETRO_CALLCONV *retro_location_stop_t)(void); + typedef void(RETRO_CALLCONV* retro_location_stop_t)(void); -/* Get the position of the current location. Will set parameters to + /* Get the position of the current location. Will set parameters to * 0 if no new location update has happened since the last time. */ -typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon, - double *horiz_accuracy, double *vert_accuracy); + typedef bool(RETRO_CALLCONV* retro_location_get_position_t)(double* lat, double* lon, + double* horiz_accuracy, double* vert_accuracy); -/* Callback which signals when the location driver is initialized + /* Callback which signals when the location driver is initialized * and/or deinitialized. * retro_location_start_t can be called in initialized callback. */ -typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void); + 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; + 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; -}; + retro_location_lifetime_status_t initialized; + retro_location_lifetime_status_t deinitialized; + }; -enum retro_rumble_effect -{ - RETRO_RUMBLE_STRONG = 0, - RETRO_RUMBLE_WEAK = 1, + enum retro_rumble_effect + { + RETRO_RUMBLE_STRONG = 0, + RETRO_RUMBLE_WEAK = 1, - RETRO_RUMBLE_DUMMY = INT_MAX -}; + RETRO_RUMBLE_DUMMY = INT_MAX + }; -/* Sets rumble state for joypad plugged in port 'port'. + /* Sets rumble state for joypad plugged in port 'port'. * Rumble effects are controlled independently, * and setting e.g. strong rumble does not override weak rumble. * Strength has a range of [0, 0xffff]. * * Returns true if rumble state request was honored. * 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); + 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; -}; + 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); + /* Notifies libretro that audio data should be written. */ + typedef void(RETRO_CALLCONV* retro_audio_callback_t)(void); -/* True: Audio driver in frontend is active, and callback is + /* True: Audio driver in frontend is active, and callback is * expected to be called regularily. * False: Audio driver in frontend is paused or inactive. * Audio callback will not be called until set_state has been * called with true. * Initial state is false (inactive). */ -typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled); + 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; -}; + 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 + /* 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. @@ -1961,23 +1962,23 @@ struct retro_audio_callback * 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 + 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; -}; + 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. + /* 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. @@ -1986,48 +1987,48 @@ struct retro_frame_time_callback * Also called first time video driver is initialized, * allowing libretro core to initialize resources. */ -typedef void (RETRO_CALLCONV *retro_hw_context_reset_t)(void); + typedef void(RETRO_CALLCONV* retro_hw_context_reset_t)(void); -/* Gets current framebuffer which is to be rendered to. + /* Gets current framebuffer which is to be rendered to. * Could change every frame potentially. */ -typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void); + typedef uintptr_t(RETRO_CALLCONV* retro_hw_get_current_framebuffer_t)(void); -/* Get a symbol from HW context. */ -typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym); + /* 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/ + 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, + 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, + RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, - /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ - RETRO_HW_CONTEXT_VULKAN = 6, + /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */ + RETRO_HW_CONTEXT_VULKAN = 6, - /* Direct3D, set version_major to select the type of interface + /* 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_DIRECT3D = 7, - RETRO_HW_CONTEXT_DUMMY = INT_MAX -}; + 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; + 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. + /* 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 @@ -2039,57 +2040,57 @@ struct retro_hw_render_callback * 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; + retro_hw_context_reset_t context_reset; - /* Set by frontend. + /* Set by frontend. * TODO: This is rather obsolete. The frontend should not * be providing preallocated framebuffers. */ - retro_hw_get_current_framebuffer_t get_current_framebuffer; + retro_hw_get_current_framebuffer_t get_current_framebuffer; - /* Set by frontend. + /* Set by frontend. * Can return all relevant functions, including glClear on Windows. */ - retro_hw_get_proc_address_t get_proc_address; + retro_hw_get_proc_address_t get_proc_address; - /* Set if render buffers should have depth component attached. + /* Set if render buffers should have depth component attached. * TODO: Obsolete. */ - bool depth; + bool depth; - /* Set if stencil buffers should be attached. + /* Set if stencil buffers should be attached. * TODO: Obsolete. */ - bool stencil; + bool stencil; - /* If depth and stencil are true, a packed 24/8 buffer will be added. + /* If depth and stencil are true, a packed 24/8 buffer will be added. * Only attaching stencil is invalid and will be ignored. */ - /* Use conventional bottom-left origin convention. If false, + /* Use conventional bottom-left origin convention. If false, * standard libretro top-left origin semantics are used. * TODO: Move to GL specific interface. */ - bool bottom_left_origin; + bool bottom_left_origin; - /* Major version number for core GL context or GLES 3.1+. */ - unsigned version_major; + /* 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; + /* Minor version number for core GL context or GLES 3.1+. */ + unsigned version_minor; - /* If this is true, the frontend will go very far to avoid + /* If this is true, the frontend will go very far to avoid * resetting context in scenarios like toggling fullscreen, etc. * TODO: Obsolete? Maybe frontend should just always assume this ... */ - bool cache_context; + bool cache_context; - /* The reset callback might still be called in extreme situations + /* The reset callback might still be called in extreme situations * such as if the context is lost beyond recovery. * * For optimal stability, set this to false, and allow context to be * reset at any time. */ - /* A callback to be called before the context is destroyed in a + /* A callback to be called before the context is destroyed in a * controlled way by the frontend. */ - retro_hw_context_reset_t context_destroy; + retro_hw_context_reset_t context_destroy; - /* OpenGL resources can be deinitialized cleanly at this step. + /* 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. * @@ -2103,11 +2104,11 @@ struct retro_hw_render_callback * resources in the subsequent context_reset. */ - /* Creates a debug context. */ - bool debug_context; -}; + /* Creates a debug context. */ + bool debug_context; + }; -/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + /* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. * Called by the frontend in response to keyboard events. * down is set if the key is being pressed, or false if it is being released. * keycode is the RETROK value of the char. @@ -2124,15 +2125,15 @@ struct retro_hw_render_callback * 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); + 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; -}; + struct retro_keyboard_callback + { + retro_keyboard_event_t callback; + }; -/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. + /* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. * Should be set for implementations which can swap out multiple disk * images in runtime. * @@ -2145,31 +2146,31 @@ struct retro_keyboard_callback * with set_eject_state(false). */ -/* If ejected is true, "ejects" the virtual disk tray. + /* If ejected is true, "ejects" the virtual disk tray. * When ejected, the disk image index can be set. */ -typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected); + typedef bool(RETRO_CALLCONV* retro_set_eject_state_t)(bool ejected); -/* Gets current eject state. The initial state is 'not ejected'. */ -typedef bool (RETRO_CALLCONV *retro_get_eject_state_t)(void); + /* 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. + /* 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); + typedef unsigned(RETRO_CALLCONV* retro_get_image_index_t)(void); -/* Sets image index. Can only be called when disk is ejected. + /* Sets image index. Can only be called when disk is ejected. * The implementation supports setting "no disk" by using an * index >= get_num_images(). */ -typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index); + typedef bool(RETRO_CALLCONV* retro_set_image_index_t)(unsigned index); -/* Gets total number of images which are available to use. */ -typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void); + /* Gets total number of images which are available to use. */ + typedef unsigned(RETRO_CALLCONV* retro_get_num_images_t)(void); -struct retro_game_info; + struct retro_game_info; -/* Replaces the disk image associated with index. + /* 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. * @@ -2181,92 +2182,92 @@ struct retro_game_info; * 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); + 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. + /* 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); + typedef bool(RETRO_CALLCONV* retro_add_image_index_t)(void); -struct retro_disk_control_callback -{ - retro_set_eject_state_t set_eject_state; - retro_get_eject_state_t get_eject_state; + 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_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; -}; + retro_replace_image_index_t replace_image_index; + retro_add_image_index_t add_image_index; + }; -enum retro_pixel_format -{ - /* 0RGB1555, native endian. + 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, + RETRO_PIXEL_FORMAT_0RGB1555 = 0, - /* XRGB8888, native endian. + /* XRGB8888, native endian. * X bits are ignored. */ - RETRO_PIXEL_FORMAT_XRGB8888 = 1, + RETRO_PIXEL_FORMAT_XRGB8888 = 1, - /* RGB565, native endian. + /* 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, + RETRO_PIXEL_FORMAT_RGB565 = 2, - /* Ensure sizeof() == sizeof(int). */ - RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX -}; + /* 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. */ -}; + 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 + /* 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; + struct retro_input_descriptor + { + /* Associates given parameters with a description. */ + unsigned port; + unsigned device; + unsigned index; + unsigned id; - /* Human readable description for parameters. + /* Human readable description for parameters. * The pointer must remain valid until * retro_unload_game() is called. */ - const char *description; -}; + const char* description; + }; -struct retro_system_info -{ - /* All pointers are owned by libretro implementation, and pointers must + 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 + 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* library_version; /* Descriptive version of core. */ - const char *valid_extensions; /* A string listing probably content + 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 + /* 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. * @@ -2286,59 +2287,59 @@ struct retro_system_info * - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY * - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY */ - bool need_fullpath; + bool need_fullpath; - /* If true, the frontend is not allowed to extract any archives before + /* If true, the frontend is not allowed to extract any archives before * loading the real content. * Necessary for certain libretro implementations that load games * from zipped archives. */ - bool block_extract; -}; + 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. */ + 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 + 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_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_system_av_info + { + struct retro_game_geometry geometry; + struct retro_system_timing timing; + }; -struct retro_variable -{ - /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + 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; + const char* key; - /* Value to be obtained. If key does not exist, it is set to NULL. */ - const char *value; -}; + /* Value to be obtained. If key does not exist, it is set to NULL. */ + const char* value; + }; -struct retro_game_info -{ - const char *path; /* Path to game, UTF-8 encoded. + 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`. @@ -2346,49 +2347,49 @@ struct retro_game_info * of passing NULL, which will help more cores to succeed. * retro_system_info::need_fullpath requires * that this path is valid. */ - const void *data; /* Memory buffer of loaded game. Will be NULL + const void* data; /* Memory buffer of loaded game. Will be NULL * if need_fullpath was set. */ - size_t size; /* Size of memory buffer. */ - const char *meta; /* String of implementation specific meta-data. */ -}; + 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. */ + /* 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. */ + /* The core will read from retro_framebuffer::data. */ #define RETRO_MEMORY_TYPE_CACHED (1 << 0) - /* The memory in data is cached. + /* 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. + 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, + 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. + 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. + 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. + unsigned memory_flags; /* Flags telling core how the memory has been mapped. RETRO_MEMORY_TYPE_* flags. Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */ -}; + }; -/* Callbacks */ + /* Callbacks */ -/* Environment callback. Gives implementations a way of performing + /* Environment callback. Gives implementations a way of performing * uncommon tasks. Extensible. */ -typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); + typedef bool(RETRO_CALLCONV* retro_environment_t)(unsigned cmd, void* data); -/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian + /* Render a frame. Pixel format is 15-bit 0RGB1555 native endian * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). * * Width and height specify dimensions of buffer. @@ -2399,71 +2400,71 @@ typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data); * 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); + typedef void(RETRO_CALLCONV* retro_video_refresh_t)(const void* data, unsigned width, + unsigned height, size_t pitch); -/* Renders a single audio frame. Should only be used if implementation + /* Renders a single audio frame. Should only be used if implementation * generates a single sample at a time. * Format is signed 16-bit native endian. */ -typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right); + typedef void(RETRO_CALLCONV* retro_audio_sample_t)(int16_t left, int16_t right); -/* Renders multiple audio frames in one go. + /* Renders multiple audio frames in one go. * * 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); + 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); + /* Polls input. */ + typedef void(RETRO_CALLCONV* retro_input_poll_t)(void); -/* Queries for input for player 'port'. device will be masked with + /* Queries for input for player 'port'. device will be masked with * RETRO_DEVICE_MASK. * * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that * 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); + typedef int16_t(RETRO_CALLCONV* retro_input_state_t)(unsigned port, unsigned device, + unsigned index, unsigned id); -/* Sets callbacks. retro_set_environment() is guaranteed to be called + /* Sets callbacks. retro_set_environment() is guaranteed to be called * before retro_init(). * * The rest of the set_* functions are guaranteed to have been called * 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); + 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); + /* 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 + /* Must return RETRO_API_VERSION. Used to validate ABI compatibility * when the API is revised. */ -RETRO_API unsigned retro_api_version(void); + RETRO_API unsigned retro_api_version(void); -/* Gets statically known system info. Pointers provided in *info + /* Gets statically known system info. Pointers provided in *info * must be statically allocated. * Can be called at any time, even before retro_init(). */ -RETRO_API void retro_get_system_info(struct retro_system_info *info); + RETRO_API void retro_get_system_info(struct retro_system_info* info); -/* Gets information about system audio/video timings and geometry. + /* Gets information about system audio/video timings and geometry. * Can be called only after retro_load_game() has successfully completed. * 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); + RETRO_API void retro_get_system_av_info(struct retro_system_av_info* info); -/* Sets device to be used for player 'port'. + /* Sets device to be used for player 'port'. * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all * available ports. * Setting a particular device type is not a guarantee that libretro cores @@ -2477,12 +2478,12 @@ RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info); * 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); + RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device); -/* Resets the current game. */ -RETRO_API void retro_reset(void); + /* Resets the current game. */ + RETRO_API void retro_reset(void); -/* Runs the game for one video frame. + /* Runs the game for one video frame. * During retro_run(), input_poll callback must be called at least once. * * If a frame is not rendered for reasons where a game "dropped" a frame, @@ -2490,45 +2491,44 @@ RETRO_API void retro_reset(void); * 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); + RETRO_API void retro_run(void); -/* Returns the amount of data the implementation requires to serialize + /* Returns the amount of data the implementation requires to serialize * internal state (save states). * Between calls to retro_load_game() and retro_unload_game(), the * returned size is never allowed to be larger than a previous returned * value, to ensure that the frontend can allocate a save state buffer once. */ -RETRO_API size_t retro_serialize_size(void); + RETRO_API size_t retro_serialize_size(void); -/* Serializes internal state. If failed, or size is lower than + /* Serializes internal state. If failed, or size is lower than * retro_serialize_size(), it should return false, true otherwise. */ -RETRO_API bool retro_serialize(void *data, size_t size); -RETRO_API bool retro_unserialize(const void *data, size_t size); + 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); + RETRO_API void retro_cheat_reset(void); + RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char* code); -/* Loads a game. + /* Loads a game. * Return true to indicate successful loading and false to indicate load failure. */ -RETRO_API bool retro_load_game(const struct retro_game_info *game); + RETRO_API bool retro_load_game(const struct retro_game_info* game); -/* Loads a "special" kind of game. Should not be used, + /* Loads a "special" kind of game. Should not be used, * except in extreme cases. */ -RETRO_API bool retro_load_game_special( - unsigned game_type, - const struct retro_game_info *info, size_t num_info -); + 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); + /* 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 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); + /* 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 } diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 2ac61c7b..9034289e 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -28,7 +28,9 @@ retro_input_poll_t g_input_poll_cb; retro_input_state_t g_input_state_cb; std::map g_ds2_to_retro_btn_map; -struct retro_hw_render_callback g_hw_render {}; +struct retro_hw_render_callback g_hw_render +{ +}; int g_res_factor = 1; CGSHandler::PRESENTATION_MODE g_presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FIT; @@ -36,12 +38,12 @@ bool g_forceBilinearTextures = false; bool g_audioEnabled = true; static std::vector m_vars = -{ - {"play_res_multi", "Resolution Multiplier; 1x|2x|4x|8x" }, - {"play_presentation_mode", "Presentation Mode; Fit Screen|Fill Screen|Original Size"}, - {"play_bilinear_filtering", "Force Bilinear Filtering; false|true"}, - {"audio_enable", "Enable Audio; true|false" }, - {NULL, NULL}, + { + {"play_res_multi", "Resolution Multiplier; 1x|2x|4x|8x"}, + {"play_presentation_mode", "Presentation Mode; Fit Screen|Fill Screen|Original Size"}, + {"play_bilinear_filtering", "Force Bilinear Filtering; false|true"}, + {"audio_enable", "Enable Audio; true|false"}, + {NULL, NULL}, }; unsigned retro_api_version() @@ -65,7 +67,6 @@ void SetupVideoHandler() auto retro_gs = static_cast(gsHandler); retro_gs->Reset(); } - } static void retro_context_destroy() @@ -100,39 +101,39 @@ void SetupInputHandler() if(!m_virtualMachine->GetPadHandler()) { static struct retro_input_descriptor descDS2[] = - { - {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Stick X"}, - {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Stick Y"}, - {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Stick X"}, - {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Stick Y"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Tringle"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2"}, - {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3"}, - {0}, - }; + { + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Stick X"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Stick Y"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Stick X"}, + {0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Stick Y"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Down"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Tringle"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2"}, + {0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3"}, + {0}, + }; g_environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, descDS2); static const struct retro_controller_description controllers[] = { - { "PS2 DualShock2", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) }, + {"PS2 DualShock2", RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0)}, }; static const struct retro_controller_info ports[] = { - { controllers, 1 }, - { NULL, 0 }, + {controllers, 1}, + {NULL, 0}, }; g_environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); @@ -144,12 +145,11 @@ void SetupInputHandler() g_ds2_to_retro_btn_map[ds2_button] = retro_button; } - m_virtualMachine->CreatePadHandler(CPH_Libretro_Input::GetFactoryFunction()); } } -void retro_get_system_info(struct retro_system_info *info) +void retro_get_system_info(struct retro_system_info* info) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); @@ -174,7 +174,6 @@ void retro_get_system_av_info(struct retro_system_av_info* info) info->geometry.aspect_ratio = 4.0 / 3.0; } - void retro_set_video_refresh(retro_video_refresh_t cb) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); @@ -228,7 +227,7 @@ size_t retro_serialize_size(void) return 40 * 1024 * 1024; } -bool retro_serialize(void *data, size_t size) +bool retro_serialize(void* data, size_t size) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); @@ -253,7 +252,7 @@ bool retro_serialize(void *data, size_t size) return true; } -bool retro_unserialize(const void *data, size_t size) +bool retro_unserialize(const void* data, size_t size) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); @@ -283,7 +282,7 @@ bool retro_unserialize(const void *data, size_t size) return true; } -void *retro_get_memory_data(unsigned id) +void* retro_get_memory_data(unsigned id) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); @@ -308,10 +307,9 @@ size_t retro_get_memory_size(unsigned id) void retro_cheat_reset(void) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - } -void retro_cheat_set(unsigned index, bool enabled, const char *code) +void retro_cheat_set(unsigned index, bool enabled, const char* code) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); @@ -320,7 +318,6 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) (void)code; } - void updateVars() { for(int i = 0; i < m_vars.size() - 1; ++i) @@ -329,7 +326,6 @@ void updateVars() if(!item.key) continue; - struct retro_variable var = {nullptr}; var.key = item.key; if(g_environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) @@ -337,54 +333,54 @@ void updateVars() bool videoUpdate = false; switch(i) { - case 0: - { - std::string val = var.value; - auto res_factor = std::atoi(val.substr(0, -1).c_str()); - if(res_factor != g_res_factor) - { - g_res_factor = res_factor; - CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSH_OPENGL_RESOLUTION_FACTOR, res_factor); - videoUpdate = true; - } - } - break; - case 1: - { - CGSHandler::PRESENTATION_MODE presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FIT; + case 0: + { + std::string val = var.value; + auto res_factor = std::atoi(val.substr(0, -1).c_str()); + if(res_factor != g_res_factor) + { + g_res_factor = res_factor; + CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSH_OPENGL_RESOLUTION_FACTOR, res_factor); + videoUpdate = true; + } + } + break; + case 1: + { + CGSHandler::PRESENTATION_MODE presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FIT; - std::string val(var.value); - if(val == "Fill Screen") - presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FILL; - else if(val == "Original Size") - presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_ORIGINAL; + std::string val(var.value); + if(val == "Fill Screen") + presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FILL; + else if(val == "Original Size") + presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_ORIGINAL; - if(presentation_mode != g_presentation_mode) - { - g_presentation_mode = presentation_mode; - CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSHANDLER_PRESENTATION_MODE, presentation_mode); - videoUpdate = true; - } - } - break; - case 2: - { - bool forceBilinearTextures = (std::string(var.value) == "true"); - if(forceBilinearTextures != g_forceBilinearTextures) - { - g_forceBilinearTextures = forceBilinearTextures; - CAppConfig::GetInstance().SetPreferenceBoolean(PREF_CGSH_OPENGL_FORCEBILINEARTEXTURES, forceBilinearTextures); - videoUpdate = true; - } - } - break; - case 3: - bool audioEnabled = (std::string(var.value) == "true"); - if(audioEnabled != g_audioEnabled) - { - g_audioEnabled = audioEnabled; - } - break; + if(presentation_mode != g_presentation_mode) + { + g_presentation_mode = presentation_mode; + CAppConfig::GetInstance().SetPreferenceInteger(PREF_CGSHANDLER_PRESENTATION_MODE, presentation_mode); + videoUpdate = true; + } + } + break; + case 2: + { + bool forceBilinearTextures = (std::string(var.value) == "true"); + if(forceBilinearTextures != g_forceBilinearTextures) + { + g_forceBilinearTextures = forceBilinearTextures; + CAppConfig::GetInstance().SetPreferenceBoolean(PREF_CGSH_OPENGL_FORCEBILINEARTEXTURES, forceBilinearTextures); + videoUpdate = true; + } + } + break; + case 3: + bool audioEnabled = (std::string(var.value) == "true"); + if(audioEnabled != g_audioEnabled) + { + g_audioEnabled = audioEnabled; + } + break; } if(videoUpdate) @@ -432,7 +428,6 @@ void retro_run() if(m_virtualMachine) if(m_virtualMachine->GetGSHandler()) m_virtualMachine->GetGSHandler()->ProcessSingleFrame(); - } void retro_reset(void) @@ -483,7 +478,7 @@ bool retro_load_game(const retro_game_info* info) g_environ_cb(RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT, nullptr); - g_environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)m_vars.data()); + g_environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)m_vars.data()); return true; } @@ -493,7 +488,7 @@ void retro_unload_game(void) CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); } -bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) +bool retro_load_game_special(unsigned game_type, const struct retro_game_info* info, size_t num_info) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); From cc70ffda693c7e4bdb3e8ac1977561d6bb94f8c9 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Wed, 26 Jun 2019 15:33:39 +0100 Subject: [PATCH 18/41] Disable early logs, set storage path for android --- Source/ui_libretro/main_libretro.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 9034289e..7a810408 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -48,8 +48,6 @@ static std::vector m_vars = unsigned retro_api_version() { - CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - return RETRO_API_VERSION; } @@ -151,8 +149,6 @@ void SetupInputHandler() void retro_get_system_info(struct retro_system_info* info) { - CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - *info = {}; info->library_name = "Play!"; info->library_version = PLAY_VERSION; @@ -182,7 +178,6 @@ void retro_set_video_refresh(retro_video_refresh_t cb) void retro_set_environment(retro_environment_t cb) { - CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); g_environ_cb = cb; } @@ -497,6 +492,9 @@ bool retro_load_game_special(unsigned game_type, const struct retro_game_info* i void retro_init() { +#ifdef __ANDROID__ + Framework::PathUtils::SetFilesDirPath(getenv("EXTERNAL_STORAGE")); +#endif CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); m_virtualMachine = new CPS2VM(); From ade7f38f7ed96d6cda5cdb4bc3da060373ccf2d0 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Wed, 26 Jun 2019 16:45:51 +0100 Subject: [PATCH 19/41] libretro: update supported format --- Source/ui_libretro/main_libretro.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 7a810408..071f2f2a 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -153,7 +153,7 @@ void retro_get_system_info(struct retro_system_info* info) info->library_name = "Play!"; info->library_version = PLAY_VERSION; info->need_fullpath = true; - info->valid_extensions = "elf|iso|bin"; + info->valid_extensions = "elf|iso|cso|isz|bin"; } void retro_get_system_av_info(struct retro_system_av_info* info) From aab9b66c89b31c7c603dbd4e4abb4ccc9909ccb7 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Thu, 27 Jun 2019 10:25:52 +0100 Subject: [PATCH 20/41] poll button state on retro_run() thread... to avoid race condition, as these methods are not thread safe --- Source/ui_libretro/PH_Libretro_Input.cpp | 55 +++++++++++++++--------- Source/ui_libretro/PH_Libretro_Input.h | 6 +++ Source/ui_libretro/main_libretro.cpp | 7 +++ 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/Source/ui_libretro/PH_Libretro_Input.cpp b/Source/ui_libretro/PH_Libretro_Input.cpp index 8bcf6485..638f02cf 100644 --- a/Source/ui_libretro/PH_Libretro_Input.cpp +++ b/Source/ui_libretro/PH_Libretro_Input.cpp @@ -3,40 +3,53 @@ extern retro_input_poll_t g_input_poll_cb; extern retro_input_state_t g_input_state_cb; extern std::map g_ds2_to_retro_btn_map; +std::mutex m_input_mutex; + +void CPH_Libretro_Input::UpdateInputState() +{ + std::lock_guard lock(m_input_mutex); + g_input_poll_cb(); + for(unsigned int i = 0; i < PS2::CControllerInfo::MAX_BUTTONS; i++) + { + auto currentButtonId = static_cast(i); + auto itr = g_ds2_to_retro_btn_map.find(currentButtonId); + if(PS2::CControllerInfo::IsAxis(currentButtonId)) + { + int index; + if(i < 2) + index = RETRO_DEVICE_INDEX_ANALOG_LEFT; + else + index = RETRO_DEVICE_INDEX_ANALOG_RIGHT; + + float value = g_input_state_cb(0, RETRO_DEVICE_ANALOG, index, itr->second); + uint8 val = static_cast((value / 0xFF) + 0.5) + 0x7F; + if(val > 0x7F - 5 && val < 0x7F + 5) + val = 0x7F; + m_btn_state[currentButtonId] = val; + } + else + { + uint32 value = g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, itr->second); + m_btn_state[currentButtonId] = value != 0; + } + } +} void CPH_Libretro_Input::Update(uint8* ram) { - if(!g_input_poll_cb || !g_input_state_cb || g_ds2_to_retro_btn_map.size() == 0) - return; - - g_input_poll_cb(); - + std::lock_guard lock(m_input_mutex); for(auto* listener : m_listeners) { for(unsigned int i = 0; i < PS2::CControllerInfo::MAX_BUTTONS; i++) { - auto button = static_cast(i); - auto itr = g_ds2_to_retro_btn_map.find(button); - - if(itr == g_ds2_to_retro_btn_map.end()) return; - auto currentButtonId = static_cast(i); if(PS2::CControllerInfo::IsAxis(currentButtonId)) { - int index; - if(i < 2) - index = RETRO_DEVICE_INDEX_ANALOG_LEFT; - else - index = RETRO_DEVICE_INDEX_ANALOG_RIGHT; - - float value = g_input_state_cb(0, RETRO_DEVICE_ANALOG, index, itr->second); - uint8 val = static_cast((value / 0xFF) + 0.5) + 0x7F; - listener->SetAxisState(0, currentButtonId, val, ram); + listener->SetAxisState(0, currentButtonId, m_btn_state[currentButtonId], ram); } else { - uint32 value = g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, itr->second); - listener->SetButtonState(0, currentButtonId, value != 0, ram); + listener->SetButtonState(0, currentButtonId, m_btn_state[currentButtonId], ram); } } } diff --git a/Source/ui_libretro/PH_Libretro_Input.h b/Source/ui_libretro/PH_Libretro_Input.h index 9af814a6..014390d3 100644 --- a/Source/ui_libretro/PH_Libretro_Input.h +++ b/Source/ui_libretro/PH_Libretro_Input.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "PadHandler.h" // #include "InputBindingManager.h" #include "libretro.h" @@ -14,4 +15,9 @@ public: void Update(uint8*) override; static FactoryFunction GetFactoryFunction(); + + void UpdateInputState(); + +private: + std::map m_btn_state = {}; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 071f2f2a..79ac5be6 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -407,6 +407,7 @@ void retro_run() checkVarsUpdates(); + if(!first_run) { if(m_virtualMachine) @@ -421,8 +422,14 @@ void retro_run() } if(m_virtualMachine) + { + auto pad = m_virtualMachine->GetPadHandler(); + if(pad) + static_cast(pad)->UpdateInputState(); + if(m_virtualMachine->GetGSHandler()) m_virtualMachine->GetGSHandler()->ProcessSingleFrame(); + } } void retro_reset(void) From 50bdcddc711e166557a5a0d41c3abcaa61e564d6 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Thu, 27 Jun 2019 18:39:42 +0100 Subject: [PATCH 21/41] Libretro: Remove audio dependencies --- Source/ui_libretro/CMakeLists.txt | 29 ++++------------------ Source/ui_libretro/SH_LibreAudio.cpp | 31 ++++++++++++++++++++++++ Source/ui_libretro/SH_LibreAudio.h | 36 ++++++---------------------- Source/ui_libretro/main_libretro.cpp | 6 +++-- 4 files changed, 47 insertions(+), 55 deletions(-) create mode 100644 Source/ui_libretro/SH_LibreAudio.cpp diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index f660e17e..2e861305 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -42,29 +42,14 @@ set(SRC GSH_OpenGL_Libretro.h PH_Libretro_Input.cpp PH_Libretro_Input.h + SH_LibreAudio.cpp SH_LibreAudio.h ) -if(TARGET_PLATFORM_MACOS OR TARGET_PLATFORM_UNIX OR TARGET_PLATFORM_IOS) - if(NOT TARGET sh_openal) - add_subdirectory( - ${CMAKE_CURRENT_SOURCE_DIR}/../../tools/PsfPlayer/Source/SH_OpenAL - ${CMAKE_CURRENT_BINARY_DIR}/SH_OpenAL - ) - endif() - list(APPEND PROJECT_LIBS sh_openal) -elseif(TARGET_PLATFORM_ANDROID) - set(SRC - ${SRC} - ${CMAKE_CURRENT_SOURCE_DIR}/../ui_android/SH_OpenSL.cpp - ) - list(APPEND PROJECT_LIBS android log OpenSLES GLESv3 EGL) -elseif(TARGET_PLATFORM_WIN32) - set(SRC - ${SRC} - ../../tools/PsfPlayer/Source/win32_ui/SH_WaveOut.cpp - ) - list(APPEND PROJECT_LIBS "winmm.lib") +if(TARGET_PLATFORM_ANDROID) + list(APPEND PROJECT_LIBS android log GLESv3 EGL) +elseif(TARGET_PLATFORM_IOS) + target_link_libraries(play_libretro ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES") endif() add_library(play_libretro SHARED ${SRC}) @@ -74,9 +59,5 @@ target_include_directories(play_libretro PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) -if(TARGET_PLATFORM_IOS) - target_link_libraries(play_libretro ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES -framework OpenAL") -endif() - target_link_libraries(play_libretro ${PROJECT_LIBS}) set_target_properties(play_libretro PROPERTIES PREFIX "") diff --git a/Source/ui_libretro/SH_LibreAudio.cpp b/Source/ui_libretro/SH_LibreAudio.cpp new file mode 100644 index 00000000..45abc965 --- /dev/null +++ b/Source/ui_libretro/SH_LibreAudio.cpp @@ -0,0 +1,31 @@ +#include "SH_LibreAudio.h" +#include "libretro.h" + +extern bool g_audioEnabled; +extern retro_audio_sample_batch_t g_set_audio_sample_batch_cb; + +CSoundHandler* CSH_LibreAudio::HandlerFactory() +{ + return new CSH_LibreAudio(); +} + +void CSH_LibreAudio::Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) +{ + if(g_audioEnabled && g_set_audio_sample_batch_cb) + { + g_set_audio_sample_batch_cb(buffer, sampleCount / 2); + } +} + +bool CSH_LibreAudio::HasFreeBuffers() +{ + return false; +} + +void CSH_LibreAudio::Reset() +{ +} + +void CSH_LibreAudio::RecycleBuffers() +{ +} diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index fb62a222..f56f8486 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -1,38 +1,16 @@ #pragma once -#ifdef _WIN32 -#include "../../tools/PsfPlayer/Source/win32_ui/SH_WaveOut.h" -#elif defined(__ANDROID__) -#include "../ui_android/SH_OpenSL.h" -#else -#include "tools/PsfPlayer/Source/SH_OpenAL.h" -#endif +#include "tools/PsfPlayer/Source/SoundHandler.h" -extern bool g_audioEnabled; - -#ifdef _WIN32 -#define _CSH_PARENT_ CSH_WaveOut -#elif defined(__ANDROID__) -#define _CSH_PARENT_ CSH_OpenSL -#else -#define _CSH_PARENT_ CSH_OpenAL -#endif - -class CSH_LibreAudio : public _CSH_PARENT_ +class CSH_LibreAudio : public CSoundHandler { public: CSH_LibreAudio() = default; - static CSoundHandler* HandlerFactory() - { - return new CSH_LibreAudio(); - } + static CSoundHandler* HandlerFactory(); - void Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) override - { - if(g_audioEnabled) - { - _CSH_PARENT_::Write(buffer, sampleCount, sampleRate); - } - }; + void Reset() override; + void Write(int16*, unsigned int, unsigned int) override; + bool HasFreeBuffers() override; + void RecycleBuffers() override; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 79ac5be6..d9b04eb2 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -26,6 +26,7 @@ retro_video_refresh_t g_video_cb; retro_environment_t g_environ_cb; retro_input_poll_t g_input_poll_cb; retro_input_state_t g_input_state_cb; +retro_audio_sample_batch_t g_set_audio_sample_batch_cb; std::map g_ds2_to_retro_btn_map; struct retro_hw_render_callback g_hw_render @@ -162,7 +163,7 @@ void retro_get_system_av_info(struct retro_system_av_info* info) *info = {}; info->timing.fps = 60.0; - info->timing.sample_rate = 0; + info->timing.sample_rate = 44100; info->geometry.base_width = 640; info->geometry.base_height = 448; info->geometry.max_width = 640 * 8; @@ -198,9 +199,10 @@ void retro_set_controller_port_device(unsigned port, unsigned device) CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); } -void retro_set_audio_sample_batch(retro_audio_sample_batch_t) +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + g_set_audio_sample_batch_cb = cb; } void retro_set_audio_sample(retro_audio_sample_t) From fd4387c96cc53bf32a9693a470d1a1af51e726df Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Thu, 27 Jun 2019 19:57:15 +0100 Subject: [PATCH 22/41] Libretro: move audio processing to main thread --- Source/PS2VM.cpp | 5 +++++ Source/PS2VM.h | 1 + Source/ui_libretro/SH_LibreAudio.cpp | 17 +++++++++++++++-- Source/ui_libretro/SH_LibreAudio.h | 8 ++++++++ Source/ui_libretro/main_libretro.cpp | 3 +++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Source/PS2VM.cpp b/Source/PS2VM.cpp index 6135ecdd..f0957717 100644 --- a/Source/PS2VM.cpp +++ b/Source/PS2VM.cpp @@ -539,6 +539,11 @@ void CPS2VM::CreateSoundHandlerImpl(const CSoundHandler::FactoryFunction& factor m_soundHandler = factoryFunction(); } +CSoundHandler* CPS2VM::GetSoundHandler() +{ + return m_soundHandler; +} + void CPS2VM::DestroySoundHandlerImpl() { if(m_soundHandler == nullptr) return; diff --git a/Source/PS2VM.h b/Source/PS2VM.h index 3650044b..2c301142 100644 --- a/Source/PS2VM.h +++ b/Source/PS2VM.h @@ -62,6 +62,7 @@ public: void DestroyPadHandler(); void CreateSoundHandler(const CSoundHandler::FactoryFunction&); + CSoundHandler* GetSoundHandler(); void DestroySoundHandler(); void ReloadSpuBlockCount(); diff --git a/Source/ui_libretro/SH_LibreAudio.cpp b/Source/ui_libretro/SH_LibreAudio.cpp index 45abc965..1a7aba14 100644 --- a/Source/ui_libretro/SH_LibreAudio.cpp +++ b/Source/ui_libretro/SH_LibreAudio.cpp @@ -11,9 +11,22 @@ CSoundHandler* CSH_LibreAudio::HandlerFactory() void CSH_LibreAudio::Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) { - if(g_audioEnabled && g_set_audio_sample_batch_cb) + if(g_audioEnabled) { - g_set_audio_sample_batch_cb(buffer, sampleCount / 2); + std::vector buf(sampleCount * sizeof(int16)); + memcpy(buf.data(), buffer, sampleCount * sizeof(int16)); + m_queue.push_back(std::move(buf)); + } +} + +void CSH_LibreAudio::ProcessBuffer() +{ + if(!m_queue.empty()) + { + auto buf = std::move(m_queue.front()); + m_queue.pop_front(); + if(g_set_audio_sample_batch_cb) + g_set_audio_sample_batch_cb(buf.data(), buf.size() / (2 * sizeof(int16))); } } diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index f56f8486..e4bf93b2 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -2,6 +2,9 @@ #include "tools/PsfPlayer/Source/SoundHandler.h" +#include +#include + class CSH_LibreAudio : public CSoundHandler { public: @@ -13,4 +16,9 @@ public: void Write(int16*, unsigned int, unsigned int) override; bool HasFreeBuffers() override; void RecycleBuffers() override; + + void ProcessBuffer(); + +private: + std::deque> m_queue; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index d9b04eb2..088fd6f2 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -429,6 +429,9 @@ void retro_run() if(pad) static_cast(pad)->UpdateInputState(); + if(m_virtualMachine->GetSoundHandler()) + static_cast(m_virtualMachine->GetSoundHandler())->ProcessBuffer(); + if(m_virtualMachine->GetGSHandler()) m_virtualMachine->GetGSHandler()->ProcessSingleFrame(); } From 0105b71359f75fd465ecaca1484800ee74f36bf3 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 18:54:19 +0100 Subject: [PATCH 23/41] Libretro: Audio: replace queue with buffer, remove audio mute option (thats handled by RA) --- Source/ui_libretro/SH_LibreAudio.cpp | 21 ++++++++++----------- Source/ui_libretro/SH_LibreAudio.h | 2 +- Source/ui_libretro/main_libretro.cpp | 9 --------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Source/ui_libretro/SH_LibreAudio.cpp b/Source/ui_libretro/SH_LibreAudio.cpp index 1a7aba14..8f8611ff 100644 --- a/Source/ui_libretro/SH_LibreAudio.cpp +++ b/Source/ui_libretro/SH_LibreAudio.cpp @@ -1,8 +1,10 @@ #include "SH_LibreAudio.h" #include "libretro.h" +#include +#include -extern bool g_audioEnabled; extern retro_audio_sample_batch_t g_set_audio_sample_batch_cb; +std::mutex m_buffer_lock; CSoundHandler* CSH_LibreAudio::HandlerFactory() { @@ -11,22 +13,19 @@ CSoundHandler* CSH_LibreAudio::HandlerFactory() void CSH_LibreAudio::Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) { - if(g_audioEnabled) - { - std::vector buf(sampleCount * sizeof(int16)); - memcpy(buf.data(), buffer, sampleCount * sizeof(int16)); - m_queue.push_back(std::move(buf)); - } + std::lock_guard lock(m_buffer_lock); + m_buffer.resize(sampleCount * sizeof(int16)); + memcpy(m_buffer.data(), buffer, sampleCount * sizeof(int16)); } void CSH_LibreAudio::ProcessBuffer() { - if(!m_queue.empty()) + if(!m_buffer.empty()) { - auto buf = std::move(m_queue.front()); - m_queue.pop_front(); + std::lock_guard lock(m_buffer_lock); if(g_set_audio_sample_batch_cb) - g_set_audio_sample_batch_cb(buf.data(), buf.size() / (2 * sizeof(int16))); + g_set_audio_sample_batch_cb(m_buffer.data(), m_buffer.size() / (2 * sizeof(int16))); + m_buffer.clear(); } } diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index e4bf93b2..b9c34cae 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -20,5 +20,5 @@ public: void ProcessBuffer(); private: - std::deque> m_queue; + std::vector m_buffer; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 088fd6f2..b7272e7e 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -36,14 +36,12 @@ struct retro_hw_render_callback g_hw_render int g_res_factor = 1; CGSHandler::PRESENTATION_MODE g_presentation_mode = CGSHandler::PRESENTATION_MODE::PRESENTATION_MODE_FIT; bool g_forceBilinearTextures = false; -bool g_audioEnabled = true; static std::vector m_vars = { {"play_res_multi", "Resolution Multiplier; 1x|2x|4x|8x"}, {"play_presentation_mode", "Presentation Mode; Fit Screen|Fill Screen|Original Size"}, {"play_bilinear_filtering", "Force Bilinear Filtering; false|true"}, - {"audio_enable", "Enable Audio; true|false"}, {NULL, NULL}, }; @@ -371,13 +369,6 @@ void updateVars() } } break; - case 3: - bool audioEnabled = (std::string(var.value) == "true"); - if(audioEnabled != g_audioEnabled) - { - g_audioEnabled = audioEnabled; - } - break; } if(videoUpdate) From 9588dfff350d70596fdcfde3edc050b48bf3ec8c Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Wed, 3 Jul 2019 17:36:41 +0100 Subject: [PATCH 24/41] Update libretro.h --- Source/ui_libretro/libretro.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Source/ui_libretro/libretro.h b/Source/ui_libretro/libretro.h index 4526bee4..80a24abf 100644 --- a/Source/ui_libretro/libretro.h +++ b/Source/ui_libretro/libretro.h @@ -203,6 +203,8 @@ extern "C" #define RETRO_DEVICE_ID_JOYPAD_L3 14 #define RETRO_DEVICE_ID_JOYPAD_R3 15 +#define RETRO_DEVICE_ID_JOYPAD_MASK 256 + /* Index / Id values for ANALOG device. */ #define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 #define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 @@ -249,6 +251,7 @@ extern "C" #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 @@ -1092,10 +1095,22 @@ extern "C" * refresh rate/framerate. */ +#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend supports + * input bitmasks being returned by retro_input_state_t. The advantage + * of this is that retro_input_state_t has to be only called once to + * grab all button states instead of multiple times. + * + * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id' + * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD). + * It will return a bitmask of all the digital buttons. + */ + /* VFS functionality */ /* File paths: - * File paths passed as parameters when using this api shall be well formed UNIX-style, + * 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: @@ -2534,4 +2549,4 @@ extern "C" } #endif -#endif +#endif \ No newline at end of file From d710ceee041ae265e68f9c2d4e9bbd3446480ad1 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 19:40:39 +0100 Subject: [PATCH 25/41] Libretro: update input to support bitmasking --- Source/ui_libretro/PH_Libretro_Input.cpp | 37 +++++++++++++++--------- Source/ui_libretro/PH_Libretro_Input.h | 3 +- Source/ui_libretro/main_libretro.cpp | 5 ++++ 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/Source/ui_libretro/PH_Libretro_Input.cpp b/Source/ui_libretro/PH_Libretro_Input.cpp index 638f02cf..f823bb83 100644 --- a/Source/ui_libretro/PH_Libretro_Input.cpp +++ b/Source/ui_libretro/PH_Libretro_Input.cpp @@ -1,5 +1,6 @@ #include "PH_Libretro_Input.h" +extern bool libretro_supports_bitmasks; extern retro_input_poll_t g_input_poll_cb; extern retro_input_state_t g_input_state_cb; extern std::map g_ds2_to_retro_btn_map; @@ -9,10 +10,24 @@ void CPH_Libretro_Input::UpdateInputState() { std::lock_guard lock(m_input_mutex); g_input_poll_cb(); - for(unsigned int i = 0; i < PS2::CControllerInfo::MAX_BUTTONS; i++) + + if(libretro_supports_bitmasks) + { + m_btns_state = g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK); + } + else + { + m_btns_state = 0; + for (unsigned int i = 0; i <= RETRO_DEVICE_ID_JOYPAD_R3; i++) + { + if (g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) + m_btns_state |= (1 << i); + } + } + + for(unsigned int i = 0; i <= PS2::CControllerInfo::ANALOG_RIGHT_Y + 1; i++) { auto currentButtonId = static_cast(i); - auto itr = g_ds2_to_retro_btn_map.find(currentButtonId); if(PS2::CControllerInfo::IsAxis(currentButtonId)) { int index; @@ -21,16 +36,11 @@ void CPH_Libretro_Input::UpdateInputState() else index = RETRO_DEVICE_INDEX_ANALOG_RIGHT; - float value = g_input_state_cb(0, RETRO_DEVICE_ANALOG, index, itr->second); + float value = g_input_state_cb(0, RETRO_DEVICE_ANALOG, index, g_ds2_to_retro_btn_map[currentButtonId]); uint8 val = static_cast((value / 0xFF) + 0.5) + 0x7F; - if(val > 0x7F - 5 && val < 0x7F + 5) - val = 0x7F; - m_btn_state[currentButtonId] = val; - } - else - { - uint32 value = g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, itr->second); - m_btn_state[currentButtonId] = value != 0; + if(val > 0x7F - 5 && val < 0x7F + 5) + val = 0x7F; + m_axis_btn_state[currentButtonId] = val; } } } @@ -45,11 +55,12 @@ void CPH_Libretro_Input::Update(uint8* ram) auto currentButtonId = static_cast(i); if(PS2::CControllerInfo::IsAxis(currentButtonId)) { - listener->SetAxisState(0, currentButtonId, m_btn_state[currentButtonId], ram); + listener->SetAxisState(0, currentButtonId, m_axis_btn_state[currentButtonId], ram); } else { - listener->SetButtonState(0, currentButtonId, m_btn_state[currentButtonId], ram); + uint32 val = m_btns_state & (1 << g_ds2_to_retro_btn_map[currentButtonId]); + listener->SetButtonState(0, currentButtonId, val != 0, ram); } } } diff --git a/Source/ui_libretro/PH_Libretro_Input.h b/Source/ui_libretro/PH_Libretro_Input.h index 014390d3..3cc4b474 100644 --- a/Source/ui_libretro/PH_Libretro_Input.h +++ b/Source/ui_libretro/PH_Libretro_Input.h @@ -19,5 +19,6 @@ public: void UpdateInputState(); private: - std::map m_btn_state = {}; + int16 m_btns_state = 0; + uint8 m_axis_btn_state[4] = { 0x7F }; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index b7272e7e..d02ad1f0 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -22,6 +22,7 @@ static CPS2VM* m_virtualMachine = nullptr; static bool first_run = false; +bool libretro_supports_bitmasks = false; retro_video_refresh_t g_video_cb; retro_environment_t g_environ_cb; retro_input_poll_t g_input_poll_cb; @@ -500,6 +501,9 @@ void retro_init() #endif CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); + if (g_environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) + libretro_supports_bitmasks = true; + m_virtualMachine = new CPS2VM(); m_virtualMachine->Initialize(); @@ -528,4 +532,5 @@ void retro_deinit() delete m_virtualMachine; m_virtualMachine = nullptr; } + libretro_supports_bitmasks = false; } From 515327e0de97355a2e548dbe1afd8d269b07ce94 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 20:01:28 +0100 Subject: [PATCH 26/41] cleanup --- Source/ui_libretro/PH_Libretro_Input.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ui_libretro/PH_Libretro_Input.cpp b/Source/ui_libretro/PH_Libretro_Input.cpp index f823bb83..a63d8a71 100644 --- a/Source/ui_libretro/PH_Libretro_Input.cpp +++ b/Source/ui_libretro/PH_Libretro_Input.cpp @@ -18,9 +18,9 @@ void CPH_Libretro_Input::UpdateInputState() else { m_btns_state = 0; - for (unsigned int i = 0; i <= RETRO_DEVICE_ID_JOYPAD_R3; i++) + for(unsigned int i = 0; i <= RETRO_DEVICE_ID_JOYPAD_R3; i++) { - if (g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) + if(g_input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) m_btns_state |= (1 << i); } } From 461d371156497475c72273ac418b91e4352415a9 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 20:53:05 +0100 Subject: [PATCH 27/41] Libretro: Fix iOS build --- Source/ui_libretro/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index 2e861305..eb06c030 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -49,7 +49,7 @@ set(SRC if(TARGET_PLATFORM_ANDROID) list(APPEND PROJECT_LIBS android log GLESv3 EGL) elseif(TARGET_PLATFORM_IOS) - target_link_libraries(play_libretro ${PROJECT_LIBS} "-ObjC -lsqlite3 -framework OpenGLES") + list(APPEND PROJECT_LIBS "-ObjC -lsqlite3 -framework OpenGLES") endif() add_library(play_libretro SHARED ${SRC}) From a9ec80dbd8744c4e25600e5473ac864a3f4be2ec Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 5 Jul 2019 23:13:27 +0100 Subject: [PATCH 28/41] libretro: add _android.so suffix to shared library, its how retroarch expect the libraries to be named --- Source/ui_libretro/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index eb06c030..b4a2c1e2 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -59,5 +59,9 @@ target_include_directories(play_libretro PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) +if(TARGET_PLATFORM_ANDROID) + set_target_properties(play_libretro PROPERTIES SUFFIX "_android.so") +endif() + target_link_libraries(play_libretro ${PROJECT_LIBS}) set_target_properties(play_libretro PROPERTIES PREFIX "") From ea3a3facdf96c65dfa52c831b81223c2316fa465 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 28 Jun 2019 21:28:36 +0100 Subject: [PATCH 29/41] Update android libretro bash build scrip --- build_retro/android_build.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/build_retro/android_build.sh b/build_retro/android_build.sh index 22148cc7..7dd3e375 100644 --- a/build_retro/android_build.sh +++ b/build_retro/android_build.sh @@ -18,12 +18,11 @@ do -DANDROID_NDK=${ANDROID_NDK} \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ - -DANDROID_NATIVE_API_LEVEL=23 \ + -DANDROID_NATIVE_API_LEVEL=19 \ + -DANDROID_STL=c++_static \ -DANDROID_TOOLCHAIN=clang cmake --build . --target play_libretro - - mv Source/ui_libretro/play_libretro.so ../play_libretro_${ABI}.so - ${STRIP} -strip-all ../play_libretro_${ABI}.so ../play_libretro_${ABI}_stripped.so + ${STRIP} -strip-all Source/ui_libretro/play_libretro_android.so ../play_libretro_${ABI}_android.so popd done \ No newline at end of file From 3b18a619663c5b4af04399ddf6517cd45df59336 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Wed, 3 Jul 2019 17:34:57 +0100 Subject: [PATCH 30/41] cleanup --- Source/ui_libretro/PH_Libretro_Input.h | 2 +- Source/ui_libretro/main_libretro.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/ui_libretro/PH_Libretro_Input.h b/Source/ui_libretro/PH_Libretro_Input.h index 3cc4b474..603e3c1e 100644 --- a/Source/ui_libretro/PH_Libretro_Input.h +++ b/Source/ui_libretro/PH_Libretro_Input.h @@ -20,5 +20,5 @@ public: private: int16 m_btns_state = 0; - uint8 m_axis_btn_state[4] = { 0x7F }; + uint8 m_axis_btn_state[4] = {0x7F}; }; diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index d02ad1f0..194b6cf5 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -401,7 +401,6 @@ void retro_run() checkVarsUpdates(); - if(!first_run) { if(m_virtualMachine) @@ -501,7 +500,7 @@ void retro_init() #endif CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); - if (g_environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) + if(g_environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) libretro_supports_bitmasks = true; m_virtualMachine = new CPS2VM(); From ac4c10a4e42fabff6abefc67c10dd680427a4480 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Sun, 7 Jul 2019 00:03:40 +0100 Subject: [PATCH 31/41] libretro: cmake: add iOS suffix --- Source/ui_libretro/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index b4a2c1e2..a5cba6e7 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -62,6 +62,9 @@ target_include_directories(play_libretro PRIVATE if(TARGET_PLATFORM_ANDROID) set_target_properties(play_libretro PROPERTIES SUFFIX "_android.so") endif() +if(TARGET_PLATFORM_IOS) + set_target_properties(play_libretro PROPERTIES SUFFIX "_ios.dylib") +endif() target_link_libraries(play_libretro ${PROJECT_LIBS}) set_target_properties(play_libretro PROPERTIES PREFIX "") From 0defbb0585309761e77f9a69921d6e821fd88ad0 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 16 Aug 2019 18:21:55 +0300 Subject: [PATCH 32/41] change to unix line endings --- Source/ui_libretro/SH_LibreAudio.cpp | 86 ++++++++++++++-------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/Source/ui_libretro/SH_LibreAudio.cpp b/Source/ui_libretro/SH_LibreAudio.cpp index 8f8611ff..19f206f2 100644 --- a/Source/ui_libretro/SH_LibreAudio.cpp +++ b/Source/ui_libretro/SH_LibreAudio.cpp @@ -1,43 +1,43 @@ -#include "SH_LibreAudio.h" -#include "libretro.h" -#include -#include - -extern retro_audio_sample_batch_t g_set_audio_sample_batch_cb; -std::mutex m_buffer_lock; - -CSoundHandler* CSH_LibreAudio::HandlerFactory() -{ - return new CSH_LibreAudio(); -} - -void CSH_LibreAudio::Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) -{ - std::lock_guard lock(m_buffer_lock); - m_buffer.resize(sampleCount * sizeof(int16)); - memcpy(m_buffer.data(), buffer, sampleCount * sizeof(int16)); -} - -void CSH_LibreAudio::ProcessBuffer() -{ - if(!m_buffer.empty()) - { - std::lock_guard lock(m_buffer_lock); - if(g_set_audio_sample_batch_cb) - g_set_audio_sample_batch_cb(m_buffer.data(), m_buffer.size() / (2 * sizeof(int16))); - m_buffer.clear(); - } -} - -bool CSH_LibreAudio::HasFreeBuffers() -{ - return false; -} - -void CSH_LibreAudio::Reset() -{ -} - -void CSH_LibreAudio::RecycleBuffers() -{ -} +#include "SH_LibreAudio.h" +#include "libretro.h" +#include +#include + +extern retro_audio_sample_batch_t g_set_audio_sample_batch_cb; +std::mutex m_buffer_lock; + +CSoundHandler* CSH_LibreAudio::HandlerFactory() +{ + return new CSH_LibreAudio(); +} + +void CSH_LibreAudio::Write(int16* buffer, unsigned int sampleCount, unsigned int sampleRate) +{ + std::lock_guard lock(m_buffer_lock); + m_buffer.resize(sampleCount * sizeof(int16)); + memcpy(m_buffer.data(), buffer, sampleCount * sizeof(int16)); +} + +void CSH_LibreAudio::ProcessBuffer() +{ + if(!m_buffer.empty()) + { + std::lock_guard lock(m_buffer_lock); + if(g_set_audio_sample_batch_cb) + g_set_audio_sample_batch_cb(m_buffer.data(), m_buffer.size() / (2 * sizeof(int16))); + m_buffer.clear(); + } +} + +bool CSH_LibreAudio::HasFreeBuffers() +{ + return false; +} + +void CSH_LibreAudio::Reset() +{ +} + +void CSH_LibreAudio::RecycleBuffers() +{ +} From 102ea5924cfba88a34730ce7324182b5ae14becc Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Sun, 7 Jul 2019 12:59:01 +0100 Subject: [PATCH 33/41] Cleanup --- Source/ui_libretro/CMakeLists.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index a5cba6e7..85ff4eb1 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -26,16 +26,6 @@ if(NOT TARGET gsh_opengl) endif() list(INSERT PROJECT_LIBS 0 gsh_opengl) -if(NOT TARGET_PLATFORM_UNIX_AARCH64 AND (TARGET_PLATFORM_UNIX OR TARGET_PLATFORM_WIN32)) - if (NOT TARGET glew_s) - add_subdirectory( - ${CMAKE_CURRENT_SOURCE_DIR}/../../../Dependencies/glew-2.0.0 - ${CMAKE_CURRENT_BINARY_DIR}/glew-2.0.0 - ) - endif() - list(APPEND PROJECT_LIBS glew_s) -endif() - set(SRC main_libretro.cpp GSH_OpenGL_Libretro.cpp From 359b2b31e553684953e6b6cfb848a12a709bd322 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Mon, 8 Jul 2019 20:06:21 +0100 Subject: [PATCH 34/41] make mutex a class object --- Source/ui_libretro/PH_Libretro_Input.cpp | 1 - Source/ui_libretro/PH_Libretro_Input.h | 1 + Source/ui_libretro/SH_LibreAudio.h | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/ui_libretro/PH_Libretro_Input.cpp b/Source/ui_libretro/PH_Libretro_Input.cpp index a63d8a71..864a8d0b 100644 --- a/Source/ui_libretro/PH_Libretro_Input.cpp +++ b/Source/ui_libretro/PH_Libretro_Input.cpp @@ -4,7 +4,6 @@ extern bool libretro_supports_bitmasks; extern retro_input_poll_t g_input_poll_cb; extern retro_input_state_t g_input_state_cb; extern std::map g_ds2_to_retro_btn_map; -std::mutex m_input_mutex; void CPH_Libretro_Input::UpdateInputState() { diff --git a/Source/ui_libretro/PH_Libretro_Input.h b/Source/ui_libretro/PH_Libretro_Input.h index 603e3c1e..fcd465e6 100644 --- a/Source/ui_libretro/PH_Libretro_Input.h +++ b/Source/ui_libretro/PH_Libretro_Input.h @@ -21,4 +21,5 @@ public: private: int16 m_btns_state = 0; uint8 m_axis_btn_state[4] = {0x7F}; + std::mutex m_input_mutex; }; diff --git a/Source/ui_libretro/SH_LibreAudio.h b/Source/ui_libretro/SH_LibreAudio.h index b9c34cae..56c70ba7 100644 --- a/Source/ui_libretro/SH_LibreAudio.h +++ b/Source/ui_libretro/SH_LibreAudio.h @@ -4,6 +4,7 @@ #include #include +#include class CSH_LibreAudio : public CSoundHandler { @@ -21,4 +22,5 @@ public: private: std::vector m_buffer; + std::mutex m_buffer_lock; }; From 3136dbafa621fc58297ce3f873423556a9aea81c Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Fri, 18 Oct 2019 10:57:04 +0100 Subject: [PATCH 35/41] libretro: set lower audio buffer --- Source/ui_libretro/main_libretro.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index 194b6cf5..eacef75c 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -503,6 +503,8 @@ void retro_init() if(g_environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL)) libretro_supports_bitmasks = true; + CAppConfig::GetInstance().RegisterPreferenceInteger(PREF_AUDIO_SPUBLOCKCOUNT, 22); + m_virtualMachine = new CPS2VM(); m_virtualMachine->Initialize(); From acf529483e4bab6926b9aabc5d36034de3ce1503 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 19 Nov 2019 13:16:29 +0000 Subject: [PATCH 36/41] fix cmake path --- Source/ui_libretro/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ui_libretro/CMakeLists.txt b/Source/ui_libretro/CMakeLists.txt index 85ff4eb1..d02a5f32 100644 --- a/Source/ui_libretro/CMakeLists.txt +++ b/Source/ui_libretro/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_MODULE_PATH - ${CMAKE_CURRENT_SOURCE_DIR}/../../../Dependencies/cmake-modules + ${CMAKE_CURRENT_SOURCE_DIR}/../../../deps/Dependencies/cmake-modules ${CMAKE_MODULE_PATH} ) include(Header) From 35a10d26f15512a17673251dff7bbb2313a1c7cf Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 19 Nov 2019 13:24:34 +0000 Subject: [PATCH 37/41] fix android libretro build --- .travis.sh | 7 +++++-- build_retro/android_build.sh | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.sh b/.travis.sh index 6bb6b46b..e10074f9 100644 --- a/.travis.sh +++ b/.travis.sh @@ -43,8 +43,11 @@ travis_script() { if [ "$TARGET_OS" = "Android" ]; then if [ "$BUILD_LIBRETRO" = "yes" ]; then - export PATH=/opt/cmake-3.8.1-Linux-x86_64/bin/:$PATH - export ANDROID_NDK=/usr/local/android-sdk/ndk-bundle + CMAKE_PATH=/usr/local/android-sdk/cmake/3.10.2.4988404 + export PATH=${CMAKE_PATH}/bin:$PATH + export NINJA_EXE=${CMAKE_PATH}/bin/ninja + export ANDROID_NDK=/usr/local/android-sdk/ndk/20.0.5594570 + export ANDROID_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake pushd build_retro bash android_build.sh popd diff --git a/build_retro/android_build.sh b/build_retro/android_build.sh index 7dd3e375..f0db1ea0 100644 --- a/build_retro/android_build.sh +++ b/build_retro/android_build.sh @@ -17,12 +17,13 @@ do -DANDROID_ABI="${ABI}" \ -DANDROID_NDK=${ANDROID_NDK} \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ + -DCMAKE_TOOLCHAIN_FILE=${ANDROID_TOOLCHAIN_FILE} \ -DANDROID_NATIVE_API_LEVEL=19 \ -DANDROID_STL=c++_static \ - -DANDROID_TOOLCHAIN=clang + -DANDROID_TOOLCHAIN=clang \ + -DCMAKE_MAKE_PROGRAM=${NINJA_EXE} cmake --build . --target play_libretro - ${STRIP} -strip-all Source/ui_libretro/play_libretro_android.so ../play_libretro_${ABI}_android.so + ${STRIP} -strip-all -o ../play_libretro_${ABI}_android.so Source/ui_libretro/play_libretro_android.so popd done \ No newline at end of file From 3cde7c407799cf761b3008061c77dc5e7c47604f Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Tue, 19 Nov 2019 13:24:49 +0000 Subject: [PATCH 38/41] fix libretro deploy --- .travis.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.sh b/.travis.sh index e10074f9..e77cc4d6 100644 --- a/.travis.sh +++ b/.travis.sh @@ -137,11 +137,14 @@ travis_before_deploy() if [ "$TARGET_ARCH" = "x86_64" ]; then cp ../../build/Play*.AppImage . cp ../../build/Source/ui_libretro/play_libretro.so play_libretro_linux-x86_64.so + else + cp ../../build/Source/ui_libretro/play_libretro.so play_libretro_linux-ARM64.so fi; fi; if [ "$TARGET_OS" = "Android" ]; then if [ "$BUILD_LIBRETRO" = "yes" ]; then cp ../../build_retro/play_* . + ABI_LIST="arm64-v8a armeabi-v7a x86 x86_64" else cp ../../build_android/build/outputs/apk/release/Play-release-unsigned.apk . export ANDROID_BUILD_TOOLS=$ANDROID_HOME/build-tools/28.0.3 @@ -151,13 +154,13 @@ travis_before_deploy() fi; if [ "$TARGET_OS" = "OSX" ]; then cp ../../build/Play.dmg . - cp ../../build/Source/ui_libretro/play_libretro.dylib play_libretro_macOS-x86_64.dylib + cp ../../build/Source/ui_libretro/Release/play_libretro.dylib play_libretro_macOS-x86_64.dylib fi; if [ "$TARGET_OS" = "IOS" ]; then cp ../../installer_ios/Play.ipa . cp ../../installer_ios/Play.deb . cp ../../installer_ios/Packages.bz2 . - cp ../../build/Source/ui_libretro/play_libretro.dylib play_libretro_iOS-FAT.dylib + cp ../../build/Source/ui_libretro/Release/play_libretro.dylib play_libretro_iOS-FAT.dylib fi; popd popd From e6a756dbe68161d2519292a6580dd68ed06443d7 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Wed, 1 Jan 2020 13:26:55 +0000 Subject: [PATCH 39/41] remove direct access to CMailBox in Android & DirectX GS --- Source/gs/GSH_Direct3D9/GSH_Direct3D9.cpp | 4 ++-- Source/ui_android/GSH_OpenGLAndroid.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/gs/GSH_Direct3D9/GSH_Direct3D9.cpp b/Source/gs/GSH_Direct3D9/GSH_Direct3D9.cpp index 6a43263f..c566532c 100644 --- a/Source/gs/GSH_Direct3D9/GSH_Direct3D9.cpp +++ b/Source/gs/GSH_Direct3D9/GSH_Direct3D9.cpp @@ -46,14 +46,14 @@ CGSH_Direct3D9::CGSH_Direct3D9(Framework::Win32::CWindow* outputWindow) Framework::CBitmap CGSH_Direct3D9::GetFramebuffer(uint64 frameReg) { Framework::CBitmap result; - m_mailBox.SendCall([&]() { result = GetFramebufferImpl(frameReg); }, true); + SendGSCall([&]() { result = GetFramebufferImpl(frameReg); }, true); return result; } Framework::CBitmap CGSH_Direct3D9::GetTexture(uint64 tex0Reg, uint32 maxMip, uint64 miptbp1Reg, uint64 miptbp2Reg, uint32 mipLevel) { Framework::CBitmap result; - m_mailBox.SendCall([&]() { result = GetTextureImpl(tex0Reg, maxMip, miptbp1Reg, miptbp2Reg, mipLevel); }, true); + SendGSCall([&]() { result = GetTextureImpl(tex0Reg, maxMip, miptbp1Reg, miptbp2Reg, mipLevel); }, true); return result; } diff --git a/Source/ui_android/GSH_OpenGLAndroid.cpp b/Source/ui_android/GSH_OpenGLAndroid.cpp index 2e1949bf..9b5d9533 100644 --- a/Source/ui_android/GSH_OpenGLAndroid.cpp +++ b/Source/ui_android/GSH_OpenGLAndroid.cpp @@ -58,7 +58,7 @@ void CGSH_OpenGLAndroid::PresentBackbuffer() void CGSH_OpenGLAndroid::SetWindow(NativeWindowType window) { m_window = window; - m_mailBox.SendCall( + SendGSCall( [this]() { SetupContext(); }, From b8de5e8fe9a7c0af333bbe1036d389fcbbcc1597 Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Wed, 1 Jan 2020 13:28:51 +0000 Subject: [PATCH 40/41] Code style fixes. --- Source/gs/GSHandler.h | 1 - Source/ui_libretro/GSH_OpenGL_Libretro.cpp | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/gs/GSHandler.h b/Source/gs/GSHandler.h index 7eb88d30..ac6960c4 100644 --- a/Source/gs/GSHandler.h +++ b/Source/gs/GSHandler.h @@ -994,5 +994,4 @@ protected: private: CMailBox m_mailBox; - }; diff --git a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp index 00eac76d..0b9121f8 100644 --- a/Source/ui_libretro/GSH_OpenGL_Libretro.cpp +++ b/Source/ui_libretro/GSH_OpenGL_Libretro.cpp @@ -69,7 +69,8 @@ void CGSH_OpenGL_Libretro::FlushMailBox() bool isFlushed = false; SendGSCall([&]() { isFlushed = true; - }, true); + }, + true); while(!isFlushed) { // Wait for flush to complete From d88c02b2ca60360903c42ff168cf9b99b986a01f Mon Sep 17 00:00:00 2001 From: Mahmood - Zer0xFF <5013823+Zer0xFF@users.noreply.github.com> Date: Thu, 2 Jan 2020 01:19:36 +0000 Subject: [PATCH 41/41] libretro support elf loading.... this id currently duplicating code from BootablesProcesses --- Source/ui_libretro/main_libretro.cpp | 58 ++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/Source/ui_libretro/main_libretro.cpp b/Source/ui_libretro/main_libretro.cpp index eacef75c..b4e05895 100644 --- a/Source/ui_libretro/main_libretro.cpp +++ b/Source/ui_libretro/main_libretro.cpp @@ -46,6 +46,26 @@ static std::vector m_vars = {NULL, NULL}, }; +enum BootType +{ + CD, + ELF +}; + +struct LastOpenCommand +{ + LastOpenCommand() = default; + LastOpenCommand(BootType type, fs::path path) + : type(type) + , path(path) + { + } + BootType type = BootType::CD; + fs::path path; +}; + +LastOpenCommand m_bootCommand; + unsigned retro_api_version() { return RETRO_API_VERSION; @@ -407,7 +427,14 @@ void retro_run() { // m_virtualMachine->Pause(); m_virtualMachine->Reset(); - m_virtualMachine->m_ee->m_os->BootFromCDROM(); + if(m_bootCommand.type == BootType::CD) + { + m_virtualMachine->m_ee->m_os->BootFromCDROM(); + } + else + { + m_virtualMachine->m_ee->m_os->BootFromFile(m_bootCommand.path); + } m_virtualMachine->Resume(); first_run = true; CLog::GetInstance().Print(LOG_NAME, "%s\n", "Start Game"); @@ -445,13 +472,38 @@ void retro_reset(void) first_run = false; } +bool IsBootableExecutablePath(const fs::path& filePath) +{ + auto extension = filePath.extension().string(); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + return (extension == ".elf"); +} + +bool IsBootableDiscImagePath(const fs::path& filePath) +{ + auto extension = filePath.extension().string(); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + return (extension == ".iso") || + (extension == ".isz") || + (extension == ".cso") || + (extension == ".bin"); +} + bool retro_load_game(const retro_game_info* info) { CLog::GetInstance().Print(LOG_NAME, "%s\n", __FUNCTION__); fs::path filePath = info->path; - CAppConfig::GetInstance().SetPreferencePath(PREF_PS2_CDROM0_PATH, filePath); - CAppConfig::GetInstance().Save(); + if(IsBootableExecutablePath(filePath)) + { + m_bootCommand = LastOpenCommand(BootType::ELF, filePath); + } + else if(IsBootableDiscImagePath(filePath)) + { + m_bootCommand = LastOpenCommand(BootType::CD, filePath); + CAppConfig::GetInstance().SetPreferencePath(PREF_PS2_CDROM0_PATH, filePath); + CAppConfig::GetInstance().Save(); + } first_run = false; auto rgb = RETRO_PIXEL_FORMAT_XRGB8888;