├── .gitattributes ├── src ├── font.bmp ├── retroarch.ico ├── speex │ ├── version.txt │ ├── stack_alloc.h │ ├── fixed_arm4.h │ ├── resample_sse.h │ ├── fixed_bfin.h │ ├── fixed_generic.h │ ├── fixed_arm5e.h │ ├── resample_neon.h │ └── arch.h ├── GlUtil.h ├── dynlib │ ├── dynlib.c │ └── dynlib.h ├── About.h ├── CdRom.h ├── Fsm.h ├── Memory.h ├── About.cpp ├── components │ ├── VideoContext.h │ ├── Microphone.h │ ├── Allocator.h │ ├── VideoContext.cpp │ ├── Logger.h │ ├── Audio.h │ ├── Dialog.h │ ├── Input.h │ ├── Video.h │ ├── Config.h │ ├── Logger.cpp │ └── Microphone.cpp ├── Hash.h ├── Emulator.h ├── CdRom.cpp ├── libmincrypt │ ├── sha256.h │ ├── hash-internal.h │ └── sha256.c ├── main.cpp ├── RA_Implementation.cpp ├── font.py ├── States.h ├── RAHasher.vcxproj.filters ├── Util.h ├── Gl.h ├── KeyBinds.h ├── resource.h ├── GlUtil.cpp ├── libretro │ └── BareCore.h ├── menu.rc ├── Fsm.fsm ├── Application.h ├── libchdr.vcxproj.filters ├── Hash.cpp └── Hash3DS.cpp ├── .gitignore ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── c-cpp.yml ├── .gitmodules ├── etc ├── CopyDLLs.bat └── msbuild.bat ├── Makefile.RAHasher ├── README.md ├── RALibretro.sln ├── Makefile.common └── Makefile /.gitattributes: -------------------------------------------------------------------------------- 1 | *.bat text eol=crlf 2 | *.cpp text eol=lf 3 | *.h text eol=lf 4 | -------------------------------------------------------------------------------- /src/font.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroAchievements/RALibretro/HEAD/src/font.bmp -------------------------------------------------------------------------------- /src/retroarch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroAchievements/RALibretro/HEAD/src/retroarch.ico -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.opensdf 2 | *.sdf 3 | *.suo 4 | *.user 5 | *.o 6 | *.res 7 | *.swp 8 | *.log 9 | *.pdb 10 | *.zip 11 | .vs 12 | /bin 13 | /bin64 14 | /obj 15 | /src/RA_BuildVer.h 16 | 17 | .vscode 18 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # More info: http://EditorConfig.org 2 | root = true 3 | 4 | # * here means any file type 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | 9 | # latin1 is a type of ASCII, should work with mbcs 10 | [*.{h,cpp}] 11 | charset = latin1 12 | indent_style = space 13 | indent_size = 2 14 | trim_trailing_whitespace = true 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Suggest a new toolkit feature 4 | url: https://github.com/RetroAchievements/RAIntegration/discussions/new?category=ideas 5 | about: Share ideas for new features or enhancements to the toolkit 6 | - name: Report a toolkit bug 7 | url: https://github.com/RetroAchievements/RAIntegration/issues/new 8 | about: Report an issue with one of the toolkit features 9 | -------------------------------------------------------------------------------- /src/speex/version.txt: -------------------------------------------------------------------------------- 1 | SpeexDSP 1.2rc3 2 | https://www.speex.org/downloads/ 3 | 4 | Speex website indicates it has been superceded by Opus, but Opus documentation specifically 5 | states it does not have a resampler, and points back at Speex: 6 | 7 | https://gitlab.xiph.org/xiph/opusfile/-/blob/master/include/opusfile.h#L59-62 8 | 9 | (the libopusfile API does not currently provide a resampler, but 10 | the 11 | Speex resampler is a good choice if you need one) 12 | -------------------------------------------------------------------------------- /src/GlUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libretro/Components.h" 4 | 5 | #include "Gl.h" 6 | 7 | namespace GlUtil 8 | { 9 | void init(libretro::LoggerComponent* logger); 10 | 11 | GLuint createTexture(GLsizei width, GLsizei height, GLint internalFormat, GLenum format, GLenum type, GLenum filter); 12 | GLuint createShader(GLenum shaderType, const char* source); 13 | GLuint createProgram(const char* vertexShader, const char* fragmentShader); 14 | GLuint createFramebuffer(GLuint *renderbuffer, GLsizei width, GLsizei height, GLuint texture, bool depth, bool stencil); 15 | } 16 | -------------------------------------------------------------------------------- /src/dynlib/dynlib.c: -------------------------------------------------------------------------------- 1 | #include "dynlib.h" 2 | 3 | #ifdef _WIN32 4 | 5 | #include 6 | 7 | const char* dynlib_error( void ) 8 | { 9 | static char msg[ 512 ]; 10 | 11 | DWORD err = GetLastError(); 12 | 13 | DWORD res = FormatMessage( 14 | FORMAT_MESSAGE_FROM_SYSTEM, 15 | NULL, 16 | err, 17 | MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ), 18 | msg, 19 | sizeof( msg ) - 1, 20 | NULL 21 | ); 22 | 23 | if ( res == 0 ) 24 | { 25 | snprintf( msg, sizeof( msg ) - 1, "Error %lu", err ); 26 | msg[ sizeof( msg ) - 1 ] = 0; 27 | } 28 | 29 | return msg; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggest an emulator feature 3 | about: Share ideas for new features or enhancements to the emulator 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/SDL2"] 2 | path = src/SDL2 3 | url = https://github.com/RetroAchievements/SDL2 4 | [submodule "src/jsonsax"] 5 | path = src/jsonsax 6 | url = https://github.com/leiradel/jsonsax 7 | [submodule "src/miniz"] 8 | path = src/miniz 9 | url = https://github.com/richgel999/miniz.git 10 | ignore = untracked 11 | [submodule "src/RAInterface"] 12 | path = src/RAInterface 13 | url = https://github.com/RetroAchievements/RAInterface.git 14 | [submodule "src/rcheevos"] 15 | path = src/rcheevos 16 | url = https://github.com/RetroAchievements/rcheevos.git 17 | [submodule "src/libchdr"] 18 | path = src/libchdr 19 | url = https://github.com/rtissera/libchdr.git 20 | ignore = untracked 21 | -------------------------------------------------------------------------------- /src/About.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | void aboutDialog(const char* log); 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report an emulator bug 3 | about: Report an issue with the emulator 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. Windows 10] 25 | 26 | **Smartphone (please complete the following information):** 27 | - Device: [e.g. iPhone6] 28 | - OS: [e.g. iOS8.1] 29 | - Browser [e.g. stock browser, safari] 30 | - Version [e.g. 22] 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /src/dynlib/dynlib.h: -------------------------------------------------------------------------------- 1 | #ifndef DYNLIB_H 2 | #define DYNLIB_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #ifdef _WIN32 9 | #ifndef WIN32_LEAN_AND_MEAN 10 | #define WIN32_LEAN_AND_MEAN 11 | #endif 12 | 13 | #include 14 | 15 | typedef HMODULE dynlib_t; 16 | 17 | #define dynlib_open( path ) LoadLibrary( path ) 18 | #define dynlib_symbol( lib, name ) (void*)GetProcAddress( lib, name ) 19 | #define dynlib_close( lib ) FreeLibrary( lib ) 20 | 21 | const char* dynlib_error( void ); 22 | #else 23 | #include 24 | 25 | typedef void* dynlib_t; 26 | 27 | #define dynlib_open( path ) dlopen( path, RTLD_LAZY ) 28 | #define dynlib_symbol( lib, name ) dlsym( lib, name ) 29 | #define dynlib_close( lib ) dlclose( lib ) 30 | #define dynlib_error() dlerror() 31 | #endif 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif /* DYNLIB_H */ 38 | -------------------------------------------------------------------------------- /src/CdRom.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "components/Logger.h" 23 | 24 | #include 25 | 26 | int cdrom_get_cd_names(const char* filename, std::vector* disc_paths, Logger* logger); 27 | -------------------------------------------------------------------------------- /src/Fsm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Generated with FSM compiler, https://github.com/leiradel/ddlt 4 | 5 | 6 | #include "Emulator.h" 7 | #include 8 | 9 | typedef const std::string const_string; 10 | 11 | class Application; 12 | 13 | class Fsm { 14 | public: 15 | enum class State { 16 | CoreLoaded, 17 | FrameStep, 18 | GamePaused, 19 | GamePausedNoOvl, 20 | GameRunning, 21 | Quit, 22 | Start, 23 | }; 24 | 25 | Fsm(Application& slave): ctx(slave), __state(State::Start) {} 26 | 27 | State currentState() const { return __state; } 28 | 29 | #ifdef DEBUG_FSM 30 | const char* stateName(State state) const; 31 | #endif 32 | 33 | bool loadCore(const_string core); 34 | bool loadGame(const_string path); 35 | bool pauseGame(); 36 | bool pauseGameNoOvl(); 37 | bool quit(); 38 | bool resetGame(); 39 | bool resumeGame(); 40 | bool step(); 41 | bool unloadCore(); 42 | bool unloadGame(); 43 | 44 | protected: 45 | bool before() const; 46 | bool before(State state) const; 47 | void after() const; 48 | void after(State state) const; 49 | 50 | Application& ctx; 51 | State __state; 52 | }; 53 | -------------------------------------------------------------------------------- /src/Memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Core.h" 23 | 24 | #include "Emulator.h" 25 | 26 | struct rc_memory_regions_t; 27 | 28 | class Memory 29 | { 30 | public: 31 | bool init(libretro::LoggerComponent* logger); 32 | void destroy(); 33 | 34 | void attachToCore(libretro::Core* core, int consoleId); 35 | 36 | protected: 37 | void installMemoryBanks(); 38 | 39 | libretro::LoggerComponent* _logger; 40 | }; 41 | -------------------------------------------------------------------------------- /src/About.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #include "About.h" 21 | 22 | #include "components/Dialog.h" 23 | 24 | void aboutDialog(const char* log) 25 | { 26 | const WORD WIDTH = 280; 27 | const WORD LINE = 15; 28 | 29 | Dialog db; 30 | db.init("About"); 31 | 32 | WORD y = 0; 33 | 34 | db.addLabel("RALibretro \xC2\xA9 2017-2025 RetroAchievements", 0, y, WIDTH, 8); 35 | y += LINE; 36 | 37 | db.addEditbox(40000, 0, y, WIDTH, LINE, 12, (char*)log, 0, true); 38 | y += LINE * 12; 39 | 40 | db.addButton("OK", IDOK, WIDTH - 50, y, 50, 14, true); 41 | db.show(); 42 | } 43 | -------------------------------------------------------------------------------- /src/components/VideoContext.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Components.h" 23 | 24 | #include 25 | 26 | class VideoContext : public libretro::VideoContextComponent 27 | { 28 | public: 29 | bool init(libretro::LoggerComponent* logger, SDL_Window* window); 30 | void destroy(); 31 | 32 | virtual void enableCoreContext(bool enable) override; 33 | virtual void resetCoreContext() override; 34 | virtual void swapBuffers() override; 35 | 36 | private: 37 | libretro::LoggerComponent* _logger; 38 | SDL_Window* _window; 39 | SDL_GLContext _raContext; 40 | SDL_GLContext _coreContext; 41 | }; 42 | -------------------------------------------------------------------------------- /src/Hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #ifndef _WINDOWS 23 | // prevent interface from attempting to define DLL functions that require Windows APIs 24 | #define RA_EXPORTS 25 | 26 | // explicitly define APIs needed by hasher 27 | typedef unsigned char BYTE; 28 | unsigned int RA_IdentifyHash(const char* sHash); 29 | void RA_ActivateGame(unsigned int nGameId); 30 | void RA_OnLoadNewRom(BYTE* pROMData, unsigned int nROMSize); 31 | 32 | #endif 33 | 34 | #include "Emulator.h" 35 | 36 | namespace libretro 37 | { 38 | class Core; 39 | } 40 | 41 | bool romLoaded(libretro::Core* core, Logger* logger, int consoleId, const std::string& path, void* rom, size_t size, bool changingDiscs); 42 | void romUnloaded(Logger* logger); 43 | -------------------------------------------------------------------------------- /etc/CopyDLLs.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | @setlocal 3 | 4 | set W64=0 5 | if "%1"=="x64" set W64=1 6 | 7 | set PROJECTDIR=%2 8 | set BINDIR=%3 9 | 10 | rem === SDL2 is required by RALibretro, libstdc++-6 and libwinpthread-1 are required by cores === 11 | set LIBSTDCPP=libstdc++-6.dll 12 | set LIBPTHREAD=libwinpthread-1.dll 13 | set SDL=SDL2.dll 14 | 15 | set SDLSRC=SDL2\lib\x86 16 | if %W64% equ 1 set SDLSRC=SDL2\lib\x64 17 | if not exist "%BINDIR%\%SDL%" ( 18 | echo Copying SDL2.dll from %SDLSRC% 19 | copy /y "%PROJECTDIR%\%SDLSRC%\%SDL%" "%BINDIR%" 20 | ) 21 | 22 | if exist "%BINDIR%\%LIBSTDC%" ( 23 | if exist "%BINDIR%\%LIBPTHREAD%" ( 24 | exit /B 0 25 | ) 26 | ) 27 | 28 | if %W64% equ 1 if exist C:\msys64\mingw64 set SRCDIR=C:\msys64\mingw64 29 | if %W64% neq 1 if exist C:\msys64\mingw32 set SRCDIR=C:\msys64\mingw32 30 | if "%SRCDIR%"=="" set SRCDIR="%MINGW%" 31 | if not exist "%SRCDIR%" set SRCDIR=C:\mingw 32 | ) 33 | 34 | if not exist "%SRCDIR%" ( 35 | echo Could not locate MINGW 36 | exit /B 0 37 | ) 38 | 39 | if not exist "%BINDIR%\%LIBSTDCPP%" ( 40 | if not exist "%SRCDIR%\bin\%LIBSTDCPP%" ( 41 | echo WARNING: %LIBSTDCPP% not found in %SRCDIR%\bin 42 | ) else ( 43 | echo Copying %LIBSTDCPP% from %SRCDIR% 44 | copy /y "%SRCDIR%\bin\%LIBSTDCPP%" "%BINDIR%" 45 | ) 46 | ) 47 | 48 | if not exist "%BINDIR%\%LIBPTHREAD%" ( 49 | if not exist "%SRCDIR%\bin\%LIBPTHREAD%" ( 50 | echo WARNING: %LIBPTHREAD% not found in %SRCDIR%\bin 51 | ) else ( 52 | echo Copying %LIBPTHREAD% from %SRCDIR% 53 | copy /y "%SRCDIR%\bin\%LIBPTHREAD%" "%BINDIR%" 54 | ) 55 | ) 56 | -------------------------------------------------------------------------------- /src/Emulator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | const std::string& getEmulatorName(const std::string& coreName, int system); 28 | const char* getEmulatorExtensions(const std::string& coreName, int system); 29 | const char* getSystemName(int system); 30 | const char* getSystemManufacturer(int system); 31 | 32 | class Config; 33 | class Logger; 34 | bool loadCores(Config* config, Logger* logger); 35 | 36 | bool doesCoreSupportSystem(const std::string& coreFilename, int system); 37 | void getAvailableSystems(std::set& systems); 38 | void getAvailableSystemCores(int system, std::set& coreNames); 39 | int encodeCoreName(const std::string& coreName, int system); 40 | const std::string& getCoreName(int encoded, int& systemOut); 41 | const std::string* getCoreDeprecationMessage(const std::string& coreName); 42 | 43 | bool showCoresDialog(Config* config, Logger* logger, const std::string& loadedCoreName, int selectedSystem); 44 | -------------------------------------------------------------------------------- /src/components/Microphone.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2023 Brian Weiss 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Components.h" 23 | 24 | #include "libretro/libretro.h" 25 | #include "Audio.h" 26 | 27 | class Microphone : public libretro::MicrophoneComponent 28 | { 29 | public: 30 | bool init(libretro::LoggerComponent* logger); 31 | void destroy(); 32 | 33 | virtual retro_microphone_t* openMic(const retro_microphone_params_t* params) override; 34 | virtual void closeMic(retro_microphone_t* microphone) override; 35 | virtual bool getMicParams(const retro_microphone_t* microphone, retro_microphone_params_t* params) override; 36 | virtual bool getMicState(const retro_microphone_t* microphone) override; 37 | virtual bool setMicState(retro_microphone_t* microphone, bool state) override; 38 | virtual int readMic(retro_microphone_t* microphone, int16_t* frames, size_t num_frames) override; 39 | 40 | protected: 41 | libretro::LoggerComponent* _logger; 42 | 43 | Fifo* _fifo; 44 | 45 | struct SDLData; 46 | struct SDLData* _data; 47 | 48 | static void recordCallback(void* data, Uint8* stream, int len); 49 | }; 50 | -------------------------------------------------------------------------------- /src/components/Allocator.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Core.h" 23 | 24 | template 25 | class Allocator: public libretro::AllocatorComponent 26 | { 27 | public: 28 | inline bool init(libretro::LoggerComponent* logger) 29 | { 30 | _logger = logger; 31 | _head = 0; 32 | return true; 33 | } 34 | 35 | inline void destroy() {} 36 | 37 | virtual void reset() override 38 | { 39 | _head = 0; 40 | } 41 | 42 | virtual void* allocate(size_t alignment, size_t numBytes) override 43 | { 44 | size_t align_m1 = alignment - 1; 45 | size_t ptr = (_head + align_m1) & ~align_m1; 46 | 47 | if (numBytes <= (kBufferSize - ptr)) 48 | { 49 | _head = ptr + numBytes; 50 | return (void*)(_buffer + ptr); 51 | } 52 | 53 | _logger->printf(RETRO_LOG_ERROR, "Out of memory allocating %u bytes", numBytes); 54 | return NULL; 55 | } 56 | 57 | protected: 58 | enum 59 | { 60 | kBufferSize = N 61 | }; 62 | 63 | libretro::LoggerComponent* _logger; 64 | uint8_t _buffer[N]; 65 | size_t _head; 66 | }; 67 | -------------------------------------------------------------------------------- /src/components/VideoContext.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #include "VideoContext.h" 21 | 22 | #define TAG "[CONTEXT] " 23 | 24 | bool VideoContext::init(libretro::LoggerComponent* logger, SDL_Window* window) 25 | { 26 | _logger = logger; 27 | _window = window; 28 | 29 | _raContext = SDL_GL_CreateContext(_window); 30 | _coreContext = SDL_GL_CreateContext(_window); 31 | if (SDL_GL_MakeCurrent(_window, _raContext) != 0) 32 | { 33 | _logger->error(TAG "SDL_GL_MakeCurrent: %s", SDL_GetError()); 34 | return false; 35 | } 36 | 37 | return true; 38 | } 39 | 40 | void VideoContext::destroy() 41 | { 42 | } 43 | 44 | void VideoContext::enableCoreContext(bool enable) 45 | { 46 | if (enable) 47 | { 48 | SDL_GL_MakeCurrent(_window, _coreContext); 49 | } 50 | else 51 | { 52 | SDL_GL_MakeCurrent(_window, _raContext); 53 | } 54 | } 55 | 56 | void VideoContext::resetCoreContext() { 57 | SDL_GL_MakeCurrent(_window, _raContext); 58 | SDL_GL_DeleteContext(_coreContext); 59 | _coreContext = SDL_GL_CreateContext(_window); 60 | } 61 | 62 | void VideoContext::swapBuffers() 63 | { 64 | SDL_GL_SwapWindow(_window); 65 | } 66 | -------------------------------------------------------------------------------- /src/components/Logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Components.h" 23 | 24 | #ifdef LOG_TO_FILE 25 | #include 26 | #endif 27 | 28 | // Must be at least MAX_LINE_SIZE + 3 29 | #ifndef RING_LOG_MAX_BUFFER_SIZE 30 | #define RING_LOG_MAX_BUFFER_SIZE 65536 31 | #endif 32 | 33 | class Logger: public libretro::LoggerComponent 34 | { 35 | public: 36 | bool init(const char* rootFolder); 37 | void destroy(); 38 | 39 | std::string contents() const; 40 | 41 | typedef bool (*Iterator)(enum retro_log_level level, const char* line, void* ud); 42 | void iterate(Iterator iterator, void* ud) const; 43 | 44 | protected: 45 | void log(enum retro_log_level level, const char* msg, size_t length) override; 46 | 47 | void write(const void* data, size_t size); 48 | void read(void* data, size_t size); 49 | size_t peek(size_t pos, void* data, size_t size) const; 50 | 51 | inline void skip(size_t size) 52 | { 53 | _first = (_first + size) % RING_LOG_MAX_BUFFER_SIZE; 54 | _avail += size; 55 | } 56 | 57 | char _buffer[RING_LOG_MAX_BUFFER_SIZE]; 58 | size_t _avail; 59 | size_t _first; 60 | size_t _last; 61 | 62 | #ifdef LOG_TO_FILE 63 | FILE* _file; 64 | #endif 65 | }; 66 | -------------------------------------------------------------------------------- /Makefile.RAHasher: -------------------------------------------------------------------------------- 1 | # supported parameters 2 | # ARCH architecture - "x86" or "x64" [detected if not set] 3 | # DEBUG if set to anything, builds with DEBUG symbols 4 | 5 | include Makefile.common 6 | 7 | # Toolset setup 8 | CC=gcc 9 | CXX=g++ 10 | 11 | ifeq ($(OS),Windows_NT) 12 | EXE=.exe 13 | KERNEL=windows 14 | else 15 | KERNEL := $(shell uname -s) 16 | endif 17 | 18 | # compile flags 19 | DEFINES=-D_CONSOLE 20 | CFLAGS += $(DEFINES) 21 | CXXFLAGS += $(DEFINES) 22 | 23 | # main 24 | LIBS= 25 | OBJS=\ 26 | src/components/Logger.o \ 27 | src/libmincrypt/sha256.o \ 28 | src/miniz/miniz.o \ 29 | src/miniz/miniz_tdef.o \ 30 | src/miniz/miniz_tinfl.o \ 31 | src/miniz/miniz_zip.o \ 32 | src/rcheevos/src/rhash/aes.o \ 33 | src/rcheevos/src/rhash/cdreader.o \ 34 | src/rcheevos/src/rhash/hash.o \ 35 | src/rcheevos/src/rhash/hash_disc.o \ 36 | src/rcheevos/src/rhash/hash_encrypted.o \ 37 | src/rcheevos/src/rhash/hash_rom.o \ 38 | src/rcheevos/src/rhash/hash_zip.o \ 39 | src/rcheevos/src/rhash/md5.o \ 40 | src/Hash3DS.o \ 41 | src/Util.o \ 42 | src/RAHasher.o 43 | 44 | ifdef HAVE_CHD 45 | OBJS += $(CHD_OBJS) \ 46 | src/HashCHD.o 47 | endif 48 | 49 | all: $(OUTDIR)/RAHasher$(EXE) 50 | 51 | %.o: %.cpp 52 | $(CXX) $(CXXFLAGS) -c $< -o $@ 53 | 54 | %.o: %.c 55 | $(CC) $(CFLAGS) -c $< -o $@ 56 | 57 | src/RA_BuildVer.h: .git/HEAD 58 | src/RAInterface/MakeBuildVer.sh src/RA_BuildVer.h "" RA_LIBRETRO 59 | 60 | src/RAHasher.o: src/RAHasher.cpp src/RA_BuildVer.h 61 | $(CXX) $(CXXFLAGS) -c $< -o $@ 62 | 63 | $(OUTDIR)/RAHasher$(EXE): $(OBJS) 64 | mkdir -p $(OUTDIR) 65 | $(CXX) -o $@ $+ $(LDFLAGS) 66 | 67 | zip: $(OUTDIR)/RAHasher$(EXE) 68 | rm -f $(OUTDIR)/RAHasher-*.zip RAHasher-*.zip 69 | zip -9 RAHasher-$(ARCH)-$(KERNEL)-`git describe --tags | sed s/\-.*//g | tr -d "\n"`.zip $(OUTDIR)/RAHasher$(EXE) 70 | 71 | clean: 72 | rm -f $(OUTDIR)/RAHasher$(EXE) $(OBJS) $(OUTDIR)/RAHasher*.zip RAHasher*.zip 73 | 74 | .PHONY: clean FORCE 75 | -------------------------------------------------------------------------------- /src/components/Audio.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Components.h" 23 | 24 | #include "speex/speex_resampler.h" 25 | 26 | #include 27 | 28 | class Fifo 29 | { 30 | public: 31 | bool init(size_t size); 32 | void destroy(); 33 | void reset(); 34 | 35 | void read(void* data, size_t size); 36 | void write(const void* data, size_t size); 37 | 38 | inline size_t size() { return _size; } 39 | 40 | size_t occupied(); 41 | size_t free(); 42 | 43 | protected: 44 | SDL_mutex* _mutex; 45 | uint8_t* _buffer; 46 | size_t _size; 47 | size_t _avail; 48 | size_t _first; 49 | size_t _last; 50 | }; 51 | 52 | class Audio: public libretro::AudioComponent 53 | { 54 | public: 55 | bool init(libretro::LoggerComponent* logger, double sample_rate, int channels, Fifo* fifo); 56 | void destroy(); 57 | 58 | virtual bool setRate(double rate) override; 59 | virtual void mix(const int16_t* samples, size_t frames) override; 60 | 61 | void setBlocking(bool value) { _blocking = value; } 62 | 63 | protected: 64 | libretro::LoggerComponent* _logger; 65 | 66 | double _sampleRate; 67 | double _coreRate; 68 | int _channels; 69 | bool _blocking; 70 | 71 | double _currentRatio; 72 | double _originalRatio; 73 | SpeexResamplerState* _resamplerLeft; 74 | SpeexResamplerState* _resamplerRight; 75 | 76 | Fifo* _fifo; 77 | }; 78 | -------------------------------------------------------------------------------- /src/CdRom.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #include "CdRom.h" 21 | 22 | #include "Util.h" 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | static int cdrom_get_cd_names_m3u(const char* filename, std::vector* disc_paths, Logger* logger) 30 | { 31 | int count = 0; 32 | char buffer[2048], *ptr, *start; 33 | FILE* fp = util::openFile(logger, filename, "r"); 34 | if (fp) 35 | { 36 | size_t bytes = fread(buffer, 1, sizeof(buffer), fp); 37 | fclose(fp); 38 | 39 | buffer[bytes] = '\0'; 40 | ptr = buffer; 41 | do 42 | { 43 | start = ptr; 44 | while (*ptr && *ptr != '\n') 45 | ++ptr; 46 | 47 | if (ptr > start) 48 | { 49 | std::string path(start, ptr - start); 50 | disc_paths->push_back(path); 51 | ++count; 52 | } 53 | 54 | if (!*ptr) 55 | break; 56 | 57 | ++ptr; 58 | } while (true); 59 | } 60 | 61 | return count; 62 | } 63 | 64 | int cdrom_get_cd_names(const char* filename, std::vector* disc_paths, Logger* logger) 65 | { 66 | disc_paths->clear(); 67 | 68 | int len = strlen(filename); 69 | if (len > 4 && strcasecmp(&filename[len - 4], ".m3u") == 0) 70 | return cdrom_get_cd_names_m3u(filename, disc_paths, logger); 71 | 72 | std::string filename_path = util::fileNameWithExtension(filename); 73 | disc_paths->push_back(std::move(filename_path)); 74 | return 1; 75 | } 76 | -------------------------------------------------------------------------------- /src/libmincrypt/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ 29 | 30 | #include 31 | #include "hash-internal.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif // __cplusplus 36 | 37 | typedef HASH_CTX SHA256_CTX; 38 | 39 | void SHA256_init(SHA256_CTX* ctx); 40 | void SHA256_update(SHA256_CTX* ctx, const void* data, int len); 41 | const uint8_t* SHA256_final(SHA256_CTX* ctx); 42 | 43 | // Convenience method. Returns digest address. 44 | const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest); 45 | 46 | #define SHA256_DIGEST_SIZE 32 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif // __cplusplus 51 | 52 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RALibretro 2 | 3 | RALibretro is a multi-emulator that can be used to develop RetroAchievements and, of course, earn them. 4 | 5 | The "multi-emulation" feature is only possible because it uses [libretro](https://github.com/libretro/) cores to do the actual emulation. What RALibretro does is to connect the emulation to the tools used to create RetroAchievements. 6 | 7 | The integration with RetroAchievements.org site is done by the [RAIntegration](https://github.com/RetroAchievements/RAIntegration). 8 | 9 | 10 | ## Building RALibretro with MSYS2/Makefile 11 | 12 | ### Install MSYS2 13 | 14 | 1. Go to [http://www.msys2.org/](http://www.msys2.org/) and download the 32 bit version. 15 | 2. Follow the installation instructions on the site [http://www.msys2.org/](http://www.msys2.org/). 16 | 3. When on the prompt for the first time, run `pacman -Syu` (**NOTE**: at the end of this command it will ask you to close the terminal window **without** going back to the prompt.) 17 | 4. Launch the MSYS2 terminal again and run `pacman -Su` 18 | 19 | ### Install the toolchain 20 | 21 | ``` 22 | $ pacman -S make git zip mingw-w64-i686-gcc mingw-w64-i686-SDL2 mingw-w64-i686-gcc-libs 23 | ``` 24 | 25 | ### Clone the repo 26 | 27 | ``` 28 | $ git clone --recursive --depth 1 https://github.com/RetroAchievements/RALibretro.git 29 | ``` 30 | 31 | ### Build 32 | 33 | ``` 34 | $ cd RALibretro 35 | $ make 36 | ``` 37 | 38 | **NOTE**: use `make` for a release build or `make DEBUG=1` for a debug build. Don't forget to run `make clean` first if switching between a release build and a debug build. 39 | 40 | ## Building RALibretro with Visual Studio 41 | 42 | ### Clone the repo 43 | 44 | ``` 45 | > git clone --recursive --depth 1 https://github.com/RetroAchievements/RALibretro.git 46 | ``` 47 | 48 | ### Build 49 | 50 | Load `RALibretro.sln` in Visual Studio and build it. 51 | 52 | ## Command Line Arguments 53 | 54 | Argument|Description 55 | -|- 56 | -c [--core]|the core's name, e.g. `--core picodrive_libretro` 57 | -s [--system]|the system id, see ConsoleID in [RAInterface/RA_Consoles.h](https://github.com/RetroAchievements/RAInterface/blob/master/RA_Consoles.h), e.g. `--system 1` 58 | -g [--game]|full path to the game's file, e.g. `--game "C:\ROMS\GEN\Demons Of Asteborg Demo.gen"` 59 | 60 | In order to run a game on startup, provide the core, system and game, e.g.: 61 | 62 | `RALibretro.exe --core picodrive_libretro --system 1 --game "C:\ROMS\GEN\Demons Of Asteborg Demo.gen"` 63 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #define WINDOWS_IGNORE_PACKING_MISMATCH 1 // prevent "Windows headers require the default packing option" error - need to upgrade SDL library to fix it 21 | 22 | #include 23 | #include 24 | 25 | #include "Application.h" 26 | #include "Util.h" 27 | 28 | #include 29 | 30 | extern Application app; 31 | 32 | bool isGameActive() 33 | { 34 | return app.isGameActive(); 35 | } 36 | 37 | void getGameName(char name[], size_t len) 38 | { 39 | std::string fileName = util::fileName(app.gameName()); 40 | strncpy(name, fileName.c_str(), len); 41 | name[len - 1] = '\0'; 42 | } 43 | 44 | void pause() 45 | { 46 | app.pauseGame(true); 47 | } 48 | 49 | void resume() 50 | { 51 | app.pauseGame(false); 52 | } 53 | 54 | void reset() 55 | { 56 | // this is called when the user switches from non-hardcore to hardcore - validate the config settings 57 | if (app.validateHardcoreEnablement()) 58 | app.resetGame(); 59 | } 60 | 61 | void loadROM(const char* path) 62 | { 63 | app.loadGame(path); 64 | } 65 | 66 | extern "C" void abort_handler(int signal_number) 67 | { 68 | app.logger().error("[APP] abort() called"); 69 | app.unloadCore(); 70 | app.destroy(); 71 | } 72 | 73 | int main(int argc, char* argv[]) 74 | { 75 | signal(SIGABRT, &abort_handler); 76 | 77 | bool ok = app.init("RALibRetro", 640, 480); 78 | ok &= app.handleArgs(argc, argv); 79 | 80 | if (ok) 81 | { 82 | #if defined(MINGW) || defined(__MINGW32__) || defined(__MINGW64__) 83 | app.run(); 84 | #else 85 | __try 86 | { 87 | app.run(); 88 | } 89 | __except (EXCEPTION_EXECUTE_HANDLER) 90 | { 91 | app.logger().error("[APP] Unhandled exception %08X", GetExceptionCode()); 92 | } 93 | #endif 94 | 95 | app.destroy(); 96 | } 97 | 98 | return ok ? 0 : 1; 99 | } 100 | -------------------------------------------------------------------------------- /src/libmincrypt/hash-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ 29 | 30 | #include 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif // __cplusplus 35 | 36 | struct HASH_CTX; // forward decl 37 | 38 | typedef struct HASH_VTAB { 39 | void (* const init)(struct HASH_CTX*); 40 | void (* const update)(struct HASH_CTX*, const void*, int); 41 | const uint8_t* (* const final)(struct HASH_CTX*); 42 | const uint8_t* (* const hash)(const void*, int, uint8_t*); 43 | int size; 44 | } HASH_VTAB; 45 | 46 | typedef struct HASH_CTX { 47 | const HASH_VTAB * f; 48 | uint64_t count; 49 | uint8_t buf[64]; 50 | uint32_t state[8]; // upto SHA2 51 | } HASH_CTX; 52 | 53 | #define HASH_init(ctx) (ctx)->f->init(ctx) 54 | #define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) 55 | #define HASH_final(ctx) (ctx)->f->final(ctx) 56 | #define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest) 57 | #define HASH_size(ctx) (ctx)->f->size 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif // __cplusplus 62 | 63 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ -------------------------------------------------------------------------------- /src/RA_Implementation.cpp: -------------------------------------------------------------------------------- 1 | #include "RA_Interface.h" 2 | 3 | #include "RA_Emulators.h" 4 | 5 | #include 6 | 7 | #include "RA_BuildVer.h" 8 | 9 | extern HWND g_mainWindow; 10 | 11 | bool isGameActive(); 12 | void getGameName(char name[], size_t len); 13 | void pause(); 14 | void resume(); 15 | void reset(); 16 | void loadROM(const char* path); 17 | 18 | 19 | // returns -1 if not found 20 | int GetMenuItemIndex(HMENU hMenu, const char* ItemName) 21 | { 22 | int index = 0; 23 | char buf[256]; 24 | 25 | while (index < GetMenuItemCount(hMenu)) 26 | { 27 | if (GetMenuString(hMenu, index, buf, sizeof(buf) - 1, MF_BYPOSITION) && !strcmp(ItemName, buf)) 28 | { 29 | return index; 30 | } 31 | 32 | index++; 33 | } 34 | 35 | return -1; 36 | } 37 | 38 | 39 | // Return whether a game has been loaded. Should return FALSE if 40 | // no ROM is loaded, or a ROM has been unloaded. 41 | bool GameIsActive() 42 | { 43 | return isGameActive(); 44 | } 45 | 46 | 47 | void CauseUnpause() 48 | { 49 | resume(); 50 | } 51 | 52 | 53 | // Perform whatever action is required to Pause emulation. 54 | void CausePause() 55 | { 56 | pause(); 57 | } 58 | 59 | 60 | // Perform whatever function in the case of needing to rebuild the menu. 61 | void RebuildMenu() 62 | { 63 | HMENU mainMenu = GetMenu(g_mainWindow); 64 | if (!mainMenu) return; 65 | 66 | // get file menu index 67 | int index = GetMenuItemIndex(mainMenu, "&RetroAchievements"); 68 | if (index >= 0) 69 | DeleteMenu(mainMenu, index, MF_BYPOSITION); 70 | 71 | // ##RA embed RA 72 | AppendMenu(mainMenu, MF_POPUP | MF_STRING, (UINT_PTR)RA_CreatePopupMenu(), TEXT("&RetroAchievements")); 73 | InvalidateRect(g_mainWindow, NULL, TRUE); 74 | DrawMenuBar(g_mainWindow); 75 | } 76 | 77 | 78 | // sNameOut points to a 256 character buffer. 79 | // sNameOut should have copied into it the estimated game title 80 | // for the ROM, if one can be inferred from the ROM. 81 | void GetEstimatedGameTitle(char* sNameOut) 82 | { 83 | getGameName(sNameOut, 256); 84 | } 85 | 86 | 87 | void ResetEmulation() 88 | { 89 | reset(); 90 | } 91 | 92 | 93 | void LoadROM(const char* sFullPath) 94 | { 95 | loadROM(sFullPath); 96 | } 97 | 98 | void RA_Init(HWND hWnd) 99 | { 100 | // initialize the DLL 101 | RA_Init(hWnd, RA_Libretro, RA_LIBRETRO_VERSION_FULL); 102 | 103 | // provide callbacks to the DLL 104 | RA_InstallSharedFunctions(NULL, &CauseUnpause, &CausePause, &RebuildMenu, &GetEstimatedGameTitle, &ResetEmulation, &LoadROM); 105 | 106 | // add a placeholder menu item and start the login process - menu will be updated when login completes 107 | RebuildMenu(); 108 | 109 | // ensure titlebar text matches expected format 110 | RA_UpdateAppTitle(""); 111 | } 112 | -------------------------------------------------------------------------------- /src/font.py: -------------------------------------------------------------------------------- 1 | #! python 2 | 3 | with open('font.bmp', 'rb') as f: 4 | data = bytearray(f.read()) 5 | 6 | # this assumes the file is a 4-bpp bitmap. 7 | 8 | start = 0x42 9 | width = 144 10 | height = 272 11 | stride = width / 2 12 | 13 | with open('components/BitmapFont.h', 'w') as f: 14 | f.write("/*\n"); 15 | f.write("Copyright (C) 2024 Brian Weiss\n"); 16 | f.write("\n"); 17 | f.write("This file is part of RALibretro.\n"); 18 | f.write("\n"); 19 | f.write("RALibretro is free software: you can redistribute it and/or modify\n"); 20 | f.write("it under the terms of the GNU General Public License as published by\n"); 21 | f.write("the Free Software Foundation, either version 3 of the License, or\n"); 22 | f.write("(at your option) any later version.\n"); 23 | f.write("\n"); 24 | f.write("RALibretro is distributed in the hope that it will be useful,\n"); 25 | f.write("but WITHOUT ANY WARRANTY; without even the implied warranty of\n"); 26 | f.write("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"); 27 | f.write("GNU General Public License for more details.\n"); 28 | f.write("\n"); 29 | f.write("You should have received a copy of the GNU General Public License\n"); 30 | f.write("along with RALibretro. If not, see .\n"); 31 | f.write("*/\n"); 32 | f.write("\n"); 33 | f.write("#pragma once\n"); 34 | f.write("\n"); 35 | f.write("/* https://github.com/epto/epto-fonts/blob/master/font-images/img/simple-8x16.png */\n"); 36 | f.write("\n"); 37 | 38 | f.write("static uint8_t _bitmapFont[] = {\n") 39 | 40 | for c in range(0x20, 0x80): 41 | f.write(' /* ' ) 42 | f.write(hex(c)) 43 | f.write(': ') 44 | f.write(chr(c)) 45 | f.write(" */\n") 46 | 47 | cy = (int)(c // 16) 48 | cx = (int)(c % 16) 49 | input = (height - 1 - cy * 17) * width + cx * 9 50 | for y in range(0, 16): 51 | f.write(' 0b'); 52 | for x in range(0, 8): 53 | i = input + x; 54 | b = data[(int)(start + i // 2)] 55 | if i & 1 == 0: 56 | f.write('1' if (b & 0xF0) != 0 else '0') 57 | else: 58 | f.write('1' if (b & 0x0F) != 0 else '0') 59 | 60 | f.write(",\n"); 61 | input -= width; 62 | 63 | f.write("\n"); 64 | 65 | f.write(" /* 0x80: unknown char */\n") 66 | f.write(" 0b00000000,\n") 67 | f.write(" 0b00000000,\n") 68 | f.write(" 0b00000000,\n") 69 | f.write(" 0b01111110,\n") 70 | f.write(" 0b01100110,\n") 71 | f.write(" 0b01100110,\n") 72 | f.write(" 0b01100110,\n") 73 | f.write(" 0b01100110,\n") 74 | f.write(" 0b01100110,\n") 75 | f.write(" 0b01111110,\n") 76 | f.write(" 0b00000000,\n") 77 | f.write(" 0b00000000,\n") 78 | f.write(" 0b00000000,\n") 79 | f.write(" 0b00000000,\n") 80 | f.write(" 0b00000000,\n") 81 | f.write(" 0b00000000\n") 82 | 83 | f.write("};\n"); -------------------------------------------------------------------------------- /src/States.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibRetro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "components/Config.h" 23 | #include "components/Logger.h" 24 | #include "components/Video.h" 25 | 26 | #include "libretro/Core.h" 27 | 28 | class States 29 | { 30 | public: 31 | bool init(Logger* logger, Config* config, Video* video); 32 | 33 | void setGame(const std::string& gameFileName, int system, const std::string& coreName, libretro::Core* core); 34 | 35 | std::string getSRamPath() const; 36 | std::string getStatePath(unsigned ndx) const; 37 | 38 | bool saveState(const std::string& path); 39 | bool saveState(unsigned ndx); 40 | bool loadState(const std::string& path); 41 | bool loadState(unsigned ndx); 42 | 43 | void loadSRAM(libretro::Core* core); 44 | void saveSRAM(libretro::Core* core); 45 | void periodicSaveSRAM(libretro::Core* core); 46 | 47 | void migrateFiles(); 48 | bool existsState(unsigned ndx); 49 | 50 | std::string serializeSettings() const; 51 | bool deserializeSettings(const char* json); 52 | 53 | void showDialog(); 54 | 55 | protected: 56 | enum Path 57 | { 58 | Saves = 0x00, 59 | State = 0x01, 60 | System = 0x02, 61 | Core = 0x04, 62 | Game = 0x08 63 | }; 64 | Path _sramPath = Path::Saves; 65 | Path _statePath = Path::Saves; 66 | 67 | static const States::Path _sramPaths[]; 68 | static const States::Path _statePaths[]; 69 | static const int _saveIntervals[]; 70 | 71 | Logger* _logger; 72 | Config* _config; 73 | Video* _video; 74 | 75 | std::string _gameFileName; 76 | int _system = 0; 77 | std::string _coreName; 78 | libretro::Core* _core = NULL; 79 | int _saveInterval = 0; 80 | void* _lastSaveData = NULL; 81 | time_t _lastSave = 0; 82 | 83 | private: 84 | std::string buildPath(Path path) const; 85 | static std::string encodePath(Path path); 86 | static Path decodePath(const std::string& shorthand); 87 | 88 | std::string getSRamPath(Path path) const; 89 | std::string getStatePath(unsigned ndx, Path path, bool bOldFormat) const; 90 | 91 | void saveSRAM(void* sramData, size_t sramSize); 92 | void restoreFrameBuffer(const void* pixels, unsigned image_width, unsigned image_height, unsigned pitch); 93 | 94 | bool loadRAState1(unsigned char* input, size_t size, std::string& errorBuffer); 95 | }; 96 | -------------------------------------------------------------------------------- /etc/msbuild.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | rem === Globals === 5 | 6 | set BUILDCLEAN=0 7 | set DEBUG=0 8 | set RELEASE=0 9 | set W32=0 10 | set W64=0 11 | 12 | for %%A in (%*) do ( 13 | if /I "%%A" == "Clean" ( 14 | set BUILDCLEAN=1 15 | ) else if /I "%%A" == "Debug" ( 16 | set DEBUG=1 17 | ) else if /I "%%A" == "Release" ( 18 | set RELEASE=1 19 | ) else if /I "%%A" == "x86" ( 20 | set W32=1 21 | ) else if /I "%%A" == "x64" ( 22 | set W64=1 23 | ) 24 | ) 25 | 26 | if %W32% equ 0 if %W64% equ 0 ( 27 | set W64=1 28 | ) 29 | 30 | echo Initializing Visual Studio environment 31 | if "%VSINSTALLDIR%"=="" set VSINSTALLDIR=%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\ 32 | if not exist "%VSINSTALLDIR%" set VSINSTALLDIR=%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\ 33 | if not exist "%VSINSTALLDIR%" set VSINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\ 34 | if not exist "%VSINSTALLDIR%" ( 35 | echo Could not determine VSINSTALLDIR 36 | exit /B 1 37 | ) 38 | echo using VSINSTALLDIR=%VSINSTALLDIR% 39 | 40 | call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars32.bat" 41 | 42 | rem === Build each project === 43 | 44 | if %BUILDCLEAN% equ 1 ( 45 | if %DEBUG% equ 1 ( 46 | call :build Clean Debug || goto eof 47 | ) 48 | 49 | if %RELEASE% equ 1 ( 50 | call :build Clean Release || goto eof 51 | ) 52 | ) else ( 53 | if %DEBUG% equ 1 ( 54 | call :build RALibretro Debug || goto eof 55 | ) 56 | 57 | if %RELEASE% equ 1 ( 58 | call :build RALibretro Release || goto eof 59 | ) 60 | ) 61 | 62 | exit /B 0 63 | 64 | rem === Build subroutine === 65 | 66 | :build 67 | 68 | set PROJECT=%~1 69 | set CONFIG=%~2 70 | 71 | if %W32% equ 1 call :build2 %PROJECT% %CONFIG% x86 72 | if %W64% equ 1 call :build2 %PROJECT% %CONFIG% x64 73 | 74 | exit /B %ERRORLEVEL% 75 | 76 | :build2 77 | 78 | rem === Do the build === 79 | 80 | echo. 81 | echo Building %~1 %~2 %~3 82 | 83 | rem -- vsbuild doesn't like periods in the "-t" parameter, so replace them with underscores 84 | rem -- https://stackoverflow.com/questions/56253635/what-could-i-be-doing-wrong-with-my-msbuild-argument 85 | rem -- https://stackoverflow.com/questions/15441422/replace-character-of-string-in-batch-script/25812295 86 | set ESCAPEDKEY=%~1 87 | :replace_periods 88 | for /f "tokens=1* delims=." %%i in ("%ESCAPEDKEY%") do ( 89 | set ESCAPEDKEY=%%j 90 | if defined ESCAPEDKEY ( 91 | set ESCAPEDKEY=%%i_%%j 92 | goto replace_periods 93 | ) else ( 94 | set ESCAPEDKEY=%%i 95 | ) 96 | ) 97 | 98 | msbuild.exe RALibretro.sln -t:%ESCAPEDKEY% -p:Configuration=%~2 -p:Platform=%~3 /nowarn:C4091 99 | set RESULT=%ERRORLEVEL% 100 | 101 | rem === If build failed, bail === 102 | 103 | if not %RESULT% equ 0 ( 104 | echo %~1 %~2 failed: %RESULT% 105 | exit /B %RESULT% 106 | ) 107 | 108 | rem === For termination from within function === 109 | 110 | :eof 111 | exit /B %ERRORLEVEL% 112 | -------------------------------------------------------------------------------- /RALibretro.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29201.188 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RALibretro", "src\RALibretro.vcxproj", "{418D11DE-D07C-4BF2-A454-ACCCB451BBE1}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{28CC2E0D-4F95-4A78-AA58-BA25530C93F1}" 9 | ProjectSection(SolutionItems) = preProject 10 | .editorconfig = .editorconfig 11 | EndProjectSection 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RAHasher", "src\RAHasher.vcxproj", "{5E39410E-0276-4024-8697-1BD685207142}" 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchdr", "src\libchdr.vcxproj", "{6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|x64 = Debug|x64 20 | Debug|x86 = Debug|x86 21 | Release|x64 = Release|x64 22 | Release|x86 = Release|x86 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Debug|x64.ActiveCfg = Debug|x64 26 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Debug|x64.Build.0 = Debug|x64 27 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Debug|x86.ActiveCfg = Debug|Win32 28 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Debug|x86.Build.0 = Debug|Win32 29 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Release|x64.ActiveCfg = Release|x64 30 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Release|x64.Build.0 = Release|x64 31 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Release|x86.ActiveCfg = Release|Win32 32 | {418D11DE-D07C-4BF2-A454-ACCCB451BBE1}.Release|x86.Build.0 = Release|Win32 33 | {5E39410E-0276-4024-8697-1BD685207142}.Debug|x64.ActiveCfg = Debug|x64 34 | {5E39410E-0276-4024-8697-1BD685207142}.Debug|x64.Build.0 = Debug|x64 35 | {5E39410E-0276-4024-8697-1BD685207142}.Debug|x86.ActiveCfg = Debug|Win32 36 | {5E39410E-0276-4024-8697-1BD685207142}.Debug|x86.Build.0 = Debug|Win32 37 | {5E39410E-0276-4024-8697-1BD685207142}.Release|x64.ActiveCfg = Release|x64 38 | {5E39410E-0276-4024-8697-1BD685207142}.Release|x64.Build.0 = Release|x64 39 | {5E39410E-0276-4024-8697-1BD685207142}.Release|x86.ActiveCfg = Release|Win32 40 | {5E39410E-0276-4024-8697-1BD685207142}.Release|x86.Build.0 = Release|Win32 41 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Debug|x64.ActiveCfg = Debug|x64 42 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Debug|x64.Build.0 = Debug|x64 43 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Debug|x86.ActiveCfg = Debug|Win32 44 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Debug|x86.Build.0 = Debug|Win32 45 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Release|x64.ActiveCfg = Release|x64 46 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Release|x64.Build.0 = Release|x64 47 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Release|x86.ActiveCfg = Release|Win32 48 | {6CFBE506-0BC2-4DBC-B7F2-D879C140D5D1}.Release|x86.Build.0 = Release|Win32 49 | EndGlobalSection 50 | GlobalSection(SolutionProperties) = preSolution 51 | HideSolutionNode = FALSE 52 | EndGlobalSection 53 | GlobalSection(ExtensibilityGlobals) = postSolution 54 | SolutionGuid = {71DAD649-EAE3-4C0D-B698-FF8A5EE83E01} 55 | EndGlobalSection 56 | EndGlobal 57 | -------------------------------------------------------------------------------- /src/components/Dialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | class Dialog 26 | { 27 | public: 28 | typedef const char* (*GetOption)(int index, void* udata); 29 | 30 | Dialog(); 31 | ~Dialog(); 32 | 33 | void init(const char* title); 34 | void addCheckbox(const char* caption, DWORD id, WORD x, WORD y, WORD w, WORD h, bool* checked); 35 | void addLabel(const char* caption, WORD x, WORD y, WORD w, WORD h); 36 | void addLabel(const char* caption, DWORD id, WORD x, WORD y, WORD w, WORD h); 37 | void addButton(const char* caption, DWORD id, WORD x, WORD y, WORD w, WORD h, bool isDefault); 38 | void addCombobox(DWORD id, WORD x, WORD y, WORD w, WORD h, WORD maxDropDownHeight, GetOption get_option, void* udata, int* selected); 39 | void addEditbox(DWORD id, WORD x, WORD y, WORD w, WORD h, WORD lines, char* contents, size_t maxSize, bool readOnly); 40 | 41 | bool show(); 42 | 43 | protected: 44 | enum Type 45 | { 46 | kCheckbox, 47 | kCombobox, 48 | kEditbox 49 | }; 50 | 51 | struct ControlData 52 | { 53 | Type _type; 54 | DWORD _id; 55 | 56 | union 57 | { 58 | bool* _checked; 59 | 60 | struct 61 | { 62 | GetOption _getOption; 63 | void* _udata; 64 | int* _selected; 65 | }; 66 | 67 | struct 68 | { 69 | char* _contents; 70 | size_t _maxSize; 71 | }; 72 | }; 73 | }; 74 | 75 | void align(size_t alignment); 76 | 77 | void writeDlgItemTemplateEx(DWORD helpId, DWORD exStyle, DWORD style, WORD x, WORD y, WORD cx, WORD cy, DWORD id, DWORD windowClass, const char* title, WORD extraCount); 78 | 79 | void write(void* data, size_t size); 80 | void writeStr(const char* str); 81 | void writeWide(const WCHAR* str); 82 | 83 | template void write(T t) 84 | { 85 | write(&t, sizeof(t)); 86 | } 87 | 88 | void update(WORD x, WORD y, WORD w, WORD h); 89 | 90 | virtual void initControls(HWND hwnd); 91 | virtual void retrieveData(HWND hwnd); 92 | 93 | static INT_PTR CALLBACK s_dialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); 94 | virtual INT_PTR dialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { return FALSE; } 95 | virtual void markClosed(HWND hwnd); 96 | 97 | void* _template; 98 | size_t _size; 99 | size_t _reserved; 100 | 101 | WORD* _numControls; 102 | WORD* _width; 103 | WORD* _height; 104 | 105 | std::vector _controlData; 106 | bool _updated; 107 | }; 108 | -------------------------------------------------------------------------------- /.github/workflows/c-cpp.yml: -------------------------------------------------------------------------------- 1 | name: C/C++ CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | tags: 9 | - "*" 10 | pull_request: 11 | branches: 12 | - master 13 | - develop 14 | 15 | jobs: 16 | RALibretro-Win32: 17 | runs-on: windows-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v2 21 | with: 22 | submodules: recursive 23 | - name: Install MSBuild 24 | uses: microsoft/setup-msbuild@v1.0.2 25 | - name: Build 26 | run: msbuild.exe RALibretro.sln -p:Configuration=Release -p:Platform=x86 27 | 28 | RALibretro-Win64: 29 | runs-on: windows-latest 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v2 33 | with: 34 | submodules: recursive 35 | - name: Install MSBuild 36 | uses: microsoft/setup-msbuild@v1.0.2 37 | - name: Build 38 | run: msbuild.exe RALibretro.sln -p:Configuration=Release -p:Platform=x64 39 | 40 | RALibretro-Win32-cross-compile: 41 | runs-on: ubuntu-latest 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v2 45 | with: 46 | submodules: recursive 47 | - name: Install dependencies 48 | run: | 49 | sudo apt-get update 50 | sudo apt-get install gcc-multilib # bits/libc-header-start.h 51 | - name: Install MinGW 52 | uses: egor-tensin/setup-mingw@v2 53 | - name: Build 54 | run: make ARCH=x86 55 | 56 | RALibretro-Win64-cross-compile: 57 | runs-on: ubuntu-latest 58 | steps: 59 | - name: Checkout 60 | uses: actions/checkout@v2 61 | with: 62 | submodules: recursive 63 | - name: Install dependencies 64 | run: | 65 | sudo apt-get update 66 | sudo apt-get install gcc-multilib # bits/libc-header-start.h 67 | - name: Install MinGW 68 | uses: egor-tensin/setup-mingw@v2 69 | - name: Build 70 | run: make ARCH=x64 71 | 72 | RAHasher-linux-x86: 73 | runs-on: ubuntu-latest 74 | steps: 75 | - name: Checkout 76 | uses: actions/checkout@v2 77 | with: 78 | submodules: recursive 79 | - name: Install dependencies 80 | run: | 81 | sudo apt-get update 82 | sudo apt-get install gcc-multilib g++-multilib # bits/libc-header-start.h, bits/c++config.h 83 | - name: Build 84 | run: make ARCH=x86 HAVE_CHD=1 -f Makefile.RAHasher 85 | - name: Zip 86 | if: startsWith(github.ref, 'refs/tags/') 87 | run: make ARCH=x86 HAVE_CHD=1 -f Makefile.RAHasher zip 88 | - name: Release 89 | uses: softprops/action-gh-release@v1 90 | if: startsWith(github.ref, 'refs/tags/') 91 | with: 92 | draft: true 93 | files: RAHasher*.zip 94 | 95 | RAHasher-linux-x64: 96 | runs-on: ubuntu-latest 97 | steps: 98 | - name: Checkout 99 | uses: actions/checkout@v2 100 | with: 101 | submodules: recursive 102 | - name: Install dependencies 103 | run: | 104 | sudo apt-get update 105 | sudo apt-get install gcc-multilib # bits/libc-header-start.h 106 | - name: Build 107 | run: make ARCH=x64 HAVE_CHD=1 -f Makefile.RAHasher 108 | - name: Zip 109 | if: startsWith(github.ref, 'refs/tags/') 110 | run: make ARCH=x64 HAVE_CHD=1 -f Makefile.RAHasher zip 111 | - name: Release 112 | uses: softprops/action-gh-release@v1 113 | if: startsWith(github.ref, 'refs/tags/') 114 | with: 115 | draft: true 116 | files: RAHasher*.zip 117 | -------------------------------------------------------------------------------- /src/RAHasher.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {dbb91ad7-cb9c-4d0b-8000-4c52930b4044} 18 | 19 | 20 | {1e293426-6398-4c86-81b8-5e0004cc542d} 21 | 22 | 23 | {4ea653d5-1cc2-4ca4-b75e-4e5ec8fe3ecd} 24 | 25 | 26 | {be15c3d6-6a8d-418e-b432-31e7fc552895} 27 | 28 | 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files\RALibRetro 35 | 36 | 37 | Source Files\miniz 38 | 39 | 40 | Source Files\miniz 41 | 42 | 43 | Source Files\miniz 44 | 45 | 46 | Source Files\miniz 47 | 48 | 49 | Source Files\RALibRetro 50 | 51 | 52 | Source Files\rhash 53 | 54 | 55 | Source Files\rhash 56 | 57 | 58 | Source Files\rhash 59 | 60 | 61 | Source Files\RALibRetro 62 | 63 | 64 | Source Files\RALibRetro 65 | 66 | 67 | Source Files\rhash 68 | 69 | 70 | Source Files\libmincrypt 71 | 72 | 73 | Source Files\rhash 74 | 75 | 76 | Source Files\rhash 77 | 78 | 79 | Source Files\rhash 80 | 81 | 82 | Source Files\rhash 83 | 84 | 85 | 86 | 87 | Source Files\rhash 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/speex/stack_alloc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Jean-Marc Valin */ 2 | /** 3 | @file stack_alloc.h 4 | @brief Temporary memory allocation on stack 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef STACK_ALLOC_H 36 | #define STACK_ALLOC_H 37 | 38 | #ifdef USE_ALLOCA 39 | # ifdef WIN32 40 | # include 41 | # else 42 | # ifdef HAVE_ALLOCA_H 43 | # include 44 | # else 45 | # include 46 | # endif 47 | # endif 48 | #endif 49 | 50 | /** 51 | * @def ALIGN(stack, size) 52 | * 53 | * Aligns the stack to a 'size' boundary 54 | * 55 | * @param stack Stack 56 | * @param size New size boundary 57 | */ 58 | 59 | /** 60 | * @def PUSH(stack, size, type) 61 | * 62 | * Allocates 'size' elements of type 'type' on the stack 63 | * 64 | * @param stack Stack 65 | * @param size Number of elements 66 | * @param type Type of element 67 | */ 68 | 69 | /** 70 | * @def VARDECL(var) 71 | * 72 | * Declare variable on stack 73 | * 74 | * @param var Variable to declare 75 | */ 76 | 77 | /** 78 | * @def ALLOC(var, size, type) 79 | * 80 | * Allocate 'size' elements of 'type' on stack 81 | * 82 | * @param var Name of variable to allocate 83 | * @param size Number of elements 84 | * @param type Type of element 85 | */ 86 | 87 | #ifdef ENABLE_VALGRIND 88 | 89 | #include 90 | 91 | #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) 92 | 93 | #define PUSH(stack, size, type) (VALGRIND_MAKE_NOACCESS(stack, 1000),ALIGN((stack),sizeof(type)),VALGRIND_MAKE_WRITABLE(stack, ((size)*sizeof(type))),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) 94 | 95 | #else 96 | 97 | #define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1)) 98 | 99 | #define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)),(stack)+=((size)*sizeof(type)),(type*)((stack)-((size)*sizeof(type)))) 100 | 101 | #endif 102 | 103 | #if defined(VAR_ARRAYS) 104 | #define VARDECL(var) 105 | #define ALLOC(var, size, type) type var[size] 106 | #elif defined(USE_ALLOCA) 107 | #define VARDECL(var) var 108 | #define ALLOC(var, size, type) var = alloca(sizeof(type)*(size)) 109 | #else 110 | #define VARDECL(var) var 111 | #define ALLOC(var, size, type) var = PUSH(stack, size, type) 112 | #endif 113 | 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /Makefile.common: -------------------------------------------------------------------------------- 1 | # default parameter values 2 | ifeq ($(ARCH),) 3 | UNAME := $(shell uname -s) 4 | ifeq ($(findstring MINGW64, $(UNAME)), MINGW64) 5 | ARCH=x64 6 | else ifeq ($(findstring MINGW32, $(UNAME)), MINGW32) 7 | ARCH=x86 8 | else 9 | UNAME := $(shell uname -m) 10 | ifeq ($(UNAME), x86_64) 11 | ARCH=x64 12 | else ifeq ($(UNAME), aarch64) 13 | ARCH=arm64 14 | else 15 | ARCH=x86 16 | endif 17 | endif 18 | endif 19 | 20 | INCLUDES=-Isrc -I./src/miniz -I./src/rcheevos/include 21 | CFLAGS=-Wall $(INCLUDES) 22 | CXXFLAGS=$(CFLAGS) -std=c++11 23 | LDFLAGS=-static-libgcc -static-libstdc++ 24 | 25 | ifeq ($(ARCH), x86) 26 | CFLAGS += -m32 27 | CXXFLAGS += -m32 28 | LDFLAGS += -m32 29 | OUTDIR=bin 30 | else ifeq ($(ARCH), x64) 31 | CFLAGS += -m64 32 | CXXFLAGS += -m64 33 | LDFLAGS += -m64 34 | OUTDIR=bin64 35 | else ifeq ($(ARCH), arm64) 36 | CFLAGS += -march=armv8-a 37 | CXXFLAGS += -march=armv8-a 38 | LDFLAGS += -march=armv8-a 39 | OUTDIR=bin64 40 | else 41 | $(error unknown ARCH "$(ARCH)") 42 | endif 43 | 44 | ifneq ($(DEBUG),) 45 | CFLAGS += -O0 -g 46 | CXXFLAGS += -O0 -g 47 | else 48 | CFLAGS += -O3 -DNDEBUG 49 | CXXFLAGS += -O3 -DNDEBUG 50 | endif 51 | 52 | ifdef HAVE_CHD 53 | CXXFLAGS += -DHAVE_CHD -I./src/libchdr/include 54 | CFLAGS += -DZ7_ST -DZSTD_DISABLE_ASM -I./src/libchdr/include -I./src/libchdr/deps/lzma-24.05/include -I./src/libchdr/deps/zlib-1.3.1 -I./src/libchdr/deps/zstd-1.5.6/lib 55 | CHD_OBJS = src/libchdr/deps/lzma-24.05/src/Alloc.o \ 56 | src/libchdr/deps/lzma-24.05/src/Bra86.o \ 57 | src/libchdr/deps/lzma-24.05/src/BraIA64.o \ 58 | src/libchdr/deps/lzma-24.05/src/CpuArch.o \ 59 | src/libchdr/deps/lzma-24.05/src/Delta.o \ 60 | src/libchdr/deps/lzma-24.05/src/LzFind.o \ 61 | src/libchdr/deps/lzma-24.05/src/Lzma86Dec.o \ 62 | src/libchdr/deps/lzma-24.05/src/LzmaDec.o \ 63 | src/libchdr/deps/lzma-24.05/src/LzmaEnc.o \ 64 | src/libchdr/deps/lzma-24.05/src/Sort.o \ 65 | src/libchdr/deps/zlib-1.3.1/adler32.o \ 66 | src/libchdr/deps/zlib-1.3.1/compress.o \ 67 | src/libchdr/deps/zlib-1.3.1/crc32.o \ 68 | src/libchdr/deps/zlib-1.3.1/deflate.o \ 69 | src/libchdr/deps/zlib-1.3.1/gzclose.o \ 70 | src/libchdr/deps/zlib-1.3.1/gzlib.o \ 71 | src/libchdr/deps/zlib-1.3.1/gzread.o \ 72 | src/libchdr/deps/zlib-1.3.1/gzwrite.o \ 73 | src/libchdr/deps/zlib-1.3.1/infback.o \ 74 | src/libchdr/deps/zlib-1.3.1/inffast.o \ 75 | src/libchdr/deps/zlib-1.3.1/inflate.o \ 76 | src/libchdr/deps/zlib-1.3.1/inftrees.o \ 77 | src/libchdr/deps/zlib-1.3.1/trees.o \ 78 | src/libchdr/deps/zlib-1.3.1/uncompr.o \ 79 | src/libchdr/deps/zlib-1.3.1/zutil.o \ 80 | src/libchdr/deps/zstd-1.5.6/lib/common/debug.o \ 81 | src/libchdr/deps/zstd-1.5.6/lib/common/entropy_common.o \ 82 | src/libchdr/deps/zstd-1.5.6/lib/common/error_private.o \ 83 | src/libchdr/deps/zstd-1.5.6/lib/common/fse_decompress.o \ 84 | src/libchdr/deps/zstd-1.5.6/lib/common/pool.o \ 85 | src/libchdr/deps/zstd-1.5.6/lib/common/threading.o \ 86 | src/libchdr/deps/zstd-1.5.6/lib/common/xxhash.o \ 87 | src/libchdr/deps/zstd-1.5.6/lib/common/zstd_common.o \ 88 | src/libchdr/deps/zstd-1.5.6/lib/decompress/huf_decompress.o \ 89 | src/libchdr/deps/zstd-1.5.6/lib/decompress/zstd_ddict.o \ 90 | src/libchdr/deps/zstd-1.5.6/lib/decompress/zstd_decompress.o \ 91 | src/libchdr/deps/zstd-1.5.6/lib/decompress/zstd_decompress_block.o \ 92 | src/libchdr/src/libchdr_bitstream.o \ 93 | src/libchdr/src/libchdr_cdrom.o \ 94 | src/libchdr/src/libchdr_chd.o \ 95 | src/libchdr/src/libchdr_flac.o \ 96 | src/libchdr/src/libchdr_huffman.o 97 | endif 98 | -------------------------------------------------------------------------------- /src/Util.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "components/Logger.h" 23 | 24 | #include 25 | #include 26 | 27 | // _WINDOWS says we're building _for_ Windows 28 | #ifdef _WINDOWS 29 | #define WIN32_LEAN_AND_MEAN 30 | #include 31 | #endif 32 | 33 | // _WIN32 says we're building _on_ Windows 34 | #ifdef _WIN32 35 | #define strcasecmp _stricmp 36 | #define strncasecmp _strnicmp 37 | #else 38 | #define sprintf_s sprintf 39 | #endif 40 | 41 | namespace util 42 | { 43 | time_t fileTime(const std::string& path); 44 | bool exists(const std::string& path); 45 | 46 | FILE* openFile(Logger* logger, const std::string& path, const char* mode); 47 | std::string loadFile(Logger* logger, const std::string& path); 48 | void* loadFile(Logger* logger, const std::string& path, size_t* size); 49 | 50 | #ifndef NO_MINIZ 51 | void* loadZippedFile(Logger* logger, const std::string& path, size_t* size, std::string& unzippedFileName); 52 | bool unzipFile(Logger* logger, const std::string& zipPath, const std::string& archiveFileName, const std::string& unzippedPath); 53 | #endif 54 | 55 | bool saveFile(Logger* logger, const std::string& path, const void* data, size_t size); 56 | void deleteFile(const std::string& path); 57 | 58 | #ifndef _CONSOLE 59 | bool downloadFile(Logger* logger, const std::string& url, const std::string& path); 60 | #endif 61 | 62 | std::string jsonEscape(const std::string& str); 63 | std::string jsonUnescape(const std::string& str); 64 | 65 | std::string fullPath(const std::string& path); 66 | std::string fileName(const std::string& path); 67 | std::string fileNameWithExtension(const std::string& path); 68 | std::string extension(const std::string& path); 69 | std::string replaceFileName(const std::string& originalPath, const char* newFileName); 70 | std::string sanitizeFileName(const std::string& fileName); 71 | 72 | std::string directory(const std::string& path); 73 | 74 | #ifdef _WINDOWS 75 | void ensureDirectoryExists(const std::string& path); 76 | #endif 77 | 78 | #ifdef _WINDOWS 79 | std::string openFileDialog(HWND hWnd, const std::string& extensionsFilter); 80 | std::string saveFileDialog(HWND hWnd, const std::string& extensionsFilter, const char* defaultExtension = NULL); 81 | #endif 82 | 83 | const void* toPng(Logger* logger, const void* data, unsigned width, unsigned height, unsigned pitch, enum retro_pixel_format format, int* len); 84 | const void* toRgb(Logger* logger, const void* data, unsigned width, unsigned height, unsigned pitch, enum retro_pixel_format format); 85 | void saveImage(Logger* logger, const std::string& path, const void* data, unsigned width, unsigned height, unsigned pitch, enum retro_pixel_format format); 86 | void* fromRgb(Logger* logger, const void* data, unsigned width, unsigned height, unsigned* pitch, enum retro_pixel_format format); 87 | void* fromPng(Logger* logger, const void* data, int len, unsigned* width, unsigned* height, unsigned* pitch); 88 | void* loadImage(Logger* logger, const std::string& path, unsigned* width, unsigned* height, unsigned* pitch); 89 | 90 | #ifdef _WINDOWS 91 | std::string ucharToUtf8(const std::wstring& unicodeString); 92 | std::wstring utf8ToUChar(const std::string& utf8String); 93 | #endif 94 | } 95 | -------------------------------------------------------------------------------- /src/Gl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "libretro/Components.h" 4 | 5 | #include 6 | 7 | namespace Gl 8 | { 9 | void init(libretro::LoggerComponent* logger); 10 | bool ok(); 11 | 12 | GLenum getError(); 13 | const char* getErrorMsg(GLenum error); 14 | void getIntegerv(GLenum pname, GLint *params); 15 | 16 | void genTextures(GLsizei n, GLuint* textures); 17 | void deleteTextures(GLsizei n, const GLuint* textures); 18 | void bindTexture(GLenum target, GLuint texture); 19 | void activeTexture(GLenum texture); 20 | void texParameteri(GLenum target, GLenum pname, GLint param); 21 | void texImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data); 22 | void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); 23 | void getTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels); 24 | void pixelStorei(GLenum pname, GLint param); 25 | 26 | void genBuffers(GLsizei n, GLuint* buffers); 27 | void deleteBuffers(GLsizei n, const GLuint* buffers); 28 | void bindBuffer(GLenum target, GLuint buffer); 29 | void bufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); 30 | void genVertexArray(GLsizei n, GLuint *arrays); 31 | void deleteVertexArrays(GLsizei n, const GLuint *arrays); 32 | void bindVertexArray(GLuint array); 33 | void vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); 34 | void enableVertexAttribArray(GLuint index); 35 | void disableVertexAttribArray(GLuint index); 36 | 37 | GLuint createShader(GLenum shaderType); 38 | void deleteShader(GLuint shader); 39 | void shaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length); 40 | void compileShader(GLuint shader); 41 | void getShaderiv(GLuint shader, GLenum pname, GLint* params); 42 | void getShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog); 43 | 44 | GLuint createProgram(); 45 | void deleteProgram(GLuint program); 46 | void attachShader(GLuint program, GLuint shader); 47 | void linkProgram(GLuint program); 48 | void validateProgram(GLuint program); 49 | void getProgramiv(GLuint program, GLenum pname, GLint* params); 50 | void getProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei* length, GLchar* infoLog); 51 | void useProgram(GLuint program); 52 | GLint getAttribLocation(GLuint program, const GLchar* name); 53 | GLint getUniformLocation(GLuint program, const GLchar* name); 54 | void uniform1i(GLint location, GLint v0); 55 | void uniform2f(GLint location, GLfloat v0, GLfloat v1); 56 | 57 | void genFramebuffers(GLsizei n, GLuint* ids); 58 | void deleteFramebuffers(GLsizei n, GLuint* ids); 59 | void bindFramebuffer(GLenum target, GLuint framebuffer); 60 | void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); 61 | void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); 62 | void drawBuffers(GLsizei n, const GLenum* bufs); 63 | GLenum checkFramebufferStatus(GLenum target); 64 | 65 | void genRenderbuffers(GLsizei n, GLuint* renderbuffers); 66 | void deleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); 67 | void bindRenderbuffer(GLenum target, GLuint renderbuffer); 68 | void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); 69 | 70 | void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); 71 | void clear(GLbitfield mask); 72 | void enable(GLenum cap); 73 | void disable(GLenum cap); 74 | void blendFunc(GLenum sfactor, GLenum dfactor); 75 | void blendEquation(GLenum mode); 76 | void viewport(GLint x, GLint y, GLsizei width, GLsizei height); 77 | void drawArrays(GLenum mode, GLint first, GLsizei count); 78 | 79 | void bindSampler(GLuint unit, GLuint sampler); 80 | 81 | int getVersion(); 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/KeyBinds.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "components/Logger.h" 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | 29 | class Input; // forward reference 30 | 31 | class KeyBinds 32 | { 33 | public: 34 | enum class Action 35 | { 36 | kNothing, 37 | 38 | // Joypad buttons (extra = port << 8 | pressed) 39 | kButtonUp, 40 | kButtonDown, 41 | kButtonLeft, 42 | kButtonRight, 43 | kButtonX, 44 | kButtonY, 45 | kButtonA, 46 | kButtonB, 47 | kButtonL, 48 | kButtonR, 49 | kAxisL2, 50 | kAxisR2, 51 | kButtonL3, 52 | kButtonR3, 53 | kButtonSelect, 54 | kButtonStart, 55 | 56 | // Joypad analog sticks 57 | kAxisLeftX, 58 | kAxisLeftY, 59 | kAxisRightX, 60 | kAxisRightY, 61 | 62 | // State state management (extra = slot) 63 | kSaveState, 64 | kLoadState, 65 | kChangeCurrentState, 66 | 67 | // Disc management 68 | kToggleTray, 69 | kReadyNextDisc, 70 | kReadyPreviousDisc, 71 | 72 | // Window size 73 | kSetWindowSize1, 74 | kSetWindowSize2, 75 | kSetWindowSize3, 76 | kSetWindowSize4, 77 | kSetWindowSize5, 78 | kToggleFullscreen, 79 | kRotateRight, 80 | kRotateLeft, 81 | 82 | // Emulation speed 83 | kPauseToggle, 84 | kPauseToggleNoOvl, 85 | kFastForward, // (extra = pressed[0/1],toggle[2]) 86 | kStep, 87 | 88 | // Screenshot 89 | kScreenshot, 90 | 91 | // Reset 92 | kReset, 93 | 94 | // Keyboard 95 | kGameFocusToggle, 96 | kKeyboardInput // (extra = key << 8 | pressed) 97 | }; 98 | 99 | bool init(Logger* logger); 100 | void destroy() {} 101 | 102 | Action translate(const SDL_KeyboardEvent* event, unsigned* extra); 103 | Action translate(const SDL_ControllerButtonEvent* event, unsigned* extra); 104 | void translate(const SDL_ControllerAxisEvent* caxis, Input& input, 105 | Action* action1, unsigned* extra1, Action* action2, unsigned* extra2); 106 | 107 | void mapDevice(SDL_JoystickID originalID, SDL_JoystickID newID); 108 | unsigned getNavigationPort(SDL_JoystickID joystickID); 109 | 110 | void showControllerDialog(Input& input, int portId); 111 | void showHotKeyDialog(Input& input); 112 | 113 | struct Binding 114 | { 115 | enum Type 116 | { 117 | None = 0, 118 | Button, 119 | Axis, 120 | Key, 121 | }; 122 | 123 | SDL_JoystickID joystick_id; 124 | uint32_t button; 125 | Type type; 126 | uint16_t modifiers; 127 | }; 128 | 129 | typedef std::array BindingList; 130 | 131 | static void getBindingString(char buffer[32], const KeyBinds::Binding& desc); 132 | 133 | std::string serializeBindings() const; 134 | bool deserializeBindings(const char* json); 135 | 136 | bool hasGameFocus() const noexcept { return _gameFocus; } 137 | 138 | protected: 139 | Logger* _logger; 140 | 141 | KeyBinds::Action translateButtonPress(int button, unsigned* extra); 142 | KeyBinds::Action translateButtonReleased(int button, unsigned* extra); 143 | KeyBinds::Action translateAnalog(int button, Sint16 value, unsigned* extra); 144 | KeyBinds::Action translateKeyboardInput(SDL_Keycode kcode, bool pressed, unsigned* extra) const; 145 | 146 | BindingList _bindings; 147 | SDL_JoystickID getBindingID(SDL_JoystickID id) const; 148 | 149 | std::map _bindingMap; 150 | 151 | unsigned _slot; 152 | bool _gameFocus; 153 | 154 | unsigned _axesHeld; 155 | }; 156 | 157 | -------------------------------------------------------------------------------- /src/resource.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #ifndef IDC_STATIC 21 | #define IDC_STATIC (-1) 22 | #endif 23 | 24 | // Keep those in increasing order 25 | #define IDM_SYSTEM_FIRST 45000 26 | #define IDM_SYSTEM_LAST 49999 27 | 28 | // Keep those in increasing order 29 | #define IDM_SAVE_STATE_1 51000 30 | #define IDM_SAVE_STATE_2 51001 31 | #define IDM_SAVE_STATE_3 51002 32 | #define IDM_SAVE_STATE_4 51003 33 | #define IDM_SAVE_STATE_5 51004 34 | #define IDM_SAVE_STATE_6 51005 35 | #define IDM_SAVE_STATE_7 51006 36 | #define IDM_SAVE_STATE_8 51007 37 | #define IDM_SAVE_STATE_9 51008 38 | #define IDM_SAVE_STATE_10 51009 39 | 40 | // Keep those in increasing order 41 | #define IDM_LOAD_STATE_1 52000 42 | #define IDM_LOAD_STATE_2 52001 43 | #define IDM_LOAD_STATE_3 52002 44 | #define IDM_LOAD_STATE_4 52003 45 | #define IDM_LOAD_STATE_5 52004 46 | #define IDM_LOAD_STATE_6 52005 47 | #define IDM_LOAD_STATE_7 52006 48 | #define IDM_LOAD_STATE_8 52007 49 | #define IDM_LOAD_STATE_9 52008 50 | #define IDM_LOAD_STATE_10 52009 51 | 52 | // Keep those in increasing order 53 | #define IDM_LOAD_RECENT_1 53000 54 | #define IDM_LOAD_RECENT_2 53001 55 | #define IDM_LOAD_RECENT_3 53002 56 | #define IDM_LOAD_RECENT_4 53003 57 | #define IDM_LOAD_RECENT_5 53004 58 | #define IDM_LOAD_RECENT_6 53005 59 | #define IDM_LOAD_RECENT_7 53006 60 | #define IDM_LOAD_RECENT_8 53007 61 | #define IDM_LOAD_RECENT_9 53008 62 | #define IDM_LOAD_RECENT_10 53009 63 | 64 | // Keep those in increasing order 65 | #define IDM_WINDOW_1X 54000 66 | #define IDM_WINDOW_2X 54001 67 | #define IDM_WINDOW_3X 54002 68 | #define IDM_WINDOW_4X 54003 69 | #define IDM_WINDOW_5X 54004 70 | 71 | #define IDM_CD_DISC_FIRST 55000 72 | #define IDM_CD_DISC_LAST 55019 73 | 74 | #define IDM_LOAD_GAME 40000 75 | #define IDM_RESET_GAME 40001 76 | #define IDM_EXIT 40002 77 | #define IDM_CORE_CONFIG 40003 78 | #define IDM_INPUT_CONFIG 40004 79 | #define IDM_VIDEO_CONFIG 40005 80 | #define IDM_ABOUT 40006 81 | #define IDM_PAUSE_GAME 40007 82 | #define IDM_RESUME_GAME 40008 83 | #define IDM_TURBO_GAME 40009 84 | #define IDM_LOAD_STATE 40010 85 | #define IDM_SAVE_STATE 40011 86 | #define IDM_CD_ROM 40012 87 | #define IDM_CD_OPEN_TRAY 40013 88 | #define IDM_INPUT_CONTROLLER_1 40014 89 | #define IDM_INPUT_CONTROLLER_2 40015 90 | #define IDM_MANAGE_CORES 40016 91 | #define IDM_SAVING_CONFIG 40017 92 | #define IDM_EMULATOR_CONFIG 40018 93 | #define IDM_INPUT_BACKGROUND_INPUT 40019 94 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # supported parameters 2 | # ARCH architecture - "x86" or "x64" [detected if not set] 3 | # DEBUG if set to anything, builds with DEBUG symbols 4 | 5 | include Makefile.common 6 | 7 | ifeq ($(ARCH), arm64) 8 | $(error Cannot build for arm64) 9 | endif 10 | 11 | # Toolset setup 12 | ifeq ($(OS),Windows_NT) 13 | CC=gcc 14 | CXX=g++ 15 | RC=windres 16 | 17 | ifeq ($(ARCH), x86) 18 | MINGWLIBDIR=/mingw32/bin 19 | else 20 | MINGWLIBDIR=/mingw64/bin 21 | endif 22 | 23 | else ifeq ($(shell uname -s),Linux) 24 | MINGW=x86_64-w64-mingw32 25 | ifeq ($(ARCH), x86) 26 | MINGW=i686-w64-mingw32 27 | endif 28 | 29 | CC=$(MINGW)-gcc 30 | CXX=$(MINGW)-g++ 31 | RC=$(MINGW)-windres 32 | 33 | MINGWLIBDIR=/usr/$(MINGW)/lib 34 | endif 35 | 36 | # compile flags 37 | INCLUDES += -I./src/RAInterface -I./src/SDL2/include 38 | DEFINES=-DOUTSIDE_SPEEX -DRANDOM_PREFIX=speex -DEXPORT= -D_USE_SSE2 -DFIXED_POINT -D_WINDOWS 39 | CFLAGS += $(DEFINES) 40 | CXXFLAGS += $(DEFINES) 41 | 42 | ifeq ($(ARCH), x86) 43 | SDLLIBDIR=src/SDL2/lib/x86 44 | else 45 | SDLLIBDIR=src/SDL2/lib/x64 46 | endif 47 | 48 | ifneq ($(DEBUG),) 49 | CFLAGS += -DDEBUG_FSM -DLOG_TO_FILE 50 | CXXFLAGS += -DDEBUG_FSM -DLOG_TO_FILE 51 | else 52 | CFLAGS += -DLOG_TO_FILE 53 | CXXFLAGS += -DLOG_TO_FILE 54 | endif 55 | 56 | LDFLAGS += -mwindows -lmingw32 -lopengl32 -lwinhttp -lgdi32 -limm32 -lcomdlg32 57 | LDFLAGS += -L${SDLLIBDIR} -lSDL2main -lSDL2 58 | 59 | # main 60 | OBJS=\ 61 | src/dynlib/dynlib.o \ 62 | src/jsonsax/jsonsax.o \ 63 | src/libretro/BareCore.o \ 64 | src/libretro/Core.o \ 65 | src/RA_Implementation.o \ 66 | src/RAInterface/RA_Interface.o \ 67 | src/components/Audio.o \ 68 | src/components/Config.o \ 69 | src/components/Dialog.o \ 70 | src/components/Input.o \ 71 | src/components/Logger.o \ 72 | src/components/Microphone.o \ 73 | src/components/Video.o \ 74 | src/components/VideoContext.o \ 75 | src/libmincrypt/sha256.o \ 76 | src/miniz/miniz.o \ 77 | src/miniz/miniz_tdef.o \ 78 | src/miniz/miniz_tinfl.o \ 79 | src/miniz/miniz_zip.o \ 80 | src/rcheevos/src/rcheevos/consoleinfo.o \ 81 | src/rcheevos/src/rc_libretro.o \ 82 | src/rcheevos/src/rhash/aes.o \ 83 | src/rcheevos/src/rhash/cdreader.o \ 84 | src/rcheevos/src/rhash/md5.o \ 85 | src/rcheevos/src/rhash/hash.o \ 86 | src/rcheevos/src/rhash/hash_disc.o \ 87 | src/rcheevos/src/rhash/hash_encrypted.o \ 88 | src/rcheevos/src/rhash/hash_rom.o \ 89 | src/rcheevos/src/rhash/hash_zip.o \ 90 | src/speex/resample.o \ 91 | src/About.o \ 92 | src/Application.o \ 93 | src/CdRom.o \ 94 | src/Emulator.o \ 95 | src/Fsm.o \ 96 | src/Gl.o \ 97 | src/GlUtil.o \ 98 | src/Hash.o \ 99 | src/Hash3DS.o \ 100 | src/KeyBinds.o \ 101 | src/main.o \ 102 | src/Memory.o \ 103 | src/menu.res \ 104 | src/States.o \ 105 | src/Util.o 106 | 107 | ifdef HAVE_CHD 108 | OBJS += $(CHD_OBJS) \ 109 | src/HashCHD.o 110 | endif 111 | 112 | all: $(OUTDIR)/RALibretro.exe $(OUTDIR)/SDL2.dll $(OUTDIR)/libwinpthread-1.dll 113 | 114 | src/rcheevos/src/rc_libretro.o: CFLAGS += -I./src/libretro 115 | 116 | src/components/Config.o: CFLAGS += -I./src/libretro 117 | 118 | src/Memory.o: CFLAGS += -I./src/libretro 119 | 120 | src/Hash.o: CFLAGS += -I./src/libretro 121 | 122 | src/RAInterface/RA_Interface.o: CXXFLAGS += -DRA_NOPROGRESS 123 | 124 | %.o: %.cpp 125 | $(CXX) $(CXXFLAGS) -c $< -o $@ 126 | 127 | %.o: %.c 128 | $(CC) $(CFLAGS) -c $< -o $@ 129 | 130 | src/RA_BuildVer.h: .git/HEAD 131 | src/RAInterface/MakeBuildVer.sh src/RA_BuildVer.h "" RA_LIBRETRO 132 | 133 | src/RA_Implementation.o: src/RA_Implementation.cpp src/RA_BuildVer.h 134 | $(CXX) $(CXXFLAGS) -c $< -o $@ 135 | 136 | %.res: %.rc 137 | $(RC) $< -O coff -o $@ 138 | 139 | $(OUTDIR)/SDL2.dll: $(SDLLIBDIR)/SDL2.dll 140 | cp -f $< $@ 141 | 142 | $(OUTDIR)/libwinpthread-1.dll: $(MINGWLIBDIR)/libwinpthread-1.dll 143 | cp -f $< $@ 144 | 145 | $(OUTDIR)/RALibretro.exe: $(OBJS) 146 | mkdir -p $(OUTDIR) 147 | $(CXX) -o $@ $+ $(LDFLAGS) 148 | 149 | zip: 150 | rm -f $(OUTDIR)/RALibretro-*.zip RALibretro-*.zip 151 | zip -9 RALibretro-`git describe | tr -d "\n"`.zip $(OUTDIR)/RALibretro.exe 152 | 153 | clean: 154 | rm -f $(OUTDIR)/RALibretro.exe $(OBJS) $(OUTDIR)/RALibretro-*.zip RALibretro-*.zip 155 | 156 | pack: 157 | ifeq ("", "$(wildcard $(OUTDIR)/RALibretro.exe)") 158 | echo '"$(OUTDIR)/RALibretro.exe" not found!' 159 | else 160 | rm -f $(OUTDIR)/RALibretro-*.zip RALibretro-*.zip 161 | zip -9r RALibretro-pack-`git describe | tr -d "\n"`.zip bin 162 | endif 163 | 164 | .PHONY: clean FORCE 165 | -------------------------------------------------------------------------------- /src/GlUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "GlUtil.h" 2 | 3 | #include "Gl.h" 4 | 5 | #define TAG "[GLU] " 6 | 7 | static libretro::LoggerComponent* s_logger; 8 | 9 | void GlUtil::init(libretro::LoggerComponent* logger) 10 | { 11 | s_logger = logger; 12 | } 13 | 14 | GLuint GlUtil::createTexture(GLsizei width, GLsizei height, GLint internalFormat, GLenum format, GLenum type, GLenum filter) 15 | { 16 | if (!Gl::ok()) return 0; 17 | 18 | GLuint texture; 19 | Gl::genTextures(1, &texture); 20 | Gl::bindTexture(GL_TEXTURE_2D, texture); 21 | 22 | Gl::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); 23 | Gl::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); 24 | Gl::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 25 | Gl::texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 26 | 27 | Gl::texImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, NULL); 28 | 29 | if (!Gl::ok()) 30 | { 31 | Gl::deleteTextures(1, &texture); 32 | return 0; 33 | } 34 | 35 | return texture; 36 | } 37 | 38 | GLuint GlUtil::createShader(GLenum shaderType, const char* source) 39 | { 40 | if (!Gl::ok()) return 0; 41 | 42 | GLuint shader = Gl::createShader(shaderType); 43 | Gl::shaderSource(shader, 1, &source, NULL); 44 | Gl::compileShader(shader); 45 | 46 | GLint status; 47 | Gl::getShaderiv(shader, GL_COMPILE_STATUS, &status); 48 | 49 | if (status == GL_FALSE) 50 | { 51 | char buffer[4096]; 52 | Gl::getShaderInfoLog(shader, sizeof(buffer), NULL, buffer); 53 | s_logger->error(TAG "Error in shader: %s", buffer); 54 | Gl::deleteShader(shader); 55 | return 0; 56 | } 57 | 58 | if (!Gl::ok()) 59 | { 60 | Gl::deleteShader(shader); 61 | return 0; 62 | } 63 | 64 | return shader; 65 | } 66 | 67 | GLuint GlUtil::createProgram(const char* vertexShader, const char* fragmentShader) 68 | { 69 | if (!Gl::ok()) return 0; 70 | 71 | GLuint vs = createShader(GL_VERTEX_SHADER, vertexShader); 72 | GLuint fs = createShader(GL_FRAGMENT_SHADER, fragmentShader); 73 | GLuint program = Gl::createProgram(); 74 | 75 | Gl::attachShader(program, vs); 76 | Gl::attachShader(program, fs); 77 | Gl::linkProgram(program); 78 | 79 | Gl::deleteShader(vs); 80 | Gl::deleteShader(fs); 81 | 82 | Gl::validateProgram(program); 83 | 84 | GLint status; 85 | Gl::getProgramiv(program, GL_LINK_STATUS, &status); 86 | 87 | if (status == GL_FALSE) 88 | { 89 | char buffer[4096]; 90 | Gl::getProgramInfoLog(program, sizeof(buffer), NULL, buffer); 91 | s_logger->error(TAG "Error in shader program: %s", buffer); 92 | Gl::deleteProgram(program); 93 | return 0; 94 | } 95 | 96 | if (!Gl::ok()) 97 | { 98 | Gl::deleteProgram(program); 99 | return 0; 100 | } 101 | 102 | return program; 103 | } 104 | 105 | GLuint GlUtil::createFramebuffer(GLuint* renderbuffer, GLsizei width, GLsizei height, GLuint texture, bool depth, bool stencil) 106 | { 107 | if (!Gl::ok()) return 0; 108 | 109 | GLuint framebuffer; 110 | Gl::genFramebuffers(1, &framebuffer); 111 | Gl::bindFramebuffer(GL_FRAMEBUFFER, framebuffer); 112 | 113 | Gl::framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 114 | 115 | *renderbuffer = 0; 116 | 117 | if (depth && stencil) 118 | { 119 | Gl::genRenderbuffers(1, renderbuffer); 120 | Gl::bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer); 121 | Gl::renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); 122 | Gl::framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *renderbuffer); 123 | Gl::bindRenderbuffer(GL_RENDERBUFFER, 0); 124 | } 125 | else if (depth) 126 | { 127 | Gl::genRenderbuffers(1, renderbuffer); 128 | Gl::bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer); 129 | Gl::renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); 130 | Gl::framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *renderbuffer); 131 | Gl::bindRenderbuffer(GL_RENDERBUFFER, 0); 132 | } 133 | 134 | if (Gl::checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 135 | { 136 | if (renderbuffer != 0) 137 | { 138 | Gl::deleteRenderbuffers(1, renderbuffer); 139 | } 140 | 141 | Gl::deleteFramebuffers(1, &framebuffer); 142 | *renderbuffer = 0; 143 | return 0; 144 | } 145 | 146 | Gl::clearColor(0, 0, 0, 1); 147 | Gl::clear(GL_COLOR_BUFFER_BIT); 148 | 149 | Gl::bindFramebuffer(GL_FRAMEBUFFER, 0); 150 | return framebuffer; 151 | } 152 | -------------------------------------------------------------------------------- /src/libretro/BareCore.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2016 Andre Leiradella 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #pragma once 26 | 27 | #include "libretro.h" 28 | #include "Components.h" 29 | #include "dynlib/dynlib.h" 30 | 31 | namespace libretro 32 | { 33 | /** 34 | * Core represents a libretro core loaded from the file system, i.e. 35 | * stella_libretro.so. Its methods map 1:1 to the ones from the libretro 36 | * API, not couting load, that loads a core, and destroy, which unloads the 37 | * core and destroys the object. 38 | * 39 | * It's the caller's responsibility to ensure that the core is always in a 40 | * consistent state. 41 | */ 42 | class BareCore 43 | { 44 | public: 45 | // Loads a core specified by its file path. 46 | bool load(libretro::LoggerComponent* logger, const char* path); 47 | 48 | // Unloads the core from memory. 49 | void destroy(); 50 | 51 | // All the remaining methods map 1:1 to the libretro API. 52 | void init() const; 53 | void deinit() const; 54 | unsigned apiVersion() const; 55 | void getSystemInfo(struct retro_system_info* info) const; 56 | void getSystemAVInfo(struct retro_system_av_info* info) const; 57 | void setEnvironment(retro_environment_t cb) const; 58 | void setVideoRefresh(retro_video_refresh_t cb) const; 59 | void setAudioSample(retro_audio_sample_t cb) const; 60 | void setAudioSampleBatch(retro_audio_sample_batch_t cb) const; 61 | void setInputPoll(retro_input_poll_t cb) const; 62 | void setInputState(retro_input_state_t cb) const; 63 | void setControllerPortDevice(unsigned port, unsigned device) const; 64 | void reset() const; 65 | void run() const; 66 | size_t serializeSize() const; 67 | bool serialize(void* data, size_t size) const; 68 | bool unserialize(const void* data, size_t size) const; 69 | void cheatReset() const; 70 | void cheatSet(unsigned index, bool enabled, const char* code) const; 71 | bool loadGame(const struct retro_game_info* game) const; 72 | bool loadGameSpecial(unsigned game_type, const struct retro_game_info* info, size_t num_info) const; 73 | void unloadGame() const; 74 | unsigned getRegion() const; 75 | void* getMemoryData(unsigned id) const; 76 | size_t getMemorySize(unsigned id) const; 77 | 78 | protected: 79 | libretro::LoggerComponent* _logger; 80 | dynlib_t _handle; 81 | 82 | void (*_init)(); 83 | void (*_deinit)(); 84 | unsigned (*_apiVersion)(); 85 | void (*_getSystemInfo)(struct retro_system_info*); 86 | void (*_getSystemAVInfo)(struct retro_system_av_info*); 87 | void (*_setEnvironment)(retro_environment_t); 88 | void (*_setVideoRefresh)(retro_video_refresh_t); 89 | void (*_setAudioSample)(retro_audio_sample_t); 90 | void (*_setAudioSampleBatch)(retro_audio_sample_batch_t); 91 | void (*_setInputPoll)(retro_input_poll_t); 92 | void (*_setInputState)(retro_input_state_t); 93 | void (*_setControllerPortDevice)(unsigned, unsigned); 94 | void (*_reset)(); 95 | void (*_run)(); 96 | size_t (*_serializeSize)(); 97 | bool (*_serialize)(void*, size_t); 98 | bool (*_unserialize)(const void*, size_t); 99 | void (*_cheatReset)(); 100 | void (*_cheatSet)(unsigned, bool, const char*); 101 | bool (*_loadGame)(const struct retro_game_info*); 102 | bool (*_loadGameSpecial)(unsigned, const struct retro_game_info*, size_t); 103 | void (*_unloadGame)(); 104 | unsigned (*_getRegion)(); 105 | void* (*_getMemoryData)(unsigned); 106 | size_t (*_getMemorySize)(unsigned); 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /src/menu.rc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | // Generated by ResEdit 1.6.6 21 | // Copyright (C) 2006-2015 22 | // http://www.resedit.net 23 | 24 | #include 25 | #include 26 | #include 27 | #include "resource.h" 28 | 29 | 30 | 31 | 32 | // 33 | // Menu resources 34 | // 35 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 36 | main MENU 37 | { 38 | POPUP "File" 39 | { 40 | POPUP "Select Core" 41 | { 42 | MENUITEM "No Systems Found", IDM_MANAGE_CORES 43 | } 44 | MENUITEM SEPARATOR 45 | MENUITEM "Load Game...", IDM_LOAD_GAME 46 | POPUP "Load Recent" 47 | { 48 | MENUITEM "Empty", IDM_LOAD_RECENT_1 49 | MENUITEM "Empty", IDM_LOAD_RECENT_2 50 | MENUITEM "Empty", IDM_LOAD_RECENT_3 51 | MENUITEM "Empty", IDM_LOAD_RECENT_4 52 | MENUITEM "Empty", IDM_LOAD_RECENT_5 53 | MENUITEM "Empty", IDM_LOAD_RECENT_6 54 | MENUITEM "Empty", IDM_LOAD_RECENT_7 55 | MENUITEM "Empty", IDM_LOAD_RECENT_8 56 | MENUITEM "Empty", IDM_LOAD_RECENT_9 57 | MENUITEM "Empty", IDM_LOAD_RECENT_10 58 | } 59 | MENUITEM SEPARATOR 60 | MENUITEM "Pause Game", IDM_PAUSE_GAME 61 | MENUITEM "Resume Game", IDM_RESUME_GAME 62 | MENUITEM "Turbo", IDM_TURBO_GAME 63 | MENUITEM "Reset Game", IDM_RESET_GAME 64 | MENUITEM SEPARATOR 65 | POPUP "CD-ROM" 66 | { 67 | MENUITEM "Open Tray", IDM_CD_OPEN_TRAY 68 | } 69 | MENUITEM SEPARATOR 70 | POPUP "Save Game State" 71 | { 72 | MENUITEM "Slot #1", IDM_SAVE_STATE_1 73 | MENUITEM "Slot #2", IDM_SAVE_STATE_2 74 | MENUITEM "Slot #3", IDM_SAVE_STATE_3 75 | MENUITEM "Slot #4", IDM_SAVE_STATE_4 76 | MENUITEM "Slot #5", IDM_SAVE_STATE_5 77 | MENUITEM "Slot #6", IDM_SAVE_STATE_6 78 | MENUITEM "Slot #7", IDM_SAVE_STATE_7 79 | MENUITEM "Slot #8", IDM_SAVE_STATE_8 80 | MENUITEM "Slot #9", IDM_SAVE_STATE_9 81 | MENUITEM "Slot #10", IDM_SAVE_STATE_10 82 | } 83 | MENUITEM "Save Game State...", IDM_SAVE_STATE 84 | POPUP "Load Game State" 85 | { 86 | MENUITEM "Slot #1", IDM_LOAD_STATE_1 87 | MENUITEM "Slot #2", IDM_LOAD_STATE_2 88 | MENUITEM "Slot #3", IDM_LOAD_STATE_3 89 | MENUITEM "Slot #4", IDM_LOAD_STATE_4 90 | MENUITEM "Slot #5", IDM_LOAD_STATE_5 91 | MENUITEM "Slot #6", IDM_LOAD_STATE_6 92 | MENUITEM "Slot #7", IDM_LOAD_STATE_7 93 | MENUITEM "Slot #8", IDM_LOAD_STATE_8 94 | MENUITEM "Slot #9", IDM_LOAD_STATE_9 95 | MENUITEM "Slot #10", IDM_LOAD_STATE_10 96 | } 97 | MENUITEM "Load Game State...", IDM_LOAD_STATE 98 | MENUITEM SEPARATOR 99 | MENUITEM "Exit", IDM_EXIT 100 | } 101 | POPUP "Settings" 102 | { 103 | MENUITEM "Core Settings...", IDM_CORE_CONFIG 104 | POPUP "Input" 105 | { 106 | MENUITEM "Hot Keys...", IDM_INPUT_CONFIG 107 | MENUITEM "Controller 1...", IDM_INPUT_CONTROLLER_1 108 | MENUITEM "Controller 2...", IDM_INPUT_CONTROLLER_2 109 | MENUITEM "Background Input", IDM_INPUT_BACKGROUND_INPUT 110 | } 111 | MENUITEM "Emulator...", IDM_EMULATOR_CONFIG 112 | MENUITEM "Saving...", IDM_SAVING_CONFIG 113 | MENUITEM "Video...", IDM_VIDEO_CONFIG 114 | POPUP "Window Size" 115 | { 116 | MENUITEM "Resize to 1x", IDM_WINDOW_1X 117 | MENUITEM "Resize to 2x", IDM_WINDOW_2X 118 | MENUITEM "Resize to 3x", IDM_WINDOW_3X 119 | MENUITEM "Resize to 4x", IDM_WINDOW_4X 120 | MENUITEM "Resize to 5x", IDM_WINDOW_5X 121 | } 122 | MENUITEM SEPARATOR 123 | MENUITEM "Manage Cores...", IDM_MANAGE_CORES 124 | } 125 | MENUITEM "About", IDM_ABOUT 126 | } 127 | 128 | 129 | 130 | // 131 | // Icon resources 132 | // 133 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 134 | 1 ICON "retroarch.ico" 135 | -------------------------------------------------------------------------------- /src/speex/fixed_arm4.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2004 Jean-Marc Valin */ 2 | /** 3 | @file fixed_arm4.h 4 | @brief ARM4 fixed-point operations 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef FIXED_ARM4_H 36 | #define FIXED_ARM4_H 37 | 38 | #undef MULT16_32_Q14 39 | static inline spx_word32_t MULT16_32_Q14(spx_word16_t x, spx_word32_t y) { 40 | int res; 41 | int dummy; 42 | asm ( 43 | "smull %0,%1,%2,%3 \n\t" 44 | "mov %0, %0, lsr #14 \n\t" 45 | "add %0, %0, %1, lsl #18 \n\t" 46 | : "=&r"(res), "=&r" (dummy) 47 | : "r"(y),"r"((int)x)); 48 | return(res); 49 | } 50 | 51 | #undef MULT16_32_Q15 52 | static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) { 53 | int res; 54 | int dummy; 55 | asm ( 56 | "smull %0,%1,%2,%3 \n\t" 57 | "mov %0, %0, lsr #15 \n\t" 58 | "add %0, %0, %1, lsl #17 \n\t" 59 | : "=&r"(res), "=&r" (dummy) 60 | : "r"(y),"r"((int)x)); 61 | return(res); 62 | } 63 | 64 | #undef DIV32_16 65 | static inline short DIV32_16(int a, int b) 66 | { 67 | int res=0; 68 | int dead1, dead2, dead3, dead4, dead5; 69 | __asm__ __volatile__ ( 70 | "\teor %5, %0, %1\n" 71 | "\tmovs %4, %0\n" 72 | "\trsbmi %0, %0, #0 \n" 73 | "\tmovs %4, %1\n" 74 | "\trsbmi %1, %1, #0 \n" 75 | "\tmov %4, #1\n" 76 | 77 | "\tsubs %3, %0, %1, asl #14 \n" 78 | "\tmovpl %0, %3 \n" 79 | "\torrpl %2, %2, %4, asl #14 \n" 80 | 81 | "\tsubs %3, %0, %1, asl #13 \n" 82 | "\tmovpl %0, %3 \n" 83 | "\torrpl %2, %2, %4, asl #13 \n" 84 | 85 | "\tsubs %3, %0, %1, asl #12 \n" 86 | "\tmovpl %0, %3 \n" 87 | "\torrpl %2, %2, %4, asl #12 \n" 88 | 89 | "\tsubs %3, %0, %1, asl #11 \n" 90 | "\tmovpl %0, %3 \n" 91 | "\torrpl %2, %2, %4, asl #11 \n" 92 | 93 | "\tsubs %3, %0, %1, asl #10 \n" 94 | "\tmovpl %0, %3 \n" 95 | "\torrpl %2, %2, %4, asl #10 \n" 96 | 97 | "\tsubs %3, %0, %1, asl #9 \n" 98 | "\tmovpl %0, %3 \n" 99 | "\torrpl %2, %2, %4, asl #9 \n" 100 | 101 | "\tsubs %3, %0, %1, asl #8 \n" 102 | "\tmovpl %0, %3 \n" 103 | "\torrpl %2, %2, %4, asl #8 \n" 104 | 105 | "\tsubs %3, %0, %1, asl #7 \n" 106 | "\tmovpl %0, %3 \n" 107 | "\torrpl %2, %2, %4, asl #7 \n" 108 | 109 | "\tsubs %3, %0, %1, asl #6 \n" 110 | "\tmovpl %0, %3 \n" 111 | "\torrpl %2, %2, %4, asl #6 \n" 112 | 113 | "\tsubs %3, %0, %1, asl #5 \n" 114 | "\tmovpl %0, %3 \n" 115 | "\torrpl %2, %2, %4, asl #5 \n" 116 | 117 | "\tsubs %3, %0, %1, asl #4 \n" 118 | "\tmovpl %0, %3 \n" 119 | "\torrpl %2, %2, %4, asl #4 \n" 120 | 121 | "\tsubs %3, %0, %1, asl #3 \n" 122 | "\tmovpl %0, %3 \n" 123 | "\torrpl %2, %2, %4, asl #3 \n" 124 | 125 | "\tsubs %3, %0, %1, asl #2 \n" 126 | "\tmovpl %0, %3 \n" 127 | "\torrpl %2, %2, %4, asl #2 \n" 128 | 129 | "\tsubs %3, %0, %1, asl #1 \n" 130 | "\tmovpl %0, %3 \n" 131 | "\torrpl %2, %2, %4, asl #1 \n" 132 | 133 | "\tsubs %3, %0, %1 \n" 134 | "\tmovpl %0, %3 \n" 135 | "\torrpl %2, %2, %4 \n" 136 | 137 | "\tmovs %5, %5, lsr #31 \n" 138 | "\trsbne %2, %2, #0 \n" 139 | : "=r" (dead1), "=r" (dead2), "=r" (res), 140 | "=r" (dead3), "=r" (dead4), "=r" (dead5) 141 | : "0" (a), "1" (b), "2" (res) 142 | : "cc" 143 | ); 144 | return res; 145 | } 146 | 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /src/speex/resample_sse.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2008 Jean-Marc Valin 2 | * Copyright (C) 2008 Thorvald Natvig 3 | */ 4 | /** 5 | @file resample_sse.h 6 | @brief Resampler functions (SSE version) 7 | */ 8 | /* 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions 11 | are met: 12 | 13 | - Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | 16 | - Redistributions in binary form must reproduce the above copyright 17 | notice, this list of conditions and the following disclaimer in the 18 | documentation and/or other materials provided with the distribution. 19 | 20 | - Neither the name of the Xiph.org Foundation nor the names of its 21 | contributors may be used to endorse or promote products derived from 22 | this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 28 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | 37 | #include 38 | 39 | #define OVERRIDE_INNER_PRODUCT_SINGLE 40 | static inline float inner_product_single(const float *a, const float *b, unsigned int len) 41 | { 42 | int i; 43 | float ret; 44 | __m128 sum = _mm_setzero_ps(); 45 | for (i=0;i 76 | #define OVERRIDE_INNER_PRODUCT_DOUBLE 77 | 78 | static inline double inner_product_double(const float *a, const float *b, unsigned int len) 79 | { 80 | int i; 81 | double ret; 82 | __m128d sum = _mm_setzero_pd(); 83 | __m128 t; 84 | for (i=0;i. 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Components.h" 23 | 24 | #include "Dialog.h" 25 | #include "KeyBinds.h" 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | class Input: public libretro::InputComponent 34 | { 35 | public: 36 | enum class Button 37 | { 38 | kUp, 39 | kDown, 40 | kLeft, 41 | kRight, 42 | kX, 43 | kY, 44 | kA, 45 | kB, 46 | kL, 47 | kR, 48 | kL3, 49 | kR3, 50 | kSelect, 51 | kStart, 52 | }; 53 | 54 | enum class Axis 55 | { 56 | kLeftAxisX, 57 | kLeftAxisY, 58 | kRightAxisX, 59 | kRightAxisY, 60 | kL2, 61 | kR2 62 | }; 63 | 64 | enum class MouseButton 65 | { 66 | kLeft, 67 | kRight, 68 | kMiddle, 69 | }; 70 | 71 | bool init(libretro::LoggerComponent* logger); 72 | void destroy() {} 73 | void reset(); 74 | 75 | void autoAssign(); 76 | void buttonEvent(int port, Button button, bool pressed); 77 | void axisEvent(int port, Axis axis, int16_t value); 78 | void processEvent(const SDL_Event* event, KeyBinds* keyBinds, libretro::VideoComponent* video); 79 | void mouseButtonEvent(MouseButton button, bool pressed); 80 | void mouseMoveEvent(int relative_x, int relative_y, int absolute_x, int absolute_y); 81 | void keyboardEvent(enum retro_key key, bool pressed); 82 | 83 | virtual void setInputDescriptors(const struct retro_input_descriptor* descs, unsigned count) override; 84 | virtual void setKeyboardCallback(const struct retro_keyboard_callback* data) override; 85 | 86 | virtual void setControllerInfo(const struct retro_controller_info* info, unsigned count) override; 87 | virtual bool ctrlUpdated() override; 88 | virtual unsigned getController(unsigned port) override; 89 | void getControllerNames(unsigned port, std::vector& names, int& selectedIndex) const; 90 | void setSelectedControllerIndex(unsigned port, int selectedIndex); 91 | 92 | virtual bool setRumble(unsigned port, retro_rumble_effect effect, uint16_t strength) override; 93 | 94 | virtual void poll() override; 95 | virtual int16_t read(unsigned port, unsigned device, unsigned index, unsigned id) override; 96 | float getJoystickSensitivity(int joystickId); 97 | 98 | std::string serialize(); 99 | void deserialize(const char* json); 100 | 101 | KeyBinds::Binding captureButtonPress(); 102 | 103 | protected: 104 | struct Pad 105 | { 106 | SDL_JoystickID _id; 107 | SDL_GameController* _controller; 108 | const char* _controllerName; 109 | SDL_Joystick* _joystick; 110 | const char* _joystickName; 111 | uint64_t _ports; 112 | float _sensitivity; 113 | unsigned _navigationPort; 114 | SDL_Haptic* _haptic; 115 | int _rumbleEffect; 116 | }; 117 | 118 | struct Descriptor 119 | { 120 | unsigned _port; 121 | unsigned _device; 122 | unsigned _index; 123 | unsigned _button; 124 | 125 | std::string _description; 126 | }; 127 | 128 | struct ControllerInfo 129 | { 130 | std::string _description; 131 | unsigned _id = 0; 132 | int16_t _state = 0; 133 | int16_t _axis[6] = { 0,0,0,0,0,0 }; 134 | }; 135 | 136 | struct MouseInfo 137 | { 138 | int16_t _absolute_x, _absolute_y; 139 | int16_t _previous_x, _previous_y; 140 | int16_t _relative_x, _relative_y; 141 | bool _button[16]; 142 | }; 143 | 144 | struct KeyboardInfo 145 | { 146 | std::array _keys; 147 | struct retro_keyboard_callback _callbacks; 148 | }; 149 | 150 | enum 151 | { 152 | kMaxPorts = 8 153 | }; 154 | 155 | SDL_JoystickID addController(int which); 156 | void addController(const SDL_Event* event, KeyBinds* keyBinds, libretro::VideoComponent* video); 157 | void removeController(const SDL_Event* event, libretro::VideoComponent* video); 158 | 159 | static const char* s_getType(int index, void* udata); 160 | static const char* s_getPad(int index, void* udata); 161 | 162 | libretro::LoggerComponent* _logger; 163 | 164 | bool _updated; 165 | 166 | std::map _pads; 167 | std::vector _descriptors; 168 | 169 | std::map _joystickGUIDs; 170 | 171 | uint64_t _ports; 172 | std::vector _info[kMaxPorts]; 173 | MouseInfo _mouse; 174 | KeyboardInfo _keyboard; 175 | 176 | int _devices[kMaxPorts]; 177 | }; 178 | -------------------------------------------------------------------------------- /src/components/Video.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include "libretro/Components.h" 23 | #include "Config.h" 24 | #include "Gl.h" 25 | 26 | #include 27 | 28 | class Video: public libretro::VideoComponent 29 | { 30 | public: 31 | Video(); 32 | 33 | bool init(libretro::LoggerComponent* logger, libretro::VideoContextComponent* ctx, Config* config); 34 | void destroy(); 35 | 36 | virtual void setEnabled(bool enabled) override; 37 | 38 | void clear(); 39 | void redraw(); 40 | 41 | virtual bool setGeometry(unsigned width, unsigned height, unsigned maxWidth, unsigned maxHeight, float aspect, enum retro_pixel_format pixelFormat, const struct retro_hw_render_callback* hwRenderCallback) override; 42 | virtual void refresh(const void* data, unsigned width, unsigned height, size_t pitch) override; 43 | virtual void reset() override; 44 | 45 | virtual bool supportsContext(enum retro_hw_context_type type) override; 46 | virtual uintptr_t getCurrentFramebuffer() override; 47 | virtual retro_proc_address_t getProcAddress(const char* symbol) override; 48 | 49 | virtual void showMessage(const char* msg, unsigned frames) override; 50 | bool hasMessage() const { return _numMessages != 0; } 51 | 52 | virtual void showSpeedIndicator(Speed visibleIndicator) override; 53 | 54 | void windowResized(unsigned width, unsigned height); 55 | void getFramebufferSize(unsigned* width, unsigned* height, enum retro_pixel_format* format); 56 | const void* getFramebuffer(unsigned* width, unsigned* height, unsigned* pitch, enum retro_pixel_format* format); 57 | void setFramebuffer(void* pixels, unsigned width, unsigned height, unsigned pitch); 58 | 59 | std::string serializeSettings(); 60 | bool deserializeSettings(const char* json); 61 | void showDialog(); 62 | 63 | unsigned getWindowWidth() const { return _windowWidth; } 64 | unsigned getWindowHeight() const { return _windowHeight; } 65 | 66 | unsigned getViewWidth() const { return _viewWidth; } 67 | unsigned getViewHeight() const { return _viewHeight; } 68 | 69 | unsigned getViewScaledWidth() const { return _viewScaledWidth; } 70 | unsigned getViewScaledHeight() const { return _viewScaledHeight; } 71 | 72 | void setRotation(Rotation rotation) override; 73 | Rotation getRotation() const override { return _rotation; } 74 | 75 | typedef void (*RotationHandler)(Rotation oldRotation, Rotation newRotation); 76 | void setRotationChangedHandler(RotationHandler handler) { _rotationHandler = handler; } 77 | 78 | protected: 79 | void draw(bool force = false); 80 | 81 | GLuint createProgram(GLint* pos, GLint* uv, GLint* tex); 82 | bool ensureVertexArray(unsigned windowWidth, unsigned windowHeight, float texScaleX, float texScaleY, GLint pos, GLint uv); 83 | GLuint createTexture(unsigned width, unsigned height, retro_pixel_format pixelFormat, bool linear); 84 | bool ensureFramebuffer(unsigned width, unsigned height, retro_pixel_format pixelFormat, bool linearFilter); 85 | bool ensureView(unsigned width, unsigned height, unsigned windowWidth, unsigned windowHeight, bool preserveAspect, Rotation rotation); 86 | void clearErrors(); 87 | 88 | libretro::LoggerComponent* _logger; 89 | libretro::VideoContextComponent* _ctx; 90 | Config* _config; 91 | 92 | bool _enabled; 93 | 94 | GLuint _program; 95 | GLint _posAttribute; 96 | GLint _uvAttribute; 97 | GLint _texUniform; 98 | GLuint _vertexArray; 99 | GLuint _vertexBuffer; 100 | GLuint _indentityVertexBuffer; 101 | GLuint _texture; 102 | 103 | GLuint _messageTexture[4]; 104 | unsigned _messageWidth[4]; 105 | unsigned _messageFrames[4]; 106 | unsigned _numMessages; 107 | GLuint _speedIndicatorTexture; 108 | 109 | unsigned _windowWidth; 110 | unsigned _windowHeight; 111 | unsigned _textureWidth; 112 | unsigned _textureHeight; 113 | unsigned _viewWidth; 114 | unsigned _viewHeight; 115 | unsigned _viewScaledWidth; 116 | unsigned _viewScaledHeight; 117 | enum retro_pixel_format _pixelFormat; 118 | float _aspect; 119 | Rotation _rotation; 120 | RotationHandler _rotationHandler; 121 | 122 | bool _preserveAspect; 123 | bool _linearFilter; 124 | 125 | struct { 126 | bool enabled; 127 | GLuint frameBuffer; 128 | GLuint renderBuffer; 129 | const retro_hw_render_callback *callback; 130 | } _hw; 131 | }; 132 | 133 | -------------------------------------------------------------------------------- /src/components/Config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #ifdef _WINDOWS 23 | #include "components/Input.h" 24 | #endif 25 | 26 | #include "libretro/Components.h" 27 | 28 | #include 29 | #include 30 | 31 | class Config: public libretro::ConfigComponent 32 | { 33 | public: 34 | void initRootFolder(); 35 | bool init(libretro::LoggerComponent* logger); 36 | void destroy() {} 37 | void reset(); 38 | 39 | virtual const char* getCoreAssetsDirectory() override; 40 | virtual const char* getSaveDirectory() override; 41 | virtual const char* getSystemPath() override; 42 | 43 | virtual void setVariables(const struct retro_variable* variables, unsigned count) override; 44 | virtual void setVariables(const struct retro_core_option_definition* options, unsigned count) override; 45 | virtual void setVariables(const struct retro_core_option_v2_definition* options, unsigned count, 46 | const struct retro_core_option_v2_category* categories, unsigned category_count) override; 47 | virtual void setVariableDisplay(const struct retro_core_option_display* display) override; 48 | virtual bool varUpdated() override; 49 | virtual const char* getVariable(const char* variable) override; 50 | 51 | virtual bool getBackgroundInput() override { return _backgroundInput; } 52 | virtual void setBackgroundInput(bool value) override { _backgroundInput = value; } 53 | 54 | virtual bool getFastForwarding() override { return _fastForwarding; } 55 | virtual void setFastForwarding(bool value) override { _fastForwarding = value; } 56 | 57 | virtual bool getAudioWhileFastForwarding() override { return _audioWhileFastForwarding; } 58 | virtual int getFastForwardRatio() override { return _fastForwardRatio; } 59 | 60 | virtual bool getShowSpeedIndicator() override { return _showSpeedIndicator; } 61 | virtual void setShowSpeedIndicator(bool value) override { _showSpeedIndicator = value; } 62 | 63 | virtual bool getGameFocusCaptureMouse() override { return _gameFocusCaptureMouse; } 64 | 65 | void setSaveDirectory(const std::string& path) { _saveFolder = path; } 66 | 67 | const char* getRootFolder() 68 | { 69 | return _rootFolder.c_str(); 70 | } 71 | 72 | const char* getScreenshotsFolder() 73 | { 74 | return _screenshotsFolder.c_str(); 75 | } 76 | 77 | std::string serialize(); 78 | void deserialize(const char* json); 79 | 80 | bool validateSettingsForHardcore(const char* library_name, int console_id, bool prompt); 81 | 82 | std::string serializeEmulatorSettings() const; 83 | bool deserializeEmulatorSettings(const char* json); 84 | 85 | #ifdef _WINDOWS 86 | void showDialog(const std::string& coreName, Input& input); 87 | void showEmulatorSettingsDialog(); 88 | #endif 89 | 90 | protected: 91 | static const char* s_getOption(int index, void* udata); 92 | 93 | struct Category 94 | { 95 | std::string _key; 96 | std::string _name; 97 | std::string _description; 98 | int _visibleCount; 99 | }; 100 | 101 | struct Variable 102 | { 103 | std::string _key; 104 | std::string _name; 105 | int _selected; 106 | bool _hidden; 107 | 108 | Category* _category; 109 | 110 | std::vector _options; 111 | std::vector _labels; 112 | }; 113 | 114 | class ConfigDialog : public Dialog 115 | { 116 | public: 117 | std::vector variables; 118 | std::vector selections; 119 | std::vector categoryNames; 120 | Config* owner; 121 | int maxCount; 122 | Category* category; 123 | bool updated; 124 | 125 | void updateVariables(); 126 | 127 | protected: 128 | void initControls(HWND hwnd) override; 129 | 130 | INT_PTR dialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override; 131 | void retrieveData(HWND hwnd) override; 132 | 133 | HWND hwnd; 134 | }; 135 | 136 | static void initializeControllerVariable(Variable& variable, const char* name, const char* key, const std::map& names, unsigned selectedDevice); 137 | void setOptions(Variable& var, const retro_core_option_value* values, const char* default_value); 138 | 139 | libretro::LoggerComponent* _logger; 140 | 141 | std::string _rootFolder; 142 | std::string _assetsFolder; 143 | std::string _saveFolder; 144 | std::string _systemFolder; 145 | std::string _screenshotsFolder; 146 | 147 | std::vector _categories; 148 | std::vector _variables; 149 | std::unordered_map _selections; 150 | 151 | bool _updated; 152 | bool _fastForwarding; 153 | bool _hadDisallowedSetting; 154 | bool _audioWhileFastForwarding; 155 | bool _backgroundInput; 156 | bool _showSpeedIndicator; 157 | bool _gameFocusCaptureMouse; 158 | 159 | int _fastForwardRatio; 160 | 161 | std::string _key; 162 | }; 163 | -------------------------------------------------------------------------------- /src/Fsm.fsm: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | /* 21 | 22 | To generate Fsm.h and Fsm.cpp from this file: 23 | 24 | [Windows] 25 | * install lua 26 | - download lua-5.2.4.tar.gz (http://www.lua.org/ftp/) and extract somewhere [it must be a 5.2 version] 27 | - open MinGW 64-bit and change to the folder where you extracted the tar.gz 28 | - run `make clean`, `make mingw` and `make install TO_BIN="lua.exe luac.exe lua52.dll"` 29 | - verify install: 30 | $ lua -e "print('hello world')" 31 | hello world 32 | - remove extracted files; they're not needed anymore 33 | * install luarocks 34 | - download the latest ".win32.zip" not the ".windows-32.zip" (http://luarocks.github.io/luarocks/releases/) and extract it 35 | - open an elevated command prompt and change into the extracted folder 36 | - run `install.bat /lv 5.2 /bin c:\msys64\usr\local\bin /lib c:\msys64\usr\local\bin /inc c:\msys64\usr\local\include` 37 | * install luasrcdiet 38 | - open an elevated command promot and change into the luarocks install folder (C:\Program Files (x86)\LuaRocks) 39 | - run `luarocks.bat install luasrcdiet` 40 | * build ddlt 41 | - clone the https://github.com/leiradel/ddlt repository 42 | - open MinGW 64-bit and change to the cloned repository folder 43 | - manually run luasrcdiet as it was not installed under the MinGW context: 44 | `$ /c/Program\ Files\ \(x86\)/LuaRocks/bin/luasrcdiet.bat --noopt-emptylines src/boot.lua -o src/boot_diet.lua` 45 | - edit the Makefile to point to the correct lua locations: 46 | `INCLUDES=-Isrc -I/usr/local/include` 47 | `LUALIB=/usr/local/bin/lua52.dll` 48 | - allow make to do the rest of the work: `make` 49 | * generate the FSM files: 50 | - from MinGW 64-bit console (in the ddlt repository): 51 | `lua examples/fsmc/fsmc.lua /e/source/RALibRetro/src/Fsm.fsm` 52 | - this will generate the Fsm.h and Fsm.cpp files in the same directory as the Fsm.fsm file. 53 | */ 54 | 55 | header { 56 | #include "Emulator.h" 57 | #include 58 | 59 | typedef const std::string const_string; 60 | } 61 | 62 | fsm Fsm { 63 | class Application as ctx; 64 | 65 | after { 66 | ctx.updateMenu(); 67 | } 68 | 69 | Start { 70 | loadCore(const_string core) => CoreLoaded { 71 | if (!ctx.loadCore(core)) { 72 | forbid; 73 | } 74 | } 75 | 76 | quit() => Quit; 77 | } 78 | 79 | Quit {} 80 | 81 | CoreLoaded { 82 | loadCore(const_string core) => unloadCore() => loadCore(core); 83 | 84 | unloadCore() => Start { 85 | ctx.unloadCore(); 86 | } 87 | 88 | loadGame(const_string path) => GameRunning { 89 | if (!ctx.loadGame(path)) { 90 | forbid; 91 | } 92 | } 93 | 94 | quit() => unloadCore() => quit(); 95 | } 96 | 97 | GameRunning { 98 | pauseGame() => GamePaused; 99 | 100 | pauseGameNoOvl() => GamePausedNoOvl { 101 | if (ctx.hardcore()) { 102 | forbid; 103 | } 104 | } 105 | 106 | resetGame() => GameRunning { 107 | ctx.resetGame(); 108 | } 109 | 110 | step() => FrameStep { 111 | if (ctx.hardcore()) { 112 | forbid; 113 | } 114 | } 115 | 116 | unloadGame() => CoreLoaded { 117 | if (!ctx.unloadGame()) { 118 | forbid; 119 | } 120 | } 121 | 122 | loadCore(const_string core) => unloadGame() => unloadCore() => loadCore(core); 123 | 124 | loadGame(const_string path) => unloadGame() => loadGame(path); 125 | 126 | quit() => unloadGame() => quit(); 127 | } 128 | 129 | GamePaused { 130 | resumeGame() => GameRunning; 131 | 132 | resetGame() => GamePaused { 133 | ctx.resetGame(); 134 | } 135 | 136 | step() => FrameStep { 137 | if (ctx.hardcore()) { 138 | forbid; 139 | } 140 | } 141 | 142 | unloadGame() => CoreLoaded { 143 | if (!ctx.unloadGame()) { 144 | forbid; 145 | } 146 | } 147 | 148 | loadCore(const_string core) => unloadGame() => unloadCore() => loadCore(core); 149 | 150 | loadGame(const_string path) => unloadGame() => loadGame(path); 151 | 152 | quit() => unloadGame() => quit(); 153 | } 154 | 155 | GamePausedNoOvl { 156 | pauseGame() => GamePaused; 157 | 158 | resumeGame() => GameRunning; 159 | 160 | resetGame() => GamePausedNoOvl { 161 | ctx.resetGame(); 162 | } 163 | 164 | step() => FrameStep { 165 | if (ctx.hardcore()) { 166 | forbid; 167 | } 168 | } 169 | 170 | unloadGame() => CoreLoaded { 171 | if (!ctx.unloadGame()) { 172 | forbid; 173 | } 174 | } 175 | 176 | loadCore(const_string core) => unloadGame() => unloadCore() => loadCore(core); 177 | 178 | loadGame(const_string path) => unloadGame() => loadGame(path); 179 | 180 | quit() => unloadGame() => quit(); 181 | } 182 | 183 | FrameStep { 184 | resumeGame() => GamePaused; 185 | } 186 | } 187 | 188 | -------------------------------------------------------------------------------- /src/speex/fixed_bfin.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2005 Analog Devices 2 | Author: Jean-Marc Valin */ 3 | /** 4 | @file fixed_bfin.h 5 | @brief Blackfin fixed-point operations 6 | */ 7 | /* 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions 10 | are met: 11 | 12 | - Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | 15 | - Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimer in the 17 | documentation and/or other materials provided with the distribution. 18 | 19 | - Neither the name of the Xiph.org Foundation nor the names of its 20 | contributors may be used to endorse or promote products derived from 21 | this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | #ifndef FIXED_BFIN_H 37 | #define FIXED_BFIN_H 38 | 39 | #include "bfin.h" 40 | 41 | #undef PDIV32_16 42 | static inline spx_word16_t PDIV32_16(spx_word32_t a, spx_word16_t b) 43 | { 44 | spx_word32_t res, bb; 45 | bb = b; 46 | a += b>>1; 47 | __asm__ ( 48 | "P0 = 15;\n\t" 49 | "R0 = %1;\n\t" 50 | "R1 = %2;\n\t" 51 | //"R0 = R0 + R1;\n\t" 52 | "R0 <<= 1;\n\t" 53 | "DIVS (R0, R1);\n\t" 54 | "LOOP divide%= LC0 = P0;\n\t" 55 | "LOOP_BEGIN divide%=;\n\t" 56 | "DIVQ (R0, R1);\n\t" 57 | "LOOP_END divide%=;\n\t" 58 | "R0 = R0.L;\n\t" 59 | "%0 = R0;\n\t" 60 | : "=m" (res) 61 | : "m" (a), "m" (bb) 62 | : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); 63 | return res; 64 | } 65 | 66 | #undef DIV32_16 67 | static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word16_t b) 68 | { 69 | spx_word32_t res, bb; 70 | bb = b; 71 | /* Make the roundinf consistent with the C version 72 | (do we need to do that?)*/ 73 | if (a<0) 74 | a += (b-1); 75 | __asm__ ( 76 | "P0 = 15;\n\t" 77 | "R0 = %1;\n\t" 78 | "R1 = %2;\n\t" 79 | "R0 <<= 1;\n\t" 80 | "DIVS (R0, R1);\n\t" 81 | "LOOP divide%= LC0 = P0;\n\t" 82 | "LOOP_BEGIN divide%=;\n\t" 83 | "DIVQ (R0, R1);\n\t" 84 | "LOOP_END divide%=;\n\t" 85 | "R0 = R0.L;\n\t" 86 | "%0 = R0;\n\t" 87 | : "=m" (res) 88 | : "m" (a), "m" (bb) 89 | : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); 90 | return res; 91 | } 92 | 93 | #undef MAX16 94 | static inline spx_word16_t MAX16(spx_word16_t a, spx_word16_t b) 95 | { 96 | spx_word32_t res; 97 | __asm__ ( 98 | "%1 = %1.L (X);\n\t" 99 | "%2 = %2.L (X);\n\t" 100 | "%0 = MAX(%1,%2);" 101 | : "=d" (res) 102 | : "%d" (a), "d" (b) 103 | : "ASTAT" 104 | ); 105 | return res; 106 | } 107 | 108 | #undef MULT16_32_Q15 109 | static inline spx_word32_t MULT16_32_Q15(spx_word16_t a, spx_word32_t b) 110 | { 111 | spx_word32_t res; 112 | __asm__ 113 | ( 114 | "A1 = %2.L*%1.L (M);\n\t" 115 | "A1 = A1 >>> 15;\n\t" 116 | "%0 = (A1 += %2.L*%1.H) ;\n\t" 117 | : "=&W" (res), "=&d" (b) 118 | : "d" (a), "1" (b) 119 | : "A1", "ASTAT" 120 | ); 121 | return res; 122 | } 123 | 124 | #undef MAC16_32_Q15 125 | static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, spx_word32_t b) 126 | { 127 | spx_word32_t res; 128 | __asm__ 129 | ( 130 | "A1 = %2.L*%1.L (M);\n\t" 131 | "A1 = A1 >>> 15;\n\t" 132 | "%0 = (A1 += %2.L*%1.H);\n\t" 133 | "%0 = %0 + %4;\n\t" 134 | : "=&W" (res), "=&d" (b) 135 | : "d" (a), "1" (b), "d" (c) 136 | : "A1", "ASTAT" 137 | ); 138 | return res; 139 | } 140 | 141 | #undef MULT16_32_Q14 142 | static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b) 143 | { 144 | spx_word32_t res; 145 | __asm__ 146 | ( 147 | "%2 <<= 1;\n\t" 148 | "A1 = %1.L*%2.L (M);\n\t" 149 | "A1 = A1 >>> 15;\n\t" 150 | "%0 = (A1 += %1.L*%2.H);\n\t" 151 | : "=W" (res), "=d" (a), "=d" (b) 152 | : "1" (a), "2" (b) 153 | : "A1", "ASTAT" 154 | ); 155 | return res; 156 | } 157 | 158 | #undef MAC16_32_Q14 159 | static inline spx_word32_t MAC16_32_Q14(spx_word32_t c, spx_word16_t a, spx_word32_t b) 160 | { 161 | spx_word32_t res; 162 | __asm__ 163 | ( 164 | "%1 <<= 1;\n\t" 165 | "A1 = %2.L*%1.L (M);\n\t" 166 | "A1 = A1 >>> 15;\n\t" 167 | "%0 = (A1 += %2.L*%1.H);\n\t" 168 | "%0 = %0 + %4;\n\t" 169 | : "=&W" (res), "=&d" (b) 170 | : "d" (a), "1" (b), "d" (c) 171 | : "A1", "ASTAT" 172 | ); 173 | return res; 174 | } 175 | 176 | #endif 177 | -------------------------------------------------------------------------------- /src/speex/fixed_generic.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Jean-Marc Valin */ 2 | /** 3 | @file fixed_generic.h 4 | @brief Generic fixed-point operations 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef FIXED_GENERIC_H 36 | #define FIXED_GENERIC_H 37 | 38 | #define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) 39 | #define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) 40 | 41 | #define NEG16(x) (-(x)) 42 | #define NEG32(x) (-(x)) 43 | #define EXTRACT16(x) ((spx_word16_t)(x)) 44 | #define EXTEND32(x) ((spx_word32_t)(x)) 45 | #define SHR16(a,shift) ((a) >> (shift)) 46 | #define SHL16(a,shift) ((a) << (shift)) 47 | #define SHR32(a,shift) ((a) >> (shift)) 48 | #define SHL32(a,shift) ((a) << (shift)) 49 | #define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) 50 | #define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) 51 | #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) 52 | #define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 53 | #define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 54 | 55 | #define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \ 56 | (x)<=-(SHL32(a,shift)) ? -(a) : \ 57 | (PSHR32(x, shift))) 58 | 59 | #define SHR(a,shift) ((a) >> (shift)) 60 | #define SHL(a,shift) ((spx_word32_t)(a) << (shift)) 61 | #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) 62 | #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) 63 | 64 | 65 | #define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) 66 | #define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) 67 | #define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) 68 | #define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) 69 | 70 | 71 | /* result fits in 16 bits */ 72 | #define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) 73 | 74 | /* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ 75 | #define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) 76 | 77 | #define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) 78 | #define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) 79 | #define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) 80 | #define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14)) 81 | 82 | #define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)) 83 | #define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))) 84 | 85 | #define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) 86 | #define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) 87 | #define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) 88 | 89 | 90 | #define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) 91 | #define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13))) 92 | #define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13))) 93 | 94 | #define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) 95 | #define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) 96 | #define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) 97 | #define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) 98 | 99 | #define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) 100 | #define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) 101 | #define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) 102 | 103 | #define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) 104 | 105 | #define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) 106 | #define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) 107 | #define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) 108 | #define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/Application.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include "Fsm.h" 27 | 28 | #include 29 | 30 | #include "components/Allocator.h" 31 | #include "components/Audio.h" 32 | #include "components/Config.h" 33 | #include "components/Input.h" 34 | #include "components/Logger.h" 35 | #include "components/Microphone.h" 36 | #include "components/VideoContext.h" 37 | #include "components/Video.h" 38 | 39 | #include "Emulator.h" 40 | #include "KeyBinds.h" 41 | #include "Memory.h" 42 | #include "States.h" 43 | 44 | class Application 45 | { 46 | public: 47 | Application(); 48 | 49 | // Lifecycle 50 | bool init(const char* title, int width, int height); 51 | bool handleArgs(int argc, char *argv[]); 52 | 53 | void run(); 54 | void destroy(); 55 | 56 | // FSM 57 | bool loadCore(const std::string& coreName); 58 | void updateMenu(); 59 | bool loadGame(const std::string& path); 60 | void unloadCore(); 61 | void resetGame(); 62 | bool hardcore(); 63 | bool unloadGame(); 64 | void pauseGame(bool pause); 65 | bool isPaused() const; 66 | 67 | void printf(const char* fmt, ...); 68 | Logger& logger() { return _logger; } 69 | 70 | // RA_Integration 71 | bool isGameActive(); 72 | const std::string& gameName() const { return _gameFileName; } 73 | bool validateHardcoreEnablement(); 74 | 75 | void onRotationChanged(Video::Rotation oldRotation, Video::Rotation newRotation); 76 | 77 | void refreshMemoryMap(); 78 | 79 | Config& config() { return _config; } 80 | 81 | protected: 82 | struct RecentItem 83 | { 84 | std::string path; 85 | std::string coreName; 86 | int system; 87 | }; 88 | 89 | // Called by SDL from the audio thread 90 | static void s_audioCallback(void* udata, Uint8* stream, int len); 91 | 92 | // Helpers 93 | void processEvents(); 94 | void runSmoothed(); 95 | void runTurbo(); 96 | void pauseForBadPerformance(); 97 | 98 | void loadGame(); 99 | void enableItems(const UINT* items, size_t count, UINT enable); 100 | void enableSlots(); 101 | void enableRecent(); 102 | void updateDiscMenu(bool updateLabels); 103 | std::string getStatePath(unsigned ndx); 104 | std::string getConfigPath(); 105 | std::string getCoreConfigPath(const std::string& coreName); 106 | std::string getScreenshotPath(); 107 | void saveState(const std::string& path); 108 | void saveState(unsigned ndx); 109 | void saveState(); 110 | void loadState(const std::string& path); 111 | void loadState(unsigned ndx); 112 | void loadState(); 113 | void changeCurrentState(unsigned ndx); 114 | void screenshot(); 115 | void aboutDialog(); 116 | void resizeWindow(unsigned multiplier); 117 | void resizeWindow(int width, int height); 118 | void toggleFullscreen(); 119 | void handle(const SDL_SysWMEvent* syswm); 120 | void handle(const SDL_WindowEvent* window); 121 | void handle(const SDL_MouseMotionEvent* motion); 122 | void handle(const SDL_MouseButtonEvent* button); 123 | void handle(const KeyBinds::Action action, unsigned extra); 124 | void buildSystemsMenu(); 125 | void loadConfiguration(int* window_x, int* window_y, int* window_width, int* window_height); 126 | void saveConfiguration(); 127 | std::string serializeRecentList(); 128 | void updateMouseCapture(); 129 | void updateSpeedIndicator(); 130 | void toggleFastForwarding(unsigned extra); 131 | void toggleBackgroundInput(); 132 | void setBackgroundInput(bool enabled); 133 | void toggleTray(); 134 | void readyNextDisc(int offset); 135 | void readyDisc(unsigned newDiscIndex); 136 | std::string getDiscLabel(unsigned index) const; 137 | 138 | Fsm _fsm; 139 | bool lastHardcore; 140 | bool cancelLoad; 141 | 142 | std::string _coreName; 143 | int _system; 144 | 145 | SDL_Window* _window; 146 | SDL_AudioSpec _audioSpec; 147 | SDL_AudioDeviceID _audioDev; 148 | 149 | Fifo _fifo; 150 | Logger _logger; 151 | Config _config; 152 | VideoContext _videoContext; 153 | Video _video; 154 | Audio _audio; 155 | Microphone _microphone; 156 | Input _input; 157 | Memory _memory; 158 | States _states; 159 | 160 | int _numAudioFaults; 161 | int _numAudioRecoveries; 162 | int _audioGeneratedDuringFastForward; 163 | bool _vsyncDisabledByAudioFaults; 164 | bool _processingEvents; 165 | 166 | KeyBinds _keybinds; 167 | std::vector _recentList; 168 | std::vector _discPaths; 169 | bool _isDriveFloppy; 170 | 171 | Allocator<256 * 1024> _allocator; 172 | 173 | libretro::Components _components; 174 | libretro::Core _core; 175 | 176 | std::string _gamePath; 177 | std::string _gameFileName; 178 | void* _gameData; 179 | unsigned _validSlots; 180 | bool _gamePathIsTemporary; 181 | 182 | HMENU _menu; 183 | HMENU _cdRomMenu; 184 | 185 | int _absViewMouseX; 186 | int _absViewMouseY; 187 | }; 188 | -------------------------------------------------------------------------------- /src/speex/fixed_arm5e.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Jean-Marc Valin */ 2 | /** 3 | @file fixed_arm5e.h 4 | @brief ARM-tuned fixed-point operations 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef FIXED_ARM5E_H 36 | #define FIXED_ARM5E_H 37 | 38 | #undef MULT16_16 39 | static inline spx_word32_t MULT16_16(spx_word16_t x, spx_word16_t y) { 40 | int res; 41 | asm ("smulbb %0,%1,%2;\n" 42 | : "=&r"(res) 43 | : "%r"(x),"r"(y)); 44 | return(res); 45 | } 46 | 47 | #undef MAC16_16 48 | static inline spx_word32_t MAC16_16(spx_word32_t a, spx_word16_t x, spx_word32_t y) { 49 | int res; 50 | asm ("smlabb %0,%1,%2,%3;\n" 51 | : "=&r"(res) 52 | : "%r"(x),"r"(y),"r"(a)); 53 | return(res); 54 | } 55 | 56 | #undef MULT16_32_Q15 57 | static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) { 58 | int res; 59 | asm ("smulwb %0,%1,%2;\n" 60 | : "=&r"(res) 61 | : "%r"(y<<1),"r"(x)); 62 | return(res); 63 | } 64 | 65 | #undef MAC16_32_Q15 66 | static inline spx_word32_t MAC16_32_Q15(spx_word32_t a, spx_word16_t x, spx_word32_t y) { 67 | int res; 68 | asm ("smlawb %0,%1,%2,%3;\n" 69 | : "=&r"(res) 70 | : "%r"(y<<1),"r"(x),"r"(a)); 71 | return(res); 72 | } 73 | 74 | #undef MULT16_32_Q11 75 | static inline spx_word32_t MULT16_32_Q11(spx_word16_t x, spx_word32_t y) { 76 | int res; 77 | asm ("smulwb %0,%1,%2;\n" 78 | : "=&r"(res) 79 | : "%r"(y<<5),"r"(x)); 80 | return(res); 81 | } 82 | 83 | #undef MAC16_32_Q11 84 | static inline spx_word32_t MAC16_32_Q11(spx_word32_t a, spx_word16_t x, spx_word32_t y) { 85 | int res; 86 | asm ("smlawb %0,%1,%2,%3;\n" 87 | : "=&r"(res) 88 | : "%r"(y<<5),"r"(x),"r"(a)); 89 | return(res); 90 | } 91 | 92 | #undef DIV32_16 93 | static inline short DIV32_16(int a, int b) 94 | { 95 | int res=0; 96 | int dead1, dead2, dead3, dead4, dead5; 97 | __asm__ __volatile__ ( 98 | "\teor %5, %0, %1\n" 99 | "\tmovs %4, %0\n" 100 | "\trsbmi %0, %0, #0 \n" 101 | "\tmovs %4, %1\n" 102 | "\trsbmi %1, %1, #0 \n" 103 | "\tmov %4, #1\n" 104 | 105 | "\tsubs %3, %0, %1, asl #14 \n" 106 | "\torrpl %2, %2, %4, asl #14 \n" 107 | "\tmovpl %0, %3 \n" 108 | 109 | "\tsubs %3, %0, %1, asl #13 \n" 110 | "\torrpl %2, %2, %4, asl #13 \n" 111 | "\tmovpl %0, %3 \n" 112 | 113 | "\tsubs %3, %0, %1, asl #12 \n" 114 | "\torrpl %2, %2, %4, asl #12 \n" 115 | "\tmovpl %0, %3 \n" 116 | 117 | "\tsubs %3, %0, %1, asl #11 \n" 118 | "\torrpl %2, %2, %4, asl #11 \n" 119 | "\tmovpl %0, %3 \n" 120 | 121 | "\tsubs %3, %0, %1, asl #10 \n" 122 | "\torrpl %2, %2, %4, asl #10 \n" 123 | "\tmovpl %0, %3 \n" 124 | 125 | "\tsubs %3, %0, %1, asl #9 \n" 126 | "\torrpl %2, %2, %4, asl #9 \n" 127 | "\tmovpl %0, %3 \n" 128 | 129 | "\tsubs %3, %0, %1, asl #8 \n" 130 | "\torrpl %2, %2, %4, asl #8 \n" 131 | "\tmovpl %0, %3 \n" 132 | 133 | "\tsubs %3, %0, %1, asl #7 \n" 134 | "\torrpl %2, %2, %4, asl #7 \n" 135 | "\tmovpl %0, %3 \n" 136 | 137 | "\tsubs %3, %0, %1, asl #6 \n" 138 | "\torrpl %2, %2, %4, asl #6 \n" 139 | "\tmovpl %0, %3 \n" 140 | 141 | "\tsubs %3, %0, %1, asl #5 \n" 142 | "\torrpl %2, %2, %4, asl #5 \n" 143 | "\tmovpl %0, %3 \n" 144 | 145 | "\tsubs %3, %0, %1, asl #4 \n" 146 | "\torrpl %2, %2, %4, asl #4 \n" 147 | "\tmovpl %0, %3 \n" 148 | 149 | "\tsubs %3, %0, %1, asl #3 \n" 150 | "\torrpl %2, %2, %4, asl #3 \n" 151 | "\tmovpl %0, %3 \n" 152 | 153 | "\tsubs %3, %0, %1, asl #2 \n" 154 | "\torrpl %2, %2, %4, asl #2 \n" 155 | "\tmovpl %0, %3 \n" 156 | 157 | "\tsubs %3, %0, %1, asl #1 \n" 158 | "\torrpl %2, %2, %4, asl #1 \n" 159 | "\tmovpl %0, %3 \n" 160 | 161 | "\tsubs %3, %0, %1 \n" 162 | "\torrpl %2, %2, %4 \n" 163 | "\tmovpl %0, %3 \n" 164 | 165 | "\tmovs %5, %5, lsr #31 \n" 166 | "\trsbne %2, %2, #0 \n" 167 | : "=r" (dead1), "=r" (dead2), "=r" (res), 168 | "=r" (dead3), "=r" (dead4), "=r" (dead5) 169 | : "0" (a), "1" (b), "2" (res) 170 | : "memory", "cc" 171 | ); 172 | return res; 173 | } 174 | 175 | 176 | 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /src/libchdr.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {1b09ea08-feeb-4e7c-9bc0-0170bd1de538} 6 | 7 | 8 | {76db1418-5622-496b-9c92-8bcd9649b6f3} 9 | 10 | 11 | {ad972f61-02df-4c5a-af25-b997be37894e} 12 | 13 | 14 | {b2f0fccc-ffbd-4f14-8ca3-932cbaa6f40a} 15 | 16 | 17 | {71dd06ce-b02e-479d-b4a3-925e844d3690} 18 | 19 | 20 | {c00242e4-c3dc-4570-8f3f-ee04033a440c} 21 | 22 | 23 | 24 | 25 | libchdr 26 | 27 | 28 | libchdr 29 | 30 | 31 | libchdr 32 | 33 | 34 | libchdr 35 | 36 | 37 | libchdr 38 | 39 | 40 | zlib 41 | 42 | 43 | zlib 44 | 45 | 46 | zlib 47 | 48 | 49 | zlib 50 | 51 | 52 | zlib 53 | 54 | 55 | zlib 56 | 57 | 58 | zlib 59 | 60 | 61 | zlib 62 | 63 | 64 | zlib 65 | 66 | 67 | zlib 68 | 69 | 70 | zlib 71 | 72 | 73 | zlib 74 | 75 | 76 | zlib 77 | 78 | 79 | zlib 80 | 81 | 82 | zlib 83 | 84 | 85 | lzma 86 | 87 | 88 | lzma 89 | 90 | 91 | lzma 92 | 93 | 94 | lzma 95 | 96 | 97 | lzma 98 | 99 | 100 | lzma 101 | 102 | 103 | lzma 104 | 105 | 106 | lzma 107 | 108 | 109 | lzma 110 | 111 | 112 | lzma 113 | 114 | 115 | zstd\common 116 | 117 | 118 | zstd\common 119 | 120 | 121 | zstd\common 122 | 123 | 124 | zstd\common 125 | 126 | 127 | zstd\common 128 | 129 | 130 | zstd\common 131 | 132 | 133 | zstd\common 134 | 135 | 136 | zstd\common 137 | 138 | 139 | zstd\decompress 140 | 141 | 142 | zstd\decompress 143 | 144 | 145 | zstd\decompress 146 | 147 | 148 | zstd\decompress 149 | 150 | 151 | -------------------------------------------------------------------------------- /src/libmincrypt/sha256.c: -------------------------------------------------------------------------------- 1 | /* sha256.c 2 | ** 3 | ** Copyright 2013, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // Optimized for minimal code size. 29 | 30 | #include "sha256.h" 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits)))) 37 | #define shr(value, bits) ((value) >> (bits)) 38 | 39 | static const uint32_t K[64] = { 40 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 41 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 42 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 43 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 44 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 45 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 46 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 47 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 48 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 49 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 50 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 51 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 52 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 53 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 54 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 55 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; 56 | 57 | static void SHA256_Transform(SHA256_CTX* ctx) { 58 | uint32_t W[64]; 59 | uint32_t A, B, C, D, E, F, G, H; 60 | uint8_t* p = ctx->buf; 61 | int t; 62 | 63 | for(t = 0; t < 16; ++t) { 64 | uint32_t tmp = *p++ << 24; 65 | tmp |= *p++ << 16; 66 | tmp |= *p++ << 8; 67 | tmp |= *p++; 68 | W[t] = tmp; 69 | } 70 | 71 | for(; t < 64; t++) { 72 | uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3); 73 | uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10); 74 | W[t] = W[t-16] + s0 + W[t-7] + s1; 75 | } 76 | 77 | A = ctx->state[0]; 78 | B = ctx->state[1]; 79 | C = ctx->state[2]; 80 | D = ctx->state[3]; 81 | E = ctx->state[4]; 82 | F = ctx->state[5]; 83 | G = ctx->state[6]; 84 | H = ctx->state[7]; 85 | 86 | for(t = 0; t < 64; t++) { 87 | uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22); 88 | uint32_t maj = (A & B) ^ (A & C) ^ (B & C); 89 | uint32_t t2 = s0 + maj; 90 | uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25); 91 | uint32_t ch = (E & F) ^ ((~E) & G); 92 | uint32_t t1 = H + s1 + ch + K[t] + W[t]; 93 | 94 | H = G; 95 | G = F; 96 | F = E; 97 | E = D + t1; 98 | D = C; 99 | C = B; 100 | B = A; 101 | A = t1 + t2; 102 | } 103 | 104 | ctx->state[0] += A; 105 | ctx->state[1] += B; 106 | ctx->state[2] += C; 107 | ctx->state[3] += D; 108 | ctx->state[4] += E; 109 | ctx->state[5] += F; 110 | ctx->state[6] += G; 111 | ctx->state[7] += H; 112 | } 113 | 114 | static const HASH_VTAB SHA256_VTAB = { 115 | SHA256_init, 116 | SHA256_update, 117 | SHA256_final, 118 | SHA256_hash, 119 | SHA256_DIGEST_SIZE 120 | }; 121 | 122 | void SHA256_init(SHA256_CTX* ctx) { 123 | ctx->f = &SHA256_VTAB; 124 | ctx->state[0] = 0x6a09e667; 125 | ctx->state[1] = 0xbb67ae85; 126 | ctx->state[2] = 0x3c6ef372; 127 | ctx->state[3] = 0xa54ff53a; 128 | ctx->state[4] = 0x510e527f; 129 | ctx->state[5] = 0x9b05688c; 130 | ctx->state[6] = 0x1f83d9ab; 131 | ctx->state[7] = 0x5be0cd19; 132 | ctx->count = 0; 133 | } 134 | 135 | void SHA256_update(SHA256_CTX* ctx, const void* data, int len) { 136 | int i = (int) (ctx->count & 63); 137 | const uint8_t* p = (const uint8_t*)data; 138 | ctx->count += len; 139 | while (len--) { 140 | ctx->buf[i++] = *p++; 141 | if (i == 64) { 142 | SHA256_Transform(ctx); 143 | i = 0; 144 | } 145 | } 146 | } 147 | 148 | const uint8_t* SHA256_final(SHA256_CTX* ctx) { 149 | uint8_t *p = ctx->buf; 150 | uint64_t cnt = ctx->count * 8; 151 | int i; 152 | 153 | SHA256_update(ctx, (uint8_t*)"\x80", 1); 154 | while ((ctx->count & 63) != 56) { 155 | SHA256_update(ctx, (uint8_t*)"\0", 1); 156 | } 157 | 158 | for (i = 0; i < 8; ++i) { 159 | uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8)); 160 | SHA256_update(ctx, &tmp, 1); 161 | } 162 | 163 | for (i = 0; i < 8; i++) { 164 | uint32_t tmp = ctx->state[i]; 165 | *p++ = tmp >> 24; 166 | *p++ = tmp >> 16; 167 | *p++ = tmp >> 8; 168 | *p++ = tmp >> 0; 169 | } 170 | 171 | return ctx->buf; 172 | } 173 | 174 | /* Convenience function */ 175 | const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) { 176 | SHA256_CTX ctx; 177 | SHA256_init(&ctx); 178 | SHA256_update(&ctx, data, len); 179 | memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE); 180 | return digest; 181 | } 182 | -------------------------------------------------------------------------------- /src/components/Logger.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #include "Logger.h" 21 | 22 | #ifdef LOG_TO_FILE 23 | #include "Util.h" 24 | #include 25 | #endif 26 | 27 | #include 28 | #include 29 | 30 | /* must be less than RING_LOG_MAX_BUFFER_SIZE */ 31 | #ifndef RING_LOG_MAX_LINE_SIZE 32 | #define RING_LOG_MAX_LINE_SIZE 1024 33 | #endif 34 | 35 | bool Logger::init(const char* rootFolder) 36 | { 37 | // Do compile-time checks for the line and buffer sizes. 38 | char check_line_size[RING_LOG_MAX_LINE_SIZE <= 65535 ? 1 : -1]; 39 | char check_buffer_size[RING_LOG_MAX_BUFFER_SIZE >= RING_LOG_MAX_LINE_SIZE + 3 ? 1 : -1]; 40 | 41 | (void)check_line_size; 42 | (void)check_buffer_size; 43 | 44 | _avail = RING_LOG_MAX_BUFFER_SIZE; 45 | _first = _last = 0; 46 | 47 | #ifdef LOG_TO_FILE 48 | char path[512] = ""; 49 | if (rootFolder) 50 | strcpy(path, rootFolder); 51 | strcat(path, "log.txt"); 52 | _file = util::openFile(NULL, path, "w"); 53 | #endif 54 | 55 | #ifndef NDEBUG 56 | setLogLevel(RETRO_LOG_DEBUG); 57 | #endif 58 | 59 | return true; 60 | } 61 | 62 | void Logger::destroy() 63 | { 64 | #ifdef LOG_TO_FILE 65 | if (_file) 66 | { 67 | fclose(_file); 68 | _file = NULL; 69 | } 70 | #endif 71 | } 72 | 73 | void Logger::log(enum retro_log_level level, const char* line, size_t length) 74 | { 75 | const char* desc = "?"; 76 | 77 | switch (level) 78 | { 79 | case RETRO_LOG_DEBUG: desc = "DEBUG"; break; 80 | case RETRO_LOG_INFO: desc = "INFO "; break; 81 | case RETRO_LOG_WARN: desc = "WARN "; break; 82 | case RETRO_LOG_ERROR: desc = "ERROR"; break; 83 | case RETRO_LOG_DUMMY: desc = "DUMMY"; break; 84 | } 85 | 86 | // Do not log debug messages to the internal buffer and the console. 87 | if (level != RETRO_LOG_DEBUG) 88 | { 89 | // Log to the internal buffer. 90 | length += 3; // Add one byte for the level and two bytes for the length. 91 | 92 | if (length > RING_LOG_MAX_LINE_SIZE) 93 | length = RING_LOG_MAX_LINE_SIZE; 94 | 95 | unsigned char meta[3]; 96 | if (length > _avail) 97 | { 98 | do 99 | { 100 | // Remove content until we have enough space. 101 | read(meta, 3); 102 | skip(meta[1] | meta[2] << 8); // Little endian. 103 | } while (length > _avail); 104 | } 105 | 106 | length -= 3; 107 | 108 | meta[0] = level; 109 | meta[1] = length & 0xff; 110 | meta[2] = (unsigned char)(length >> 8); 111 | 112 | write(meta, 3); 113 | write(line, length); 114 | 115 | // Log to the console. 116 | ::printf("[%s] %s\n", desc, line); 117 | fflush(stdout); 118 | } 119 | 120 | #ifdef LOG_TO_FILE 121 | if (_file) 122 | { 123 | const std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); 124 | const unsigned int now_ms = (unsigned int) 125 | (std::chrono::time_point_cast(now).time_since_epoch().count() % 1000); 126 | const time_t now_timet = std::chrono::system_clock::to_time_t(now); 127 | std::tm now_tm; 128 | localtime_s(&now_tm, &now_timet); 129 | char buffer[10]; 130 | strftime(buffer, sizeof(buffer), "%H%M%S", &now_tm); 131 | 132 | // Log to the log file. 133 | fprintf(_file, "%s.%03u [%s] %s\n", buffer, now_ms, desc, line); 134 | #ifndef NDEBUG 135 | fflush(_file); 136 | #endif 137 | } 138 | #endif 139 | } 140 | 141 | std::string Logger::contents() const 142 | { 143 | struct Iterator 144 | { 145 | static bool iterator(enum retro_log_level level, const char* line, void* ud) 146 | { 147 | std::string* buffer = (std::string*)ud; 148 | 149 | switch (level) 150 | { 151 | case RETRO_LOG_DEBUG: *buffer += "[DEBUG] "; break; 152 | case RETRO_LOG_INFO: *buffer += "[INFO] "; break; 153 | case RETRO_LOG_WARN: *buffer += "[WARN] "; break; 154 | case RETRO_LOG_ERROR: *buffer += "[ERROR] "; break; 155 | case RETRO_LOG_DUMMY: *buffer += "[DUMMY] "; break; 156 | } 157 | 158 | *buffer += line; 159 | *buffer += "\r\n"; 160 | 161 | return true; 162 | } 163 | }; 164 | 165 | std::string buffer; 166 | iterate(Iterator::iterator, &buffer); 167 | return buffer; 168 | } 169 | 170 | void Logger::iterate(Iterator iterator, void* ud) const 171 | { 172 | size_t pos = _first; 173 | 174 | while (pos != _last) 175 | { 176 | char line[RING_LOG_MAX_LINE_SIZE + 1]; 177 | unsigned char meta[3]; 178 | pos = peek(pos, meta, 3); 179 | 180 | enum retro_log_level level = (enum retro_log_level)meta[0]; 181 | size_t length = meta[1] | meta[2] << 8; 182 | pos = peek(pos, line, length); 183 | line[length] = 0; 184 | 185 | if (!iterator(level, line, ud)) 186 | { 187 | return; 188 | } 189 | } 190 | } 191 | 192 | void Logger::write(const void* data, size_t size) 193 | { 194 | size_t first = size; 195 | size_t second = 0; 196 | 197 | if (first > RING_LOG_MAX_BUFFER_SIZE - _last) 198 | { 199 | first = RING_LOG_MAX_BUFFER_SIZE - _last; 200 | second = size - first; 201 | } 202 | 203 | char* dest = _buffer + _last; 204 | memcpy(dest, data, first); 205 | memcpy(_buffer, (char*)data + first, second); 206 | 207 | _last = (_last + size) % RING_LOG_MAX_BUFFER_SIZE; 208 | _avail -= size; 209 | } 210 | 211 | void Logger::read(void* data, size_t size) 212 | { 213 | size_t first = size; 214 | size_t second = 0; 215 | 216 | if (first > RING_LOG_MAX_BUFFER_SIZE - _first) 217 | { 218 | first = RING_LOG_MAX_BUFFER_SIZE - _first; 219 | second = size - first; 220 | } 221 | 222 | char* src = _buffer + _first; 223 | memcpy(data, src, first); 224 | memcpy((char*)data + first, _buffer, second); 225 | 226 | _first = (_first + size) % RING_LOG_MAX_BUFFER_SIZE; 227 | _avail += size; 228 | } 229 | 230 | size_t Logger::peek(size_t pos, void* data, size_t size) const 231 | { 232 | size_t first = size; 233 | size_t second = 0; 234 | 235 | if (first > RING_LOG_MAX_BUFFER_SIZE - pos) 236 | { 237 | first = RING_LOG_MAX_BUFFER_SIZE - pos; 238 | second = size - first; 239 | } 240 | 241 | const char* src = _buffer + pos; 242 | memcpy(data, src, first); 243 | memcpy((char*)data + first, _buffer, second); 244 | 245 | return (pos + size) % RING_LOG_MAX_BUFFER_SIZE; 246 | } 247 | -------------------------------------------------------------------------------- /src/Hash.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2018 Andre Leiradella 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #include "Hash.h" 21 | 22 | #include "Core.h" 23 | #include "Util.h" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | #define WIN32_LEAN_AND_MEAN 33 | #include 34 | #include 35 | 36 | #ifdef HAVE_CHD 37 | void rc_hash_init_chd_cdreader(); /* in HashCHD.cpp */ 38 | #endif 39 | 40 | void initHash3DS(const std::string& systemDir); /* in Hash3DS.cpp */ 41 | 42 | #define TAG "[HASH]" 43 | 44 | // Manages multi-disc games 45 | static int g_activeGame = 0; 46 | static rc_libretro_hash_set_t g_hashSet; 47 | 48 | static void rhash_display_error_message(const char* message) 49 | { 50 | #ifdef _WINDOWS 51 | extern HWND g_mainWindow; 52 | MessageBoxA(g_mainWindow, (LPCSTR)message, "Unable to identify game", MB_OK); 53 | #else 54 | fprintf(stderr, "Unable to identify game"); 55 | #endif 56 | } 57 | 58 | static Logger* g_logger = NULL; 59 | static libretro::Core* g_core = NULL; 60 | static void* rhash_file_open(const char* path) 61 | { 62 | return util::openFile(g_logger, path, "rb"); 63 | } 64 | 65 | void rhash_log_error_message(const char* message) 66 | { 67 | g_logger->warn(TAG "%s", message); 68 | } 69 | 70 | static int rhash_get_image_path(unsigned index, char* buffer, size_t buffer_size) 71 | { 72 | std::string path; 73 | if (!g_core->getDiscPath(index, path)) 74 | return 0; 75 | 76 | strncpy(buffer, path.c_str(), buffer_size); 77 | return 1; 78 | } 79 | 80 | bool romLoaded(libretro::Core* core, Logger* logger, int system, const std::string& path, void* rom, size_t size, bool changingDiscs) 81 | { 82 | unsigned int gameId = 0; 83 | char hash[33]; 84 | bool found = false; 85 | 86 | g_logger = logger; 87 | 88 | /* don't pop up error message when changing discs */ 89 | if (changingDiscs) 90 | rc_hash_init_error_message_callback(rhash_log_error_message); 91 | else 92 | rc_hash_init_error_message_callback(rhash_display_error_message); 93 | 94 | hash[0] = '\0'; 95 | 96 | if (changingDiscs) 97 | { 98 | const char* existingHash = rc_libretro_hash_set_get_hash(&g_hashSet, path.c_str()); 99 | if (existingHash) 100 | { 101 | memcpy(hash, existingHash, sizeof(hash)); 102 | gameId = rc_libretro_hash_set_get_game_id(&g_hashSet, existingHash); 103 | found = true; 104 | } 105 | } 106 | else 107 | { 108 | rc_hash_iterator_t hash_iterator; 109 | rc_hash_initialize_iterator(&hash_iterator, NULL, NULL, 0); 110 | hash_iterator.callbacks.filereader.open = rhash_file_open; 111 | 112 | g_core = core; 113 | rc_libretro_hash_set_init(&g_hashSet, path.c_str(), rhash_get_image_path, &hash_iterator.callbacks.filereader); 114 | g_core = NULL; 115 | 116 | rc_hash_destroy_iterator(&hash_iterator); 117 | } 118 | 119 | if (!found) 120 | { 121 | if (!hash[0]) 122 | { 123 | struct rc_hash_filereader filereader; 124 | rc_hash_iterator_t hash_iterator; 125 | std::string ext = util::extension(path); 126 | 127 | /* register a custom file_open handler for unicode support. use the default implementation for the other methods */ 128 | memset(&filereader, 0, sizeof(filereader)); 129 | filereader.open = rhash_file_open; 130 | rc_hash_init_custom_filereader(&filereader); 131 | 132 | if (ext.length() == 4 && tolower(ext[1]) == 'c' && tolower(ext[2]) == 'h' && tolower(ext[3]) == 'd') 133 | { 134 | #ifdef HAVE_CHD 135 | rc_hash_init_chd_cdreader(); 136 | #else 137 | extern HWND g_mainWindow; 138 | MessageBox(g_mainWindow, "CHD not supported without HAVE_CHD compile flag", "Error", MB_OK); 139 | return false; 140 | #endif 141 | } 142 | else 143 | { 144 | if (!rom && ext.length() == 4 && tolower(ext[1]) == 'z' && tolower(ext[2]) == 'i' && tolower(ext[3]) == 'p') 145 | { 146 | /* file is a zip and we haven't preloaded it into memory. see if the core extracted it somewhere */ 147 | if (core->getNumDiscs() > 0) 148 | { 149 | std::string discPath; 150 | if (core->getDiscPath(core->getCurrentDiscIndex(), discPath) && discPath != path) 151 | return romLoaded(core, logger, system, discPath, rom, size, changingDiscs); 152 | } 153 | } 154 | 155 | rc_hash_init_default_cdreader(); 156 | } 157 | 158 | if (system == RC_CONSOLE_NINTENDO_3DS) 159 | initHash3DS(core->getSystemDirectory()); 160 | 161 | /* generate a hash for the new content */ 162 | rc_hash_initialize_iterator(&hash_iterator, path.c_str(), (const uint8_t*)rom, size); 163 | rc_hash_generate(hash, (int)system, &hash_iterator); 164 | } 165 | 166 | /* identify the game associated to the hash */ 167 | gameId = hash[0] ? RA_IdentifyHash(hash) : 0; 168 | 169 | /* remember the hash/game so we don't have to look it up again if the user switches back */ 170 | rc_libretro_hash_set_add(&g_hashSet, path.c_str(), gameId, hash); 171 | } 172 | 173 | if (!changingDiscs) 174 | { 175 | /* when not changing discs, just activate the new game */ 176 | g_activeGame = gameId; 177 | RA_ActivateGame(gameId); 178 | } 179 | else if (gameId != 0) 180 | { 181 | /* when changing discs, if the disc is recognized, allow it. normally, this is going 182 | * to be the same game that's already loaded, but this also allows loading known game 183 | * discs for games that leverage user-provided discs. */ 184 | } 185 | else if (!hash[0]) 186 | { 187 | /* when changing discs, if the disc is not supported by the system, allow it. this is 188 | * primarily for games that support user-provided audio CDs, but does allow using discs 189 | * from other systems for games that leverage user-provided discs. */ 190 | } 191 | else 192 | { 193 | /* an unrecognized disc could be a cheated game, don't allow it in hardcore */ 194 | if (!RA_WarnDisableHardcore("switch to an unrecognized disc")) 195 | return false; 196 | } 197 | 198 | /* return true to allow the game to load, even if it's not associated to achievements */ 199 | return true; 200 | } 201 | 202 | void romUnloaded(Logger* logger) 203 | { 204 | rc_libretro_hash_set_destroy(&g_hashSet); 205 | g_activeGame = 0; 206 | RA_ActivateGame(0); 207 | } 208 | -------------------------------------------------------------------------------- /src/speex/resample_neon.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007-2008 Jean-Marc Valin 2 | * Copyright (C) 2008 Thorvald Natvig 3 | * Copyright (C) 2011 Texas Instruments 4 | * author Jyri Sarha 5 | */ 6 | /** 7 | @file resample_neon.h 8 | @brief Resampler functions (NEON version) 9 | */ 10 | /* 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | - Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | 18 | - Redistributions in binary form must reproduce the above copyright 19 | notice, this list of conditions and the following disclaimer in the 20 | documentation and/or other materials provided with the distribution. 21 | 22 | - Neither the name of the Xiph.org Foundation nor the names of its 23 | contributors may be used to endorse or promote products derived from 24 | this software without specific prior written permission. 25 | 26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 30 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 31 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 34 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 35 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 36 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #include 40 | 41 | #ifdef FIXED_POINT 42 | #ifdef __thumb2__ 43 | static inline int32_t saturate_32bit_to_16bit(int32_t a) { 44 | int32_t ret; 45 | asm ("ssat %[ret], #16, %[a]" 46 | : [ret] "=&r" (ret) 47 | : [a] "r" (a) 48 | : ); 49 | return ret; 50 | } 51 | #else 52 | static inline int32_t saturate_32bit_to_16bit(int32_t a) { 53 | int32_t ret; 54 | asm ("vmov.s32 d0[0], %[a]\n" 55 | "vqmovn.s32 d0, q0\n" 56 | "vmov.s16 %[ret], d0[0]\n" 57 | : [ret] "=&r" (ret) 58 | : [a] "r" (a) 59 | : "q0"); 60 | return ret; 61 | } 62 | #endif 63 | #undef WORD2INT 64 | #define WORD2INT(x) (saturate_32bit_to_16bit(x)) 65 | 66 | #define OVERRIDE_INNER_PRODUCT_SINGLE 67 | /* Only works when len % 4 == 0 */ 68 | static inline int32_t inner_product_single(const int16_t *a, const int16_t *b, unsigned int len) 69 | { 70 | int32_t ret; 71 | uint32_t remainder = len % 16; 72 | len = len - remainder; 73 | 74 | asm volatile (" cmp %[len], #0\n" 75 | " bne 1f\n" 76 | " vld1.16 {d16}, [%[b]]!\n" 77 | " vld1.16 {d20}, [%[a]]!\n" 78 | " subs %[remainder], %[remainder], #4\n" 79 | " vmull.s16 q0, d16, d20\n" 80 | " beq 5f\n" 81 | " b 4f\n" 82 | "1:" 83 | " vld1.16 {d16, d17, d18, d19}, [%[b]]!\n" 84 | " vld1.16 {d20, d21, d22, d23}, [%[a]]!\n" 85 | " subs %[len], %[len], #16\n" 86 | " vmull.s16 q0, d16, d20\n" 87 | " vmlal.s16 q0, d17, d21\n" 88 | " vmlal.s16 q0, d18, d22\n" 89 | " vmlal.s16 q0, d19, d23\n" 90 | " beq 3f\n" 91 | "2:" 92 | " vld1.16 {d16, d17, d18, d19}, [%[b]]!\n" 93 | " vld1.16 {d20, d21, d22, d23}, [%[a]]!\n" 94 | " subs %[len], %[len], #16\n" 95 | " vmlal.s16 q0, d16, d20\n" 96 | " vmlal.s16 q0, d17, d21\n" 97 | " vmlal.s16 q0, d18, d22\n" 98 | " vmlal.s16 q0, d19, d23\n" 99 | " bne 2b\n" 100 | "3:" 101 | " cmp %[remainder], #0\n" 102 | " beq 5f\n" 103 | "4:" 104 | " vld1.16 {d16}, [%[b]]!\n" 105 | " vld1.16 {d20}, [%[a]]!\n" 106 | " subs %[remainder], %[remainder], #4\n" 107 | " vmlal.s16 q0, d16, d20\n" 108 | " bne 4b\n" 109 | "5:" 110 | " vaddl.s32 q0, d0, d1\n" 111 | " vadd.s64 d0, d0, d1\n" 112 | " vqmovn.s64 d0, q0\n" 113 | " vqrshrn.s32 d0, q0, #15\n" 114 | " vmov.s16 %[ret], d0[0]\n" 115 | : [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b), 116 | [len] "+r" (len), [remainder] "+r" (remainder) 117 | : 118 | : "cc", "q0", 119 | "d16", "d17", "d18", "d19", 120 | "d20", "d21", "d22", "d23"); 121 | 122 | return ret; 123 | } 124 | #elif defined(FLOATING_POINT) 125 | 126 | static inline int32_t saturate_float_to_16bit(float a) { 127 | int32_t ret; 128 | asm ("vmov.f32 d0[0], %[a]\n" 129 | "vcvt.s32.f32 d0, d0, #15\n" 130 | "vqrshrn.s32 d0, q0, #15\n" 131 | "vmov.s16 %[ret], d0[0]\n" 132 | : [ret] "=&r" (ret) 133 | : [a] "r" (a) 134 | : "q0"); 135 | return ret; 136 | } 137 | #undef WORD2INT 138 | #define WORD2INT(x) (saturate_float_to_16bit(x)) 139 | 140 | #define OVERRIDE_INNER_PRODUCT_SINGLE 141 | /* Only works when len % 4 == 0 */ 142 | static inline float inner_product_single(const float *a, const float *b, unsigned int len) 143 | { 144 | float ret; 145 | uint32_t remainder = len % 16; 146 | len = len - remainder; 147 | 148 | asm volatile (" cmp %[len], #0\n" 149 | " bne 1f\n" 150 | " vld1.32 {q4}, [%[b]]!\n" 151 | " vld1.32 {q8}, [%[a]]!\n" 152 | " subs %[remainder], %[remainder], #4\n" 153 | " vmul.f32 q0, q4, q8\n" 154 | " bne 4f\n" 155 | " b 5f\n" 156 | "1:" 157 | " vld1.32 {q4, q5}, [%[b]]!\n" 158 | " vld1.32 {q8, q9}, [%[a]]!\n" 159 | " vld1.32 {q6, q7}, [%[b]]!\n" 160 | " vld1.32 {q10, q11}, [%[a]]!\n" 161 | " subs %[len], %[len], #16\n" 162 | " vmul.f32 q0, q4, q8\n" 163 | " vmul.f32 q1, q5, q9\n" 164 | " vmul.f32 q2, q6, q10\n" 165 | " vmul.f32 q3, q7, q11\n" 166 | " beq 3f\n" 167 | "2:" 168 | " vld1.32 {q4, q5}, [%[b]]!\n" 169 | " vld1.32 {q8, q9}, [%[a]]!\n" 170 | " vld1.32 {q6, q7}, [%[b]]!\n" 171 | " vld1.32 {q10, q11}, [%[a]]!\n" 172 | " subs %[len], %[len], #16\n" 173 | " vmla.f32 q0, q4, q8\n" 174 | " vmla.f32 q1, q5, q9\n" 175 | " vmla.f32 q2, q6, q10\n" 176 | " vmla.f32 q3, q7, q11\n" 177 | " bne 2b\n" 178 | "3:" 179 | " vadd.f32 q4, q0, q1\n" 180 | " vadd.f32 q5, q2, q3\n" 181 | " cmp %[remainder], #0\n" 182 | " vadd.f32 q0, q4, q5\n" 183 | " beq 5f\n" 184 | "4:" 185 | " vld1.32 {q6}, [%[b]]!\n" 186 | " vld1.32 {q10}, [%[a]]!\n" 187 | " subs %[remainder], %[remainder], #4\n" 188 | " vmla.f32 q0, q6, q10\n" 189 | " bne 4b\n" 190 | "5:" 191 | " vadd.f32 d0, d0, d1\n" 192 | " vpadd.f32 d0, d0, d0\n" 193 | " vmov.f32 %[ret], d0[0]\n" 194 | : [ret] "=&r" (ret), [a] "+r" (a), [b] "+r" (b), 195 | [len] "+l" (len), [remainder] "+l" (remainder) 196 | : 197 | : "cc", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", 198 | "q9", "q10", "q11"); 199 | return ret; 200 | } 201 | #endif 202 | -------------------------------------------------------------------------------- /src/speex/arch.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Jean-Marc Valin */ 2 | /** 3 | @file arch.h 4 | @brief Various architecture definitions Speex 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef ARCH_H 36 | #define ARCH_H 37 | 38 | /* A couple test to catch stupid option combinations */ 39 | #ifdef FIXED_POINT 40 | 41 | #ifdef FLOATING_POINT 42 | #error You cannot compile as floating point and fixed point at the same time 43 | #endif 44 | #ifdef _USE_SSE 45 | #error SSE is only for floating-point 46 | #endif 47 | #if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM)) 48 | #error Make up your mind. What CPU do you have? 49 | #endif 50 | #ifdef VORBIS_PSYCHO 51 | #error Vorbis-psy model currently not implemented in fixed-point 52 | #endif 53 | 54 | #else 55 | 56 | #ifndef FLOATING_POINT 57 | #error You now need to define either FIXED_POINT or FLOATING_POINT 58 | #endif 59 | #if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM) 60 | #error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions? 61 | #endif 62 | #ifdef FIXED_POINT_DEBUG 63 | #error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?" 64 | #endif 65 | 66 | 67 | #endif 68 | 69 | #ifndef OUTSIDE_SPEEX 70 | #include "speex/speexdsp_types.h" 71 | #endif 72 | 73 | #define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ 74 | #define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ 75 | #define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ 76 | #define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ 77 | #define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ 78 | #define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */ 79 | #define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ 80 | 81 | #ifdef FIXED_POINT 82 | 83 | typedef spx_int16_t spx_word16_t; 84 | typedef spx_int32_t spx_word32_t; 85 | typedef spx_word32_t spx_mem_t; 86 | typedef spx_word16_t spx_coef_t; 87 | typedef spx_word16_t spx_lsp_t; 88 | typedef spx_word32_t spx_sig_t; 89 | 90 | #define Q15ONE 32767 91 | 92 | #define LPC_SCALING 8192 93 | #define SIG_SCALING 16384 94 | #define LSP_SCALING 8192. 95 | #define GAMMA_SCALING 32768. 96 | #define GAIN_SCALING 64 97 | #define GAIN_SCALING_1 0.015625 98 | 99 | #define LPC_SHIFT 13 100 | #define LSP_SHIFT 13 101 | #define SIG_SHIFT 14 102 | #define GAIN_SHIFT 6 103 | 104 | #define VERY_SMALL 0 105 | #define VERY_LARGE32 ((spx_word32_t)2147483647) 106 | #define VERY_LARGE16 ((spx_word16_t)32767) 107 | #define Q15_ONE ((spx_word16_t)32767) 108 | 109 | 110 | #ifdef FIXED_DEBUG 111 | #include "fixed_debug.h" 112 | #else 113 | 114 | #include "fixed_generic.h" 115 | 116 | #ifdef ARM5E_ASM 117 | #include "fixed_arm5e.h" 118 | #elif defined (ARM4_ASM) 119 | #include "fixed_arm4.h" 120 | #elif defined (BFIN_ASM) 121 | #include "fixed_bfin.h" 122 | #endif 123 | 124 | #endif 125 | 126 | 127 | #else 128 | 129 | typedef float spx_mem_t; 130 | typedef float spx_coef_t; 131 | typedef float spx_lsp_t; 132 | typedef float spx_sig_t; 133 | typedef float spx_word16_t; 134 | typedef float spx_word32_t; 135 | 136 | #define Q15ONE 1.0f 137 | #define LPC_SCALING 1.f 138 | #define SIG_SCALING 1.f 139 | #define LSP_SCALING 1.f 140 | #define GAMMA_SCALING 1.f 141 | #define GAIN_SCALING 1.f 142 | #define GAIN_SCALING_1 1.f 143 | 144 | 145 | #define VERY_SMALL 1e-15f 146 | #define VERY_LARGE32 1e15f 147 | #define VERY_LARGE16 1e15f 148 | #define Q15_ONE ((spx_word16_t)1.f) 149 | 150 | #define QCONST16(x,bits) (x) 151 | #define QCONST32(x,bits) (x) 152 | 153 | #define NEG16(x) (-(x)) 154 | #define NEG32(x) (-(x)) 155 | #define EXTRACT16(x) (x) 156 | #define EXTEND32(x) (x) 157 | #define SHR16(a,shift) (a) 158 | #define SHL16(a,shift) (a) 159 | #define SHR32(a,shift) (a) 160 | #define SHL32(a,shift) (a) 161 | #define PSHR16(a,shift) (a) 162 | #define PSHR32(a,shift) (a) 163 | #define VSHR32(a,shift) (a) 164 | #define SATURATE16(x,a) (x) 165 | #define SATURATE32(x,a) (x) 166 | #define SATURATE32PSHR(x,shift,a) (x) 167 | 168 | #define PSHR(a,shift) (a) 169 | #define SHR(a,shift) (a) 170 | #define SHL(a,shift) (a) 171 | #define SATURATE(x,a) (x) 172 | 173 | #define ADD16(a,b) ((a)+(b)) 174 | #define SUB16(a,b) ((a)-(b)) 175 | #define ADD32(a,b) ((a)+(b)) 176 | #define SUB32(a,b) ((a)-(b)) 177 | #define MULT16_16_16(a,b) ((a)*(b)) 178 | #define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b)) 179 | #define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b)) 180 | 181 | #define MULT16_32_Q11(a,b) ((a)*(b)) 182 | #define MULT16_32_Q13(a,b) ((a)*(b)) 183 | #define MULT16_32_Q14(a,b) ((a)*(b)) 184 | #define MULT16_32_Q15(a,b) ((a)*(b)) 185 | #define MULT16_32_P15(a,b) ((a)*(b)) 186 | 187 | #define MAC16_32_Q11(c,a,b) ((c)+(a)*(b)) 188 | #define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) 189 | 190 | #define MAC16_16_Q11(c,a,b) ((c)+(a)*(b)) 191 | #define MAC16_16_Q13(c,a,b) ((c)+(a)*(b)) 192 | #define MAC16_16_P13(c,a,b) ((c)+(a)*(b)) 193 | #define MULT16_16_Q11_32(a,b) ((a)*(b)) 194 | #define MULT16_16_Q13(a,b) ((a)*(b)) 195 | #define MULT16_16_Q14(a,b) ((a)*(b)) 196 | #define MULT16_16_Q15(a,b) ((a)*(b)) 197 | #define MULT16_16_P15(a,b) ((a)*(b)) 198 | #define MULT16_16_P13(a,b) ((a)*(b)) 199 | #define MULT16_16_P14(a,b) ((a)*(b)) 200 | 201 | #define DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) 202 | #define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) 203 | #define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) 204 | #define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) 205 | 206 | 207 | #endif 208 | 209 | 210 | #if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) 211 | 212 | /* 2 on TI C5x DSP */ 213 | #define BYTES_PER_CHAR 2 214 | #define BITS_PER_CHAR 16 215 | #define LOG2_BITS_PER_CHAR 4 216 | 217 | #else 218 | 219 | #define BYTES_PER_CHAR 1 220 | #define BITS_PER_CHAR 8 221 | #define LOG2_BITS_PER_CHAR 3 222 | 223 | #endif 224 | 225 | 226 | 227 | #ifdef FIXED_DEBUG 228 | extern long long spx_mips; 229 | #endif 230 | 231 | 232 | #endif 233 | -------------------------------------------------------------------------------- /src/Hash3DS.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2024 Brian Weiss 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | 19 | */ 20 | 21 | #include "Util.h" 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | void rhash_log_error_message(const char* message); /* in Hash.c */ 31 | 32 | #undef DEBUG_AES_KEYS 33 | 34 | /* for finding aes_keys.txt and seeddb.bin */ 35 | static std::string g_systemDir = "."; 36 | 37 | static void rhash_read_128bit_hex(const char* hex, uint8_t key[16]) 38 | { 39 | char pair[4]; 40 | int index; 41 | pair[2] = '\0'; 42 | 43 | for (index = 0; index < 16; ++index) 44 | { 45 | pair[0] = *hex++; 46 | pair[1] = *hex++; 47 | 48 | key[index] = (uint8_t)strtol(pair, NULL, 16); 49 | } 50 | } 51 | 52 | static void rhash_rol_128bit(uint8_t key[16], int amount) 53 | { 54 | uint8_t copy[16]; 55 | int offset = amount / 8; 56 | int shift = amount % 8; 57 | int index; 58 | 59 | memcpy(copy, key, 16); 60 | for (index = 0; index < 16; ++index) 61 | { 62 | key[index] = (uint8_t)(copy[offset] << shift); 63 | offset = (offset + 1) % 16; 64 | key[index] |= (uint8_t)(copy[offset] >> (8 - shift)); 65 | } 66 | } 67 | 68 | static void rhash_xor_128bit(uint8_t key[16], const uint8_t value[16]) 69 | { 70 | int index; 71 | for (index = 0; index < 16; ++index) 72 | key[index] ^= value[index]; 73 | } 74 | 75 | static void rhash_add_128bit(uint8_t key[16], const uint8_t value[16]) 76 | { 77 | uint16_t carry = 0; 78 | int index; 79 | for (index = 15; index >= 0; --index) 80 | { 81 | carry += key[index] + value[index]; 82 | key[index] = (uint8_t)(carry & 0xFF); 83 | carry >>= 8; 84 | } 85 | } 86 | 87 | #ifdef DEBUG_AES_KEYS 88 | static void rhash_print_key(uint8_t key[16]) 89 | { 90 | printf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 91 | key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7], 92 | key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]); 93 | } 94 | #endif 95 | 96 | static int rhash_3ds_normalize_keys(uint8_t keyX[16], uint8_t keyY[16], uint8_t keyN[16]) 97 | { 98 | if (keyX[0] && keyY[0]) 99 | { 100 | uint8_t generator_constant[16] = { 0x1F, 0xF9, 0xE9, 0xAA, 0xC5, 0xFE, 0x04, 0x08, 0x02, 0x45, 0x91, 0xDC, 0x5D, 0x52, 0x76, 0x8A }; 101 | 102 | memcpy(keyN, keyX, 16); 103 | rhash_rol_128bit(keyN, 2); 104 | rhash_xor_128bit(keyN, keyY); 105 | rhash_add_128bit(keyN, generator_constant); 106 | rhash_rol_128bit(keyN, 87); 107 | return 1; 108 | } 109 | 110 | return 0; 111 | } 112 | 113 | static int rhash_3ds_lookup_cia_normal_key(uint8_t index, uint8_t key[16]) 114 | { 115 | char scan[16]; 116 | size_t scan_len; 117 | char buffer[128]; 118 | uint8_t keyX[16]; 119 | uint8_t keyY[16]; 120 | char* line; 121 | 122 | FILE* fp = util::openFile(nullptr, g_systemDir + "/aes_keys.txt", "r"); 123 | if (!fp) 124 | { 125 | rhash_log_error_message("Could not open aes_keys.txt"); 126 | return 0; 127 | } 128 | 129 | keyX[0] = 0; 130 | keyY[0] = 0; 131 | scan_len = snprintf(scan, sizeof(scan), "common%u=", index); 132 | 133 | while ((line = fgets(buffer, sizeof(buffer), fp))) 134 | { 135 | if (memcmp(line, scan, scan_len) == 0) 136 | { 137 | rhash_read_128bit_hex(line + scan_len, keyY); 138 | if (keyX[0]) 139 | break; 140 | } 141 | else if (memcmp(line, "slot0x3DKeyX=", 13) == 0) 142 | { 143 | rhash_read_128bit_hex(line + 13, keyX); 144 | if (keyY[0]) 145 | break; 146 | } 147 | } 148 | 149 | fclose(fp); 150 | 151 | return rhash_3ds_normalize_keys(keyX, keyY, key); 152 | } 153 | 154 | static int rhash_3ds_lookup_ncch_normal_key(uint8_t primaryKeyY[16], 155 | uint8_t secondaryKeyXSlot, uint8_t* programId, 156 | uint8_t primaryKeyOut[16], uint8_t secondaryKeyOut[16]) 157 | { 158 | char scan[16]; 159 | char buffer[128]; 160 | uint8_t primaryKeyX[16]; 161 | uint8_t secondaryKeyX[16]; 162 | uint8_t secondaryKeyY[16]; 163 | char* line; 164 | 165 | FILE* fp = util::openFile(nullptr, g_systemDir + "/aes_keys.txt", "r"); 166 | if (!fp) 167 | { 168 | rhash_log_error_message("Could not open aes_keys.txt"); 169 | return 0; 170 | } 171 | 172 | primaryKeyX[0] = 0; 173 | secondaryKeyX[0] = 0; 174 | snprintf(scan, sizeof(scan), "slot0x%02XKeyX=", secondaryKeyXSlot); 175 | 176 | while ((line = fgets(buffer, sizeof(buffer), fp))) 177 | { 178 | if (memcmp(line, "slot0x2CKeyX=", 13) == 0) 179 | { 180 | rhash_read_128bit_hex(line + 13, primaryKeyX); 181 | if (secondaryKeyX[0]) 182 | break; 183 | 184 | if (secondaryKeyXSlot == 0x2C) 185 | { 186 | memcpy(secondaryKeyX, primaryKeyX, sizeof(secondaryKeyX)); 187 | break; 188 | } 189 | } 190 | else if (memcmp(line, scan, 13) == 0) 191 | { 192 | rhash_read_128bit_hex(line + 13, secondaryKeyX); 193 | if (primaryKeyX[0]) 194 | break; 195 | } 196 | } 197 | 198 | fclose(fp); 199 | 200 | if (!rhash_3ds_normalize_keys(primaryKeyX, primaryKeyY, primaryKeyOut)) 201 | return 0; 202 | 203 | #ifdef DEBUG_AES_KEYS 204 | printf("Primary key: "); rhash_print_key(primaryKeyOut); printf("\n"); 205 | #endif 206 | 207 | if (!programId) 208 | { 209 | memcpy(secondaryKeyY, primaryKeyY, sizeof(secondaryKeyY)); 210 | } 211 | else 212 | { 213 | uint32_t count; 214 | SHA256_CTX ctx; 215 | 216 | /* find the seed for the programId */ 217 | fp = util::openFile(nullptr, g_systemDir + "/seeddb.bin", "rb"); 218 | if (!fp) 219 | { 220 | rhash_log_error_message("Could not open seeddb.bin"); 221 | return 0; 222 | } 223 | 224 | /* seeddb.bin's layout is simply the first 4 bytes indicate the amount of seeds in the 225 | * file, followed by 12 bytes of padding. Then a collection of seeds in the format of 226 | * 8 bytes for the program id, then 16 bytes for the seed, then 8 bytes of padding */ 227 | fread(&count, sizeof(count), 1, fp); 228 | fseek(fp, 12, SEEK_CUR); 229 | 230 | for (; count > 0; count--) 231 | { 232 | fread(buffer, sizeof(uint8_t), 8, fp); 233 | if (memcmp(buffer, programId, 8) == 0) 234 | { 235 | fread(secondaryKeyY, sizeof(uint8_t), sizeof(secondaryKeyY), fp); 236 | break; 237 | } 238 | fseek(fp, 16 + 8, SEEK_CUR); 239 | } 240 | 241 | fclose(fp); 242 | 243 | if (count == 0) /* did not find programId in seeddb.bin */ 244 | return 0; 245 | 246 | /* the actual secondaryKeyY used to generate the normalized key is the first 16 bytes 247 | * of the SHA256 of the primaryKeyY and the seed pulled from seeddb.bin */ 248 | SHA256_init(&ctx); 249 | SHA256_update(&ctx, primaryKeyY, 16); 250 | SHA256_update(&ctx, secondaryKeyY, 16); 251 | memcpy(secondaryKeyY, SHA256_final(&ctx), sizeof(secondaryKeyY)); 252 | } 253 | 254 | if (!rhash_3ds_normalize_keys(secondaryKeyX, secondaryKeyY, secondaryKeyOut)) 255 | return 0; 256 | 257 | #ifdef DEBUG_AES_KEYS 258 | printf("Secondary key: "); rhash_print_key(secondaryKeyOut); printf("\n"); 259 | #endif 260 | 261 | return 1; 262 | } 263 | 264 | void initHash3DS(const std::string& systemDir) 265 | { 266 | g_systemDir = systemDir; 267 | 268 | rc_hash_init_3ds_get_cia_normal_key_func(rhash_3ds_lookup_cia_normal_key); 269 | rc_hash_init_3ds_get_ncch_normal_keys_func(rhash_3ds_lookup_ncch_normal_key); 270 | } 271 | -------------------------------------------------------------------------------- /src/components/Microphone.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2023 Brian Weiss 3 | 4 | This file is part of RALibretro. 5 | 6 | RALibretro is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | RALibretro is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with RALibretro. If not, see . 18 | */ 19 | 20 | #include "Microphone.h" 21 | 22 | #include "Application.h" 23 | 24 | #include 25 | #include "speex/speex_resampler.h" 26 | 27 | #include 28 | 29 | #define TAG "[MIC] " 30 | 31 | struct Microphone::SDLData 32 | { 33 | SDL_AudioDeviceID deviceId; 34 | SDL_AudioSpec deviceSpec; 35 | unsigned coreRate; 36 | bool enabled; 37 | Fifo fifo; 38 | libretro::LoggerComponent* logger; 39 | SpeexResamplerState* resampler; 40 | }; 41 | 42 | bool Microphone::init(libretro::LoggerComponent* logger) 43 | { 44 | _logger = logger; 45 | return true; 46 | } 47 | 48 | void Microphone::destroy() 49 | { 50 | if (_data) 51 | closeMic((retro_microphone_t*)_data); 52 | } 53 | 54 | void Microphone::recordCallback(void* data, Uint8* stream, int len) 55 | { 56 | SDLData* sdlData = (SDLData*)data; 57 | 58 | if (!sdlData->enabled) /* don't fill buffer when mic is not active, nothing is going to read the buffer */ 59 | return; 60 | 61 | extern Application app; 62 | if (app.isPaused()) /* don't fill buffer while paused, nothing is running to empty buffer */ 63 | return; 64 | 65 | int frames = len / sizeof(int16_t); 66 | int16_t* samples = (int16_t*)stream; 67 | 68 | size_t output_size; 69 | int16_t* output; 70 | 71 | if (sdlData->deviceSpec.freq == (int)sdlData->coreRate) 72 | { 73 | /* no resampling needed */ 74 | output = (int16_t*)samples; 75 | output_size = frames * sizeof(int16_t); 76 | } 77 | else 78 | { 79 | /* allocate output buffer */ 80 | spx_uint32_t out_len = (spx_uint32_t)ceil(frames * sdlData->coreRate / sdlData->deviceSpec.freq); 81 | output_size = out_len * sizeof(int16_t); 82 | output = (int16_t*)alloca(output_size); 83 | 84 | if (output == NULL) 85 | { 86 | sdlData->logger->error(TAG "Error allocating audio resampling output buffer"); 87 | return; 88 | } 89 | 90 | /* do the resampling */ 91 | int error; 92 | if (!sdlData->resampler) 93 | { 94 | sdlData->resampler = speex_resampler_init(1, sdlData->deviceSpec.freq, sdlData->coreRate, SPEEX_RESAMPLER_QUALITY_DEFAULT, &error); 95 | 96 | if (!sdlData->resampler) 97 | { 98 | sdlData->logger->error(TAG "speex_resampler_init: %s", speex_resampler_strerror(error)); 99 | SDL_PauseAudioDevice(sdlData->deviceId, true); 100 | return; 101 | } 102 | } 103 | 104 | spx_uint32_t in_frames = frames; 105 | spx_uint32_t out_frames = out_len; 106 | sdlData->logger->debug(TAG "Resampling %u samples to %u", in_frames, out_frames); 107 | error = speex_resampler_process_int(sdlData->resampler, 0, (const int16_t*)samples, &in_frames, output, &out_frames); 108 | if (error == RESAMPLER_ERR_SUCCESS) 109 | { 110 | /* update with the actual number of frames created */ 111 | output_size = out_frames * sizeof(int16_t); 112 | } 113 | else 114 | { 115 | memset(output, 0, output_size); 116 | sdlData->logger->error(TAG "speex_resampler_process_int: %s", speex_resampler_strerror(error)); 117 | } 118 | } 119 | 120 | /* flush to FIFO queue */ 121 | size_t avail = sdlData->fifo.free(); 122 | if (avail < output_size) 123 | { 124 | sdlData->logger->debug(TAG "Waiting for FIFO (need %zu bytes but only %zu available), sleeping", output_size, avail); 125 | 126 | const int MAX_WAIT = 250; 127 | int tries = MAX_WAIT; 128 | do 129 | { 130 | SDL_Delay(1); 131 | if (!sdlData->enabled) 132 | return; 133 | 134 | avail = sdlData->fifo.free(); 135 | if (avail >= output_size) 136 | break; 137 | 138 | /* prevent infinite loop if fifo full */ 139 | if (--tries == 0) 140 | { 141 | sdlData->logger->debug(TAG "FIFO still full after %dms, flushing", MAX_WAIT); 142 | sdlData->fifo.reset(); 143 | avail = sdlData->fifo.free(); 144 | break; 145 | } 146 | } while (true); 147 | 148 | if (avail < output_size) 149 | output_size = avail; 150 | } 151 | 152 | sdlData->fifo.write(output, output_size); 153 | } 154 | 155 | retro_microphone_t* Microphone::openMic(const retro_microphone_params_t* params) 156 | { 157 | if (_data != NULL) /* only one microphone allowed at a time*/ 158 | return NULL; 159 | 160 | SDLData* data = new SDLData(); 161 | if (data == NULL) 162 | return NULL; 163 | 164 | data->logger = _logger; 165 | data->resampler = nullptr; 166 | data->coreRate = params->rate; 167 | data->enabled = false; 168 | 169 | SDL_AudioSpec desired_spec {}; 170 | desired_spec.freq = params->rate; 171 | desired_spec.format = AUDIO_S16SYS; 172 | desired_spec.channels = 1; /* Microphones only usually provide input in mono */ 173 | desired_spec.samples = 2048; 174 | desired_spec.userdata = data; 175 | desired_spec.callback = recordCallback; 176 | 177 | data->deviceId = SDL_OpenAudioDevice(NULL, true, &desired_spec, &data->deviceSpec, 178 | SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); 179 | 180 | if (data->deviceId == 0) 181 | { 182 | _logger->error(TAG "Failed to open SDL audio input device: %s", SDL_GetError()); 183 | delete data; 184 | return NULL; 185 | } 186 | 187 | _logger->info(TAG "Opened microphone with ID %u (frequency %u [requested %u])", data->deviceId, data->deviceSpec.freq, desired_spec.freq); 188 | _logger->info(TAG "Microphone audio format: %u-bit %s %s %s endian\n", 189 | SDL_AUDIO_BITSIZE(data->deviceSpec.format), 190 | SDL_AUDIO_ISSIGNED(data->deviceSpec.format) ? "signed" : "unsigned", 191 | SDL_AUDIO_ISFLOAT(data->deviceSpec.format) ? "floating-point" : "integer", 192 | SDL_AUDIO_ISBIGENDIAN(data->deviceSpec.format) ? "big" : "little"); 193 | 194 | data->fifo.init(data->deviceSpec.size * 4); 195 | _data = data; 196 | return (retro_microphone_t*)data; 197 | } 198 | 199 | void Microphone::closeMic(retro_microphone_t* microphone) 200 | { 201 | if ((SDLData*)microphone == _data) 202 | { 203 | SDL_CloseAudioDevice(_data->deviceId); 204 | _data->fifo.destroy(); 205 | 206 | if (_data->resampler != NULL) 207 | speex_resampler_destroy(_data->resampler); 208 | 209 | delete _data; 210 | _data = NULL; 211 | } 212 | } 213 | 214 | bool Microphone::getMicParams(const retro_microphone_t* microphone, retro_microphone_params_t* params) 215 | { 216 | if (!_data) 217 | return false; 218 | 219 | params->rate = _data->deviceSpec.freq; 220 | return true; 221 | } 222 | 223 | bool Microphone::getMicState(const retro_microphone_t* microphone) 224 | { 225 | return _data && _data->enabled; 226 | } 227 | 228 | bool Microphone::setMicState(retro_microphone_t* microphone, bool state) 229 | { 230 | if (!_data) 231 | return false; 232 | 233 | SDL_PauseAudioDevice(_data->deviceId, !state); 234 | if (state) 235 | { 236 | if (SDL_GetAudioDeviceStatus(_data->deviceId) != SDL_AUDIO_PLAYING) 237 | { 238 | _logger->warn(TAG "Failed to start microphone %u: %s", _data->deviceId, SDL_GetError()); 239 | return false; 240 | } 241 | } 242 | else 243 | { 244 | switch (SDL_GetAudioDeviceStatus(_data->deviceId)) 245 | { 246 | case SDL_AUDIO_PLAYING: 247 | _logger->warn(TAG "Failed to pause microphone %u: %s", _data->deviceId, SDL_GetError()); 248 | return false; 249 | case SDL_AUDIO_STOPPED: 250 | _logger->warn(TAG "Microphone %u has been stopped and may not start again: %s", _data->deviceId, SDL_GetError()); 251 | return false; 252 | default: 253 | break; 254 | } 255 | 256 | _data->fifo.reset(); 257 | } 258 | 259 | _data->enabled = state; 260 | return true; 261 | } 262 | 263 | int Microphone::readMic(retro_microphone_t* microphone, int16_t* frames, size_t num_frames) 264 | { 265 | if (!_data || !_data->enabled) 266 | return 0; 267 | 268 | size_t num_read = std::min(num_frames, _data->fifo.occupied() / sizeof(int16_t)); 269 | _data->fifo.read(frames, num_read * sizeof(int16_t)); 270 | return (int)num_read; 271 | } 272 | 273 | 274 | --------------------------------------------------------------------------------