Libretro support (Linux)

This commit is contained in:
Sour 2018-01-04 23:09:07 -05:00
parent cf0bd50b9e
commit abffd86e6b
11 changed files with 110 additions and 54 deletions

View file

@ -5,14 +5,14 @@
#include "EmulationSettings.h"
#include "PPU.h"
unique_ptr<IKeyManager> KeyManager::_keyManager;
IKeyManager* KeyManager::_keyManager;
MousePosition KeyManager::_mousePosition;
atomic<int16_t> KeyManager::_xMouseMovement;
atomic<int16_t> KeyManager::_yMouseMovement;
void KeyManager::RegisterKeyManager(IKeyManager* keyManager)
{
_keyManager.reset(keyManager);
_keyManager = keyManager;
}
void KeyManager::RefreshKeyState()

View file

@ -8,7 +8,7 @@ enum class MouseButton;
class KeyManager
{
private:
static unique_ptr<IKeyManager> _keyManager;
static IKeyManager* _keyManager;
static MousePosition _mousePosition;
static atomic<int16_t> _xMouseMovement;
static atomic<int16_t> _yMouseMovement;

View file

@ -8,15 +8,13 @@
class LibretroKeyManager : public IKeyManager
{
private:
retro_input_state_t _getInputState;
retro_input_poll_t _pollInput;
retro_input_state_t _getInputState = nullptr;
retro_input_poll_t _pollInput = nullptr;
bool _mouseButtons[3] = { false, false, false };
public:
LibretroKeyManager(retro_input_state_t getInputState, retro_input_poll_t pollInput)
LibretroKeyManager()
{
_getInputState = getInputState;
_pollInput = pollInput;
KeyManager::RegisterKeyManager(this);
}
@ -25,6 +23,16 @@ public:
KeyManager::RegisterKeyManager(nullptr);
}
void SetGetInputState(retro_input_state_t getInputState)
{
_getInputState = getInputState;
}
void SetPollInput(retro_input_poll_t pollInput)
{
_pollInput = pollInput;
}
// Inherited via IKeyManager
virtual void RefreshState() override
{
@ -32,44 +40,46 @@ public:
_pollInput();
}
int32_t x = _getInputState(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
int32_t y = _getInputState(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
if(_getInputState) {
int32_t x = _getInputState(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X);
int32_t y = _getInputState(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y);
x += 0x8000;
y += 0x8000;
x += 0x8000;
y += 0x8000;
KeyManager::SetMousePosition((double)x / 0x10000, (double)y / 0x10000);
KeyManager::SetMousePosition((double)x / 0x10000, (double)y / 0x10000);
int16_t dx = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
int16_t dy = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
KeyManager::SetMouseMovement(dx, dy);
_mouseButtons[(int)MouseButton::LeftButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) != 0;
_mouseButtons[(int)MouseButton::RightButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) != 0;
_mouseButtons[(int)MouseButton::MiddleButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE) != 0;
int16_t dx = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_X);
int16_t dy = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_Y);
KeyManager::SetMouseMovement(dx, dy);
_mouseButtons[(int)MouseButton::LeftButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT) != 0;
_mouseButtons[(int)MouseButton::RightButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT) != 0;
_mouseButtons[(int)MouseButton::MiddleButton] = _getInputState(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE) != 0;
shared_ptr<FdsSystemActionManager> fdsSam = Console::GetInstance()->GetSystemActionManager<FdsSystemActionManager>();
if(fdsSam) {
if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)) {
fdsSam->InsertNextDisk();
} else if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)) {
fdsSam->SwitchDiskSide();
shared_ptr<FdsSystemActionManager> fdsSam = Console::GetInstance()->GetSystemActionManager<FdsSystemActionManager>();
if(fdsSam) {
if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)) {
fdsSam->InsertNextDisk();
} else if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)) {
fdsSam->SwitchDiskSide();
}
}
}
shared_ptr<VsSystemActionManager> vsSam = Console::GetInstance()->GetSystemActionManager<VsSystemActionManager>();
if(vsSam) {
if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)) {
vsSam->InsertCoin(0);
} else if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)) {
vsSam->InsertCoin(1);
shared_ptr<VsSystemActionManager> vsSam = Console::GetInstance()->GetSystemActionManager<VsSystemActionManager>();
if(vsSam) {
if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)) {
vsSam->InsertCoin(0);
} else if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2)) {
vsSam->InsertCoin(1);
}
}
}
}
virtual bool IsKeyPressed(uint32_t keyCode) override
{
if(keyCode > 0) {
if(keyCode > 0 && _getInputState) {
return _getInputState(keyCode >> 8, RETRO_DEVICE_JOYPAD, 0, (keyCode - 1) & 0xFF) != 0;
} else {
return false;

View file

@ -11,9 +11,8 @@ private:
bool _skipMode = false;
public:
LibretroRenderer(retro_video_refresh_t sendFrame)
LibretroRenderer()
{
_sendFrame = sendFrame;
VideoRenderer::GetInstance()->RegisterRenderingDevice(this);
}
@ -25,11 +24,16 @@ public:
// Inherited via IRenderingDevice
virtual void UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height) override
{
if(!_skipMode) {
if(!_skipMode && _sendFrame) {
_sendFrame(frameBuffer, width, height, sizeof(uint32_t) * width);
}
}
void SetSendFrame(retro_video_refresh_t sendFrame)
{
_sendFrame = sendFrame;
}
void SetSkipMode(bool skip)
{
_skipMode = skip;

View file

@ -11,9 +11,8 @@ private:
bool _skipMode = false;
public:
LibretroSoundManager(retro_audio_sample_t sendAudioSample)
LibretroSoundManager()
{
_sendAudioSample = sendAudioSample;
SoundMixer::RegisterAudioDevice(this);
}
@ -25,13 +24,18 @@ public:
// Inherited via IAudioDevice
virtual void PlayBuffer(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate, bool isStereo) override
{
if(!_skipMode) {
if(!_skipMode && _sendAudioSample) {
for(uint32_t i = 0; i < sampleCount; i++) {
_sendAudioSample(soundBuffer[i * 2], soundBuffer[i * 2 + 1]);
}
}
}
void SetSendAudioSample(retro_audio_sample_t sendAudioSample)
{
_sendAudioSample = sendAudioSample;
}
void SetSkipMode(bool skip)
{
_skipMode = skip;

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -31,32 +31,45 @@ Things that ***may or may not*** be added in the future, in no particular order:
-Support for more UNIF boards and more NES/Famicom input devices
-Debugger improvements (APU state display, etc.)
-Shaders
-Libretro support
-TAS editor
# Compiling #
### Windows ###
1) Open the solution in VS2015/2017
#### *Standalone* ####
1) Open the solution in VS2017
2) Compile as Release/x64 or Release/x86
3) Run
#### *Libretro* ####
1) Open the solution in VS2017
2) Compile as Release/x64 or Release/x86
3) Use the "mesen_libretro.dll" file in bin/(x64 or x86)/Libretro/mesen_libretro.dll
### Linux ###
To compile and run Mesen under Linux, you will need:
* A recent version of clang/gcc
#### *Standalone* ####
To compile and run Mesen under Linux a recent version of clang/gcc. Mesen requires a C++14, along with support for the filesystem API. Additionally, Mesen requires the following dependencies:
* Mono 4.2.1+ (package: mono-devel)
* SDL2 (package: libsdl2-dev)
The makefile contains some more information at the top. Running "make" will build the x64 version by default, and then "make run" should start the emulator.
LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details).
#### *Libretro* ####
To compile the libretro core you will need a recent version of clang/gcc. Mesen requires a C++14, along with support for the filesystem API.
Running "make libretro" will build the core and put it in "bin/mesen_libretro.(x64 or x86).so"
## LICENSE ##
Mesen is available under the GPL V3 license. Full text here: http://www.gnu.org/licenses/gpl-3.0.en.html
Copyright (C) 2017 M. Bibaud
Copyright (C) 2014-2018 M. Bibaud
This program is free software: you can redistribute it and/or modify

View file

@ -3,11 +3,19 @@
#This is a build script used for official releases which does not build the UI
#Read the makefile and use "make" to build Mesen normally
MESENPLATFORM=x64 make clean
LTO=true MESENPLATFORM=x64 make core -j 16
if [ "$1" = libretro ]; then
MESENPLATFORM=x64 make clean
LTO=true MESENPLATFORM=x64 make libretro -j 16
MESENPLATFORM=x86 make clean
LTO=true MESENPLATFORM=x86 make core -j 16
MESENPLATFORM=x86 make clean
LTO=true MESENPLATFORM=x86 make libretro -j 16
else
MESENPLATFORM=x64 make clean
LTO=true MESENPLATFORM=x64 make core -j 16
cp ./InteropDLL/obj.x64/libMesenCore.x64.dll ./bin
cp ./InteropDLL/obj.x86/libMesenCore.x86.dll ./bin
MESENPLATFORM=x86 make clean
LTO=true MESENPLATFORM=x86 make core -j 16
cp ./InteropDLL/obj.x64/libMesenCore.x64.dll ./bin
cp ./InteropDLL/obj.x86/libMesenCore.x86.dll ./bin
fi

View file

@ -17,11 +17,14 @@
#LTO gives a 25-30% performance boost, so use it whenever you can
#Usage: LTO=true make
MESENFLAGS=
libretro : MESENFLAGS=-D LIBRETRO
CPPC=clang++
GCCOPTIONS=-fPIC -Wall --std=c++14 -O3
GCCOPTIONS=-fPIC -Wall --std=c++14 -O3 $(MESENFLAGS)
CC=clang
CCOPTIONS=-fPIC -Wall -O3
CCOPTIONS=-fPIC -Wall -O3 $(MESENFLAGS)
AR=ar -rcs
LINKFLAG=
@ -46,6 +49,7 @@ endif
OBJFOLDER=obj.$(MESENPLATFORM)
SHAREDLIB=libMesenCore.$(MESENPLATFORM).dll
LIBRETROLIB=mesen_libretro.$(MESENPLATFORM).so
RELEASEFOLDER=bin/$(MESENPLATFORM)/Release
COREOBJ=$(patsubst Core/%.cpp,Core/$(OBJFOLDER)/%.o,$(wildcard Core/*.cpp))
@ -68,6 +72,9 @@ ui: InteropDLL/$(OBJFOLDER)/$(SHAREDLIB)
cd $(RELEASEFOLDER)/Dependencies && zip ../Dependencies.zip *
cd GUI.NET && xbuild /property:Configuration="Release" /property:Platform="$(MESENPLATFORM)" /property:PreBuildEvent="" /property:DefineConstants="HIDETESTMENU,DISABLEAUTOUPDATE"
libretro: Libretro/$(OBJFOLDER)/$(LIBRETROLIB)
cp ./Libretro/$(OBJFOLDER)/$(LIBRETROLIB) ./bin
core: InteropDLL/$(OBJFOLDER)/$(SHAREDLIB)
runtests:
@ -115,6 +122,15 @@ InteropDLL/$(OBJFOLDER)/$(SHAREDLIB): $(SEVENZIPOBJ) $(LUAOBJ) $(UTILOBJ) $(CORE
$(AR) InteropDLL/$(OBJFOLDER)/libCore.a $(COREOBJ)
cd InteropDLL/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) $(LINKFLAG) -Wl,-z,defs -Wno-parentheses -Wno-switch -shared -o $(SHAREDLIB) ../*.cpp -L . -lMesenLinux -lCore -lUtilities -lLua -lSevenZip -pthread -lSDL2 -lstdc++fs
Libretro/$(OBJFOLDER)/$(LIBRETROLIB): $(SEVENZIPOBJ) $(LUAOBJ) $(UTILOBJ) $(COREOBJ) Libretro/libretro.cpp
mkdir -p Libretro/$(OBJFOLDER)
$(AR) Libretro/$(OBJFOLDER)/libSevenZip.a $(SEVENZIPOBJ)
$(AR) Libretro/$(OBJFOLDER)/libLua.a $(LUAOBJ)
$(AR) Libretro/$(OBJFOLDER)/libUtilities.a $(UTILOBJ)
$(AR) Libretro/$(OBJFOLDER)/libCore.a $(COREOBJ)
cd Libretro/$(OBJFOLDER) && $(CPPC) $(GCCOPTIONS) $(LINKFLAG) -Wl,-z,defs -Wno-parentheses -Wno-switch -shared -o $(LIBRETROLIB) ../*.cpp -L . -lCore -lUtilities -lLua -lSevenZip -pthread -lstdc++fs
debug:
MONO_LOG_LEVEL=debug mono $(RELEASEFOLDER)/Mesen.exe
@ -128,5 +144,6 @@ clean:
rm Core/$(OBJFOLDER) -r -f
rm Linux/$(OBJFOLDER) -r -f
rm InteropDLL/$(OBJFOLDER) -r -f
rm Libretro/$(OBJFOLDER) -r -f
rm TestHelper/$(OBJFOLDER) -r -f
rm $(RELEASEFOLDER) -r -f