mirror of
https://github.com/SourMesen/Mesen.git
synced 2024-06-02 03:18:48 -04:00
Libretro support (Linux)
This commit is contained in:
parent
cf0bd50b9e
commit
abffd86e6b
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
23
README.md
23
README.md
|
@ -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
|
||||
|
|
20
build.sh
20
build.sh
|
@ -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
|
||||
|
|
21
makefile
21
makefile
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue