mirror of
https://github.com/libretro/Mesen-S.git
synced 2024-11-27 02:20:34 +00:00
Libretro: Added libretro core
This commit is contained in:
parent
f9e08d2c24
commit
b5847a3d1f
1
.gitignore
vendored
1
.gitignore
vendored
@ -182,6 +182,5 @@ packages/*
|
||||
|
||||
!Libretro/hakchi/bin
|
||||
|
||||
Libretro/*
|
||||
Docs/*
|
||||
TestHelper/*
|
||||
|
18
COMPILING.md
18
COMPILING.md
@ -1,9 +1,16 @@
|
||||
### Windows
|
||||
|
||||
1) Open the solution in VS2017
|
||||
2) Compile as Release/x64 or Release/x86
|
||||
2) Compile as Release/x64
|
||||
3) Run
|
||||
|
||||
#### *Libretro*
|
||||
|
||||
1) Open the solution in VS2017
|
||||
2) Compile as Libretro/x64
|
||||
3) Use the "mesen-s_libretro.dll" file in bin/(x64 or x86)/Libretro/mesen-s_libretro.dll
|
||||
|
||||
|
||||
### Linux
|
||||
|
||||
To compile Mesen-S under Linux you will need a recent version of clang/gcc. This is because Mesen-S requires a C++14 compiler, along with support for the filesystem API (C++17). Additionally, Mesen-S has the following dependencies:
|
||||
@ -20,3 +27,12 @@ LTO is supported under clang, which gives a large performance boost (25-30%+), s
|
||||
Examples:
|
||||
`LTO=true make` will compile with clang and LTO.
|
||||
`USE_GCC=true LTO=true make` will compile with gcc and LTO.
|
||||
|
||||
#### *Libretro*
|
||||
|
||||
To compile the libretro core you will need a recent version of clang/gcc. This is because Mesen-S requires a C++14 compiler, along with support for the filesystem API (C++17).
|
||||
|
||||
Running "make libretro" will build the core and put it in "bin/mesen-s_libretro.(x64 or x86).so".
|
||||
LTO is supported under clang, which gives a large performance boost (25-30%+), so turning it on is highly recommended (see makefile for details).
|
||||
|
||||
**Note:** There is also another makefile in the Libretro folder - this is used by the RetroArch buildbot to build the core. You can also try using this makefile if you are having issues with the one in the root folder.
|
||||
|
@ -132,6 +132,19 @@ void Console::Run()
|
||||
PlatformUtilities::RestoreTimerResolution();
|
||||
}
|
||||
|
||||
void Console::RunSingleFrame()
|
||||
{
|
||||
//Used by Libretro
|
||||
uint32_t lastFrameNumber = _ppu->GetFrameCount();
|
||||
_emulationThreadId = std::this_thread::get_id();
|
||||
|
||||
while(_ppu->GetFrameCount() == lastFrameNumber) {
|
||||
_cpu->Exec();
|
||||
}
|
||||
|
||||
_controlManager->UpdateControlDevices();
|
||||
}
|
||||
|
||||
void Console::Stop(bool sendNotification)
|
||||
{
|
||||
_stopFlag = true;
|
||||
@ -213,6 +226,7 @@ void Console::PowerCycle()
|
||||
RomInfo info = cart->GetRomInfo();
|
||||
Lock();
|
||||
LoadRom(info.RomFile, info.PatchFile, false);
|
||||
_memoryManager->IncrementMasterClockValue<182>();
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
@ -229,15 +243,6 @@ bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom)
|
||||
if(stopRom) {
|
||||
Stop(false);
|
||||
}
|
||||
|
||||
vector<uint8_t> spcRomData;
|
||||
VirtualFile spcBios(FolderUtilities::CombinePath(FolderUtilities::GetHomeFolder(), "spc700.rom"));
|
||||
if(spcBios.IsValid()) {
|
||||
spcBios.ReadFile(spcRomData);
|
||||
} else {
|
||||
MessageManager::DisplayMessage("SPC", "spc700.rom not found, cannot launch game.");
|
||||
return false;
|
||||
}
|
||||
|
||||
_cart = cart;
|
||||
UpdateRegion();
|
||||
@ -247,7 +252,7 @@ bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom)
|
||||
_internalRegisters.reset(new InternalRegisters(shared_from_this()));
|
||||
_controlManager.reset(new ControlManager(shared_from_this()));
|
||||
_dmaController.reset(new DmaController(_memoryManager.get()));
|
||||
_spc.reset(new Spc(shared_from_this(), spcRomData));
|
||||
_spc.reset(new Spc(shared_from_this()));
|
||||
|
||||
_memoryManager->Initialize(shared_from_this());
|
||||
|
||||
|
@ -74,6 +74,7 @@ public:
|
||||
void Release();
|
||||
|
||||
void Run();
|
||||
void RunSingleFrame();
|
||||
void Stop(bool sendNotification);
|
||||
|
||||
void Reset();
|
||||
|
@ -12,10 +12,9 @@
|
||||
|
||||
#include "Spc.h"
|
||||
|
||||
DummySpc::DummySpc(uint8_t *spcRam, uint8_t *spcRom, SpcState &state)
|
||||
DummySpc::DummySpc(uint8_t *spcRam, SpcState &state)
|
||||
{
|
||||
_ram = spcRam;
|
||||
_spcBios = spcRom;
|
||||
|
||||
_opCode = 0;
|
||||
_opStep = SpcOpStep::ReadOpCode;
|
||||
@ -34,7 +33,6 @@ DummySpc::DummySpc(uint8_t *spcRam, uint8_t *spcRom, SpcState &state)
|
||||
DummySpc::~DummySpc()
|
||||
{
|
||||
_ram = nullptr;
|
||||
_spcBios = nullptr;
|
||||
}
|
||||
|
||||
void DummySpc::Step()
|
||||
|
@ -13,14 +13,27 @@ EmuSettings::EmuSettings()
|
||||
|
||||
uint32_t EmuSettings::GetVersion()
|
||||
{
|
||||
//0.1.0
|
||||
return 0x00000100;
|
||||
//Version 0.1.0
|
||||
uint16_t major = 0;
|
||||
uint8_t minor = 1;
|
||||
uint8_t revision = 0;
|
||||
return (major << 16) | (minor << 8) | revision;
|
||||
}
|
||||
|
||||
string EmuSettings::GetVersionString()
|
||||
{
|
||||
uint32_t version = GetVersion();
|
||||
return std::to_string(version >> 16) + "." + std::to_string((version >> 8) & 0xFF) + "." + std::to_string(version & 0xFF);
|
||||
}
|
||||
|
||||
void EmuSettings::ProcessString(string & str, const char ** strPointer)
|
||||
{
|
||||
//Make a copy of the string and keep it (the original pointer will not be valid after the call is over)
|
||||
str = *strPointer;
|
||||
if(*strPointer) {
|
||||
str = *strPointer;
|
||||
} else {
|
||||
str.clear();
|
||||
}
|
||||
*strPointer = str.c_str();
|
||||
}
|
||||
|
||||
@ -180,17 +193,11 @@ uint32_t EmuSettings::GetEmulationSpeed()
|
||||
}
|
||||
}
|
||||
|
||||
double EmuSettings::GetAspectRatio()
|
||||
double EmuSettings::GetAspectRatio(ConsoleRegion region)
|
||||
{
|
||||
switch(_video.AspectRatio) {
|
||||
case VideoAspectRatio::NoStretching: return 0.0;
|
||||
|
||||
case VideoAspectRatio::Auto:
|
||||
{
|
||||
bool isPal = false;
|
||||
return isPal ? (9440000.0 / 6384411.0) : (128.0 / 105.0);
|
||||
}
|
||||
|
||||
case VideoAspectRatio::Auto: return region == ConsoleRegion::Pal ? (9440000.0 / 6384411.0) : (128.0 / 105.0);
|
||||
case VideoAspectRatio::NTSC: return 128.0 / 105.0;
|
||||
case VideoAspectRatio::PAL: return 9440000.0 / 6384411.0;
|
||||
case VideoAspectRatio::Standard: return 4.0 / 3.0;
|
||||
|
@ -31,7 +31,9 @@ private:
|
||||
|
||||
public:
|
||||
EmuSettings();
|
||||
|
||||
uint32_t GetVersion();
|
||||
string GetVersionString();
|
||||
|
||||
void SetVideoConfig(VideoConfig config);
|
||||
VideoConfig GetVideoConfig();
|
||||
@ -56,7 +58,7 @@ public:
|
||||
OverscanDimensions GetOverscan();
|
||||
uint32_t GetRewindBufferSize();
|
||||
uint32_t GetEmulationSpeed();
|
||||
double GetAspectRatio();
|
||||
double GetAspectRatio(ConsoleRegion region);
|
||||
|
||||
void SetFlag(EmulationFlags flag);
|
||||
void SetFlagState(EmulationFlags flag, bool enabled);
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef LIBRETRO
|
||||
#include "LuaApi.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
@ -703,3 +705,4 @@ int LuaApi::GetState(lua_State *lua)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
@ -1,4 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#ifndef LIBRETRO
|
||||
#include "LuaCallHelper.h"
|
||||
|
||||
LuaCallHelper::LuaCallHelper(lua_State *lua) : _lua(lua)
|
||||
@ -145,3 +146,5 @@ int LuaCallHelper::ReturnCount()
|
||||
{
|
||||
return _returnCount;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,4 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifndef LIBRETRO
|
||||
#include "../Lua/lua.hpp"
|
||||
#include "../Lua/luasocket.hpp"
|
||||
#include "LuaScriptingContext.h"
|
||||
@ -155,3 +157,4 @@ int LuaScriptingContext::InternalCallEventCallback(EventType type)
|
||||
}
|
||||
return l.ReturnCount();
|
||||
}
|
||||
#endif
|
@ -1163,6 +1163,9 @@ void Ppu::SendFrame()
|
||||
}
|
||||
|
||||
bool isRewinding = _console->GetRewindManager()->IsRewinding();
|
||||
#ifdef LIBRETRO
|
||||
_console->GetVideoDecoder()->UpdateFrameSync(_currentBuffer, width, height, _frameCount, isRewinding);
|
||||
#else
|
||||
if(isRewinding || _screenInterlace) {
|
||||
_console->GetVideoDecoder()->UpdateFrameSync(_currentBuffer, width, height, _frameCount, isRewinding);
|
||||
} else {
|
||||
@ -1172,6 +1175,7 @@ void Ppu::SendFrame()
|
||||
_currentBuffer = _currentBuffer == _outputBuffers[0] ? _outputBuffers[1] : _outputBuffers[0];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t* Ppu::GetScreenBuffer()
|
||||
|
@ -6,16 +6,13 @@
|
||||
#include "SPC_DSP.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
Spc::Spc(shared_ptr<Console> console, vector<uint8_t> &spcRomData)
|
||||
Spc::Spc(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
_memoryManager = console->GetMemoryManager();
|
||||
_soundBuffer = new int16_t[Spc::SampleBufferSize];
|
||||
|
||||
_ram = new uint8_t[Spc::SpcRamSize];
|
||||
_spcBios = new uint8_t[Spc::SpcRomSize];
|
||||
|
||||
memcpy(_spcBios, spcRomData.data(), Spc::SpcRomSize);
|
||||
memset(_ram, 0, Spc::SpcRamSize);
|
||||
|
||||
_dsp.reset(new SPC_DSP());
|
||||
@ -47,7 +44,6 @@ Spc::~Spc()
|
||||
{
|
||||
delete[] _soundBuffer;
|
||||
delete[] _ram;
|
||||
delete[] _spcBios;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
15
Core/Spc.h
15
Core/Spc.h
@ -44,7 +44,16 @@ private:
|
||||
|
||||
SpcState _state;
|
||||
uint8_t* _ram;
|
||||
uint8_t* _spcBios;
|
||||
uint8_t _spcBios[64] {
|
||||
0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
|
||||
0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
|
||||
0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19, 0xEB, 0xF4,
|
||||
0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5,
|
||||
0xCB, 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB,
|
||||
0x01, 0x10, 0xEF, 0x7E, 0xF4, 0x10, 0xEB, 0xBA,
|
||||
0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4, 0xDD,
|
||||
0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF
|
||||
};
|
||||
|
||||
int16_t *_soundBuffer;
|
||||
|
||||
@ -268,7 +277,7 @@ private:
|
||||
void Exec();
|
||||
|
||||
public:
|
||||
Spc(shared_ptr<Console> console, vector<uint8_t> &spcRomData);
|
||||
Spc(shared_ptr<Console> console);
|
||||
virtual ~Spc();
|
||||
|
||||
void Run();
|
||||
@ -305,7 +314,7 @@ private:
|
||||
void LogWrite(uint32_t addr, uint8_t value);
|
||||
|
||||
public:
|
||||
DummySpc(uint8_t *spcRam, uint8_t *spcRom, SpcState &state);
|
||||
DummySpc(uint8_t *spcRam, SpcState &state);
|
||||
|
||||
void Step();
|
||||
|
||||
|
@ -131,7 +131,7 @@ int32_t SpcDisUtils::GetEffectiveAddress(DisassemblyInfo &info, Console *console
|
||||
{
|
||||
if(_needAddress[info.GetOpCode()]) {
|
||||
Spc* spc = console->GetSpc().get();
|
||||
DummySpc dummySpc(spc->GetSpcRam(), spc->GetSpcRom(), state);
|
||||
DummySpc dummySpc(spc->GetSpcRam(), state);
|
||||
dummySpc.Step();
|
||||
uint32_t addr;
|
||||
uint8_t value;
|
||||
|
@ -39,7 +39,7 @@ ScreenSize VideoDecoder::GetScreenSize(bool ignoreScale)
|
||||
ScreenSize size;
|
||||
OverscanDimensions overscan = ignoreScale ? _videoFilter->GetOverscan() : _console->GetSettings()->GetOverscan();
|
||||
FrameInfo frameInfo = _videoFilter->GetFrameInfo();
|
||||
double aspectRatio = _console->GetSettings()->GetAspectRatio();
|
||||
double aspectRatio = _console->GetSettings()->GetAspectRatio(_console->GetRegion());
|
||||
double scale = (ignoreScale ? 1 : _console->GetSettings()->GetVideoConfig().VideoScale);
|
||||
size.Width = (int32_t)(frameInfo.Width * scale / 2);
|
||||
size.Height = (int32_t)(frameInfo.Height * scale / 2);
|
||||
|
5
Libretro/.gitignore
vendored
Normal file
5
Libretro/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*.a
|
||||
*.so
|
||||
*.dylib
|
||||
*.bc
|
||||
*.dll
|
265
Libretro/Libretro.vcxproj
Normal file
265
Libretro/Libretro.vcxproj
Normal file
@ -0,0 +1,265 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Libretro|Win32">
|
||||
<Configuration>Libretro</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Libretro|x64">
|
||||
<Configuration>Libretro</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{4432139E-528B-44DE-961C-B37CD5E92E0E}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Libretro</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>Libretro</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>mesen-s_libretro</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>mesen-s_libretro</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>mesen-s_libretro</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>mesen-s_libretro</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>mesen-s_libretro</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)\bin\$(PlatformTarget)\$(Configuration)\</OutDir>
|
||||
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>mesen-s_libretro</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;LIBRETRO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;LIBRETRO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>Core.lib;Utilities.lib;SevenZip.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;LIBRETRO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;LIBRETRO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;LIBRETRO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Libretro|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;LIBRETRO_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<DisableLanguageExtensions>true</DisableLanguageExtensions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>Core.lib;Utilities.lib;SevenZip.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libretro.h" />
|
||||
<ClInclude Include="LibretroKeyManager.h" />
|
||||
<ClInclude Include="LibretroMessageManager.h" />
|
||||
<ClInclude Include="LibretroRenderer.h" />
|
||||
<ClInclude Include="LibretroSoundManager.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libretro.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
13
Libretro/Libretro.vcxproj.filters
Normal file
13
Libretro/Libretro.vcxproj.filters
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClInclude Include="libretro.h" />
|
||||
<ClInclude Include="LibretroKeyManager.h" />
|
||||
<ClInclude Include="LibretroMessageManager.h" />
|
||||
<ClInclude Include="LibretroRenderer.h" />
|
||||
<ClInclude Include="LibretroSoundManager.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="libretro.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
122
Libretro/LibretroKeyManager.h
Normal file
122
Libretro/LibretroKeyManager.h
Normal file
@ -0,0 +1,122 @@
|
||||
#pragma once
|
||||
#include "libretro.h"
|
||||
#include "../Core/IKeyManager.h"
|
||||
#include "../Core/KeyManager.h"
|
||||
#include "../Core/Console.h"
|
||||
|
||||
class LibretroKeyManager : public IKeyManager
|
||||
{
|
||||
private:
|
||||
shared_ptr<Console> _console;
|
||||
retro_input_state_t _getInputState = nullptr;
|
||||
retro_input_poll_t _pollInput = nullptr;
|
||||
bool _mouseButtons[3] = { false, false, false };
|
||||
bool _wasPushed[16] = { };
|
||||
|
||||
bool ProcessAction(uint32_t button)
|
||||
{
|
||||
if(_getInputState(0, RETRO_DEVICE_JOYPAD, 0, button)) {
|
||||
if(!_wasPushed[button]) {
|
||||
//Newly pressed, process action
|
||||
_wasPushed[button] = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
_wasPushed[button] = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
LibretroKeyManager(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
KeyManager::RegisterKeyManager(this);
|
||||
}
|
||||
|
||||
~LibretroKeyManager()
|
||||
{
|
||||
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
|
||||
{
|
||||
if(_pollInput) {
|
||||
_pollInput();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
KeyManager::SetMousePosition(_console, (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;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool IsKeyPressed(uint32_t keyCode) override
|
||||
{
|
||||
if(keyCode > 0 && _getInputState) {
|
||||
return _getInputState(keyCode >> 8, RETRO_DEVICE_JOYPAD, 0, (keyCode - 1) & 0xFF) != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void UpdateDevices() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool IsMouseButtonPressed(MouseButton button) override
|
||||
{
|
||||
return _mouseButtons[(int)button];
|
||||
}
|
||||
|
||||
virtual vector<uint32_t> GetPressedKeys() override
|
||||
{
|
||||
return vector<uint32_t>();
|
||||
}
|
||||
|
||||
virtual string GetKeyName(uint32_t keyCode) override
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
virtual uint32_t GetKeyCode(string keyName) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void SetKeyState(uint16_t scanCode, bool state) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ResetKeyState() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void SetDisabled(bool disabled) override
|
||||
{
|
||||
}
|
||||
};
|
38
Libretro/LibretroMessageManager.h
Normal file
38
Libretro/LibretroMessageManager.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "libretro.h"
|
||||
#include "../Core/IMessageManager.h"
|
||||
#include "../Core/MessageManager.h"
|
||||
|
||||
class LibretroMessageManager : public IMessageManager
|
||||
{
|
||||
private:
|
||||
retro_log_printf_t _log = nullptr;
|
||||
retro_environment_t _retroEnv = nullptr;
|
||||
|
||||
public:
|
||||
LibretroMessageManager(retro_log_printf_t logCallback, retro_environment_t retroEnv)
|
||||
{
|
||||
_log = logCallback;
|
||||
_retroEnv = retroEnv;
|
||||
MessageManager::RegisterMessageManager(this);
|
||||
}
|
||||
|
||||
virtual ~LibretroMessageManager()
|
||||
{
|
||||
MessageManager::RegisterMessageManager(nullptr);
|
||||
}
|
||||
|
||||
// Inherited via IMessageManager
|
||||
virtual void DisplayMessage(string title, string message) override
|
||||
{
|
||||
if(title.empty()) {
|
||||
if(_log) {
|
||||
_log(RETRO_LOG_INFO, message.c_str());
|
||||
}
|
||||
} else {
|
||||
string osdMessage = "[" + title + "] " + message;
|
||||
retro_message msg = { osdMessage.c_str(), 180 };
|
||||
_retroEnv(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
|
||||
}
|
||||
}
|
||||
};
|
104
Libretro/LibretroRenderer.h
Normal file
104
Libretro/LibretroRenderer.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
#include "../Core/IRenderingDevice.h"
|
||||
#include "../Core/VideoRenderer.h"
|
||||
#include "../Core/EmuSettings.h"
|
||||
#include "../Core/Console.h"
|
||||
#include "../Utilities/snes_ntsc.h"
|
||||
#include "libretro.h"
|
||||
|
||||
class LibretroRenderer : public IRenderingDevice
|
||||
{
|
||||
private:
|
||||
shared_ptr<Console> _console;
|
||||
retro_video_refresh_t _sendFrame = nullptr;
|
||||
retro_environment_t _retroEnv = nullptr;
|
||||
bool _skipMode = false;
|
||||
int32_t _previousHeight = -1;
|
||||
int32_t _previousWidth = -1;
|
||||
|
||||
public:
|
||||
LibretroRenderer(shared_ptr<Console> console, retro_environment_t retroEnv)
|
||||
{
|
||||
_console = console;
|
||||
_retroEnv = retroEnv;
|
||||
_console->GetVideoRenderer()->RegisterRenderingDevice(this);
|
||||
}
|
||||
|
||||
~LibretroRenderer()
|
||||
{
|
||||
_console->GetVideoRenderer()->UnregisterRenderingDevice(this);
|
||||
}
|
||||
|
||||
// Inherited via IRenderingDevice
|
||||
virtual void UpdateFrame(void *frameBuffer, uint32_t width, uint32_t height) override
|
||||
{
|
||||
if(!_skipMode && _sendFrame) {
|
||||
//Use Blargg's NTSC filter's max size as a minimum resolution, to prevent changing resolution too often
|
||||
int32_t newWidth = std::max<int32_t>(width, SNES_NTSC_OUT_WIDTH(256));
|
||||
int32_t newHeight = std::max<int32_t>(height, 240);
|
||||
if(_retroEnv != nullptr && (_previousWidth != newWidth || _previousHeight != newHeight)) {
|
||||
//Resolution change is needed
|
||||
retro_system_av_info avInfo = {};
|
||||
GetSystemAudioVideoInfo(avInfo, newWidth, newHeight);
|
||||
_retroEnv(RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO, &avInfo);
|
||||
|
||||
_previousWidth = newWidth;
|
||||
_previousHeight = newHeight;
|
||||
}
|
||||
|
||||
_sendFrame(frameBuffer, width, height, sizeof(uint32_t) * width);
|
||||
}
|
||||
}
|
||||
|
||||
void GetSystemAudioVideoInfo(retro_system_av_info &info, int32_t maxWidth = 0, int32_t maxHeight = 0)
|
||||
{
|
||||
AudioConfig audio = _console->GetSettings()->GetAudioConfig();
|
||||
EmulationConfig emulation = _console->GetSettings()->GetEmulationConfig();
|
||||
|
||||
info.timing.fps = emulation.Region == ConsoleRegion::Ntsc ? 60.098811862348404716732985230828 : 50.006977968268290848936010226333;
|
||||
info.timing.sample_rate = audio.SampleRate;
|
||||
|
||||
float ratio = (float)_console->GetSettings()->GetAspectRatio(_console->GetRegion());
|
||||
if(ratio == 0.0f) {
|
||||
ratio = (float)256 / 239;
|
||||
}
|
||||
OverscanDimensions overscan = _console->GetSettings()->GetOverscan();
|
||||
int width = (256 - overscan.Left - overscan.Right) * 2;
|
||||
int height = (239 - overscan.Top - overscan.Bottom) * 2;
|
||||
ratio *= (float)width / height / 256 * 239;
|
||||
|
||||
info.geometry.aspect_ratio = ratio;
|
||||
info.geometry.base_width = width;
|
||||
info.geometry.base_height = height;
|
||||
|
||||
info.geometry.max_width = maxWidth;
|
||||
info.geometry.max_height = maxHeight;
|
||||
|
||||
if(maxHeight > 0 && maxWidth > 0) {
|
||||
_previousWidth = maxWidth;
|
||||
_previousHeight = maxHeight;
|
||||
}
|
||||
}
|
||||
|
||||
void SetVideoCallback(retro_video_refresh_t sendFrame)
|
||||
{
|
||||
_sendFrame = sendFrame;
|
||||
}
|
||||
|
||||
void SetSkipMode(bool skip)
|
||||
{
|
||||
_skipMode = skip;
|
||||
}
|
||||
|
||||
virtual void Render() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Reset() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void SetFullscreenMode(bool fullscreen, void *windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) override
|
||||
{
|
||||
}
|
||||
};
|
70
Libretro/LibretroSoundManager.h
Normal file
70
Libretro/LibretroSoundManager.h
Normal file
@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
#include "../Core/IAudioDevice.h"
|
||||
#include "../Core/SoundMixer.h"
|
||||
#include "libretro.h"
|
||||
|
||||
class LibretroSoundManager : public IAudioDevice
|
||||
{
|
||||
private:
|
||||
retro_audio_sample_t _sendAudioSample = nullptr;
|
||||
bool _skipMode = false;
|
||||
shared_ptr<Console> _console;
|
||||
|
||||
public:
|
||||
LibretroSoundManager(shared_ptr<Console> console)
|
||||
{
|
||||
_console = console;
|
||||
_console->GetSoundMixer()->RegisterAudioDevice(this);
|
||||
}
|
||||
|
||||
~LibretroSoundManager()
|
||||
{
|
||||
_console->GetSoundMixer()->RegisterAudioDevice(nullptr);
|
||||
}
|
||||
|
||||
// Inherited via IAudioDevice
|
||||
virtual void PlayBuffer(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate, bool isStereo) override
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
virtual void Stop() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Pause() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual string GetAvailableDevices() override
|
||||
{
|
||||
return string();
|
||||
}
|
||||
|
||||
virtual void SetAudioDevice(string deviceName) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ProcessEndOfFrame() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual AudioStatistics GetStatistics() override
|
||||
{
|
||||
return AudioStatistics();
|
||||
}
|
||||
};
|
323
Libretro/Makefile
Normal file
323
Libretro/Makefile
Normal file
@ -0,0 +1,323 @@
|
||||
STATIC_LINKING := 0
|
||||
AR := ar
|
||||
|
||||
SPACE :=
|
||||
SPACE := $(SPACE) $(SPACE)
|
||||
BACKSLASH :=
|
||||
BACKSLASH := \$(BACKSLASH)
|
||||
filter_out1 = $(filter-out $(firstword $1),$1)
|
||||
filter_out2 = $(call filter_out1,$(call filter_out1,$1))
|
||||
|
||||
ifeq ($(platform),)
|
||||
platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
platform = win
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
platform = osx
|
||||
else ifneq ($(findstring win,$(shell uname -a)),)
|
||||
platform = win
|
||||
endif
|
||||
endif
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
arch = intel
|
||||
ifeq ($(shell uname -p),powerpc)
|
||||
arch = ppc
|
||||
endif
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
LIBRETRO_DIR += .
|
||||
SEVENZIP_DIR += ../SevenZip
|
||||
CORE_DIR += ../Core
|
||||
UTIL_DIR += ../Utilities
|
||||
|
||||
TARGET_NAME := mesen-s
|
||||
LIBM = -lm
|
||||
|
||||
ifeq ($(ARCHFLAGS),)
|
||||
ifeq ($(archs),ppc)
|
||||
ARCHFLAGS = -arch ppc -arch ppc64
|
||||
else
|
||||
ARCHFLAGS = -arch i386 -arch x86_64
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(platform), osx)
|
||||
ifndef ($(NOUNIVERSAL))
|
||||
CXXFLAGS += $(ARCHFLAGS)
|
||||
LFLAGS += $(ARCHFLAGS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC_LINKING), 1)
|
||||
EXT := a
|
||||
endif
|
||||
|
||||
ifeq ($(platform), unix)
|
||||
EXT ?= so
|
||||
TARGET := $(TARGET_NAME)_libretro.$(EXT)
|
||||
fpic := -fPIC -pthread
|
||||
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||
|
||||
else ifeq ($(platform), linux-portable)
|
||||
TARGET := $(TARGET_NAME)_libretro.$(EXT)
|
||||
fpic := -fPIC -nostdlib
|
||||
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T
|
||||
LIBM :=
|
||||
|
||||
# Classic Platforms ####################
|
||||
# Platform affix = classic_<ISA>_<µARCH>
|
||||
# Help at https://modmyclassic.com/comp
|
||||
|
||||
# (armv7 a7, hard point, neon based) ###
|
||||
# NESC, SNESC, C64 mini
|
||||
else ifeq ($(platform), classic_armv7_a7)
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
fpic := -fPIC -pthread
|
||||
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||
CFLAGS += -Ofast \
|
||||
-flto=4 -fwhole-program -fuse-linker-plugin \
|
||||
-fdata-sections -ffunction-sections -Wl,--gc-sections \
|
||||
-fno-stack-protector -fno-ident -fomit-frame-pointer \
|
||||
-falign-functions=1 -falign-jumps=1 -falign-loops=1 \
|
||||
-fno-unwind-tables -fno-asynchronous-unwind-tables -fno-unroll-loops \
|
||||
-fmerge-all-constants -fno-math-errno \
|
||||
-marm -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
CPPFLAGS += $(CFLAGS)
|
||||
ASFLAGS += $(CFLAGS)
|
||||
HAVE_NEON = 1
|
||||
ARCH = arm
|
||||
BUILTIN_GPU = neon
|
||||
USE_DYNAREC = 1
|
||||
ifeq ($(shell echo `$(CC) -dumpversion` "< 4.9" | bc -l), 1)
|
||||
CFLAGS += -march=armv7-a
|
||||
else
|
||||
CFLAGS += -march=armv7ve
|
||||
# If gcc is 5.0 or later
|
||||
ifeq ($(shell echo `$(CC) -dumpversion` ">= 5" | bc -l), 1)
|
||||
LDFLAGS += -static-libgcc -static-libstdc++
|
||||
endif
|
||||
endif
|
||||
#######################################
|
||||
|
||||
else ifneq (,$(findstring osx,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
else ifneq (,$(findstring ios,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro_ios.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
|
||||
ifeq ($(IOSSDK),)
|
||||
IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path)
|
||||
endif
|
||||
|
||||
DEFINES := -DIOS
|
||||
CC = cc -arch armv7 -isysroot $(IOSSDK)
|
||||
ifeq ($(platform),ios9)
|
||||
CC += -miphoneos-version-min=8.0
|
||||
CXXFLAGS += -miphoneos-version-min=8.0
|
||||
else
|
||||
CC += -miphoneos-version-min=5.0
|
||||
CXXFLAGS += -miphoneos-version-min=5.0
|
||||
endif
|
||||
else ifneq (,$(findstring qnx,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro_qnx.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||
else ifeq ($(platform), emscripten)
|
||||
TARGET := $(TARGET_NAME)_libretro_emscripten.bc
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||
else ifeq ($(platform), vita)
|
||||
TARGET := $(TARGET_NAME)_vita.a
|
||||
CC = arm-vita-eabi-gcc
|
||||
AR = arm-vita-eabi-ar
|
||||
CXXFLAGS += -Wl,-q -Wall -O3
|
||||
STATIC_LINKING = 1
|
||||
# Windows MSVC 2017 all architectures
|
||||
else ifneq (,$(findstring windows_msvc2017,$(platform)))
|
||||
|
||||
PlatformSuffix = $(subst windows_msvc2017_,,$(platform))
|
||||
ifneq (,$(findstring desktop,$(PlatformSuffix)))
|
||||
WinPartition = desktop
|
||||
MSVC2017CompileFlags = -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -FS -MP -GL -W0 -Gy -Zc:wchar_t -Gm- -Ox -Ob2 -sdl- -Zc:inline -fp:precise -DLIBRETRO -DWIN32 -D_CONSOLE -D_LIB -D_UNICODE -DUNICODE -errorReport:prompt -WX- -Zc:forScope -Gd -Oy -Oi -MT -EHsc -Ot -diagnostics:classic
|
||||
LDFLAGS += -MANIFEST -LTCG:incremental -NXCOMPAT -DYNAMICBASE -OPT:REF -INCREMENTAL:NO -SUBSYSTEM:WINDOWS -MANIFESTUAC:"level='asInvoker' uiAccess='false'" -OPT:ICF -ERRORREPORT:PROMPT -NOLOGO -TLBID:1
|
||||
LIBS += kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib
|
||||
else ifneq (,$(findstring uwp,$(PlatformSuffix)))
|
||||
WinPartition = uwp
|
||||
MSVC2017CompileFlags = -DWINAPI_FAMILY=WINAPI_FAMILY_APP -DWINDLL -D_UNICODE -DUNICODE -DWRL_NO_DEFAULT_LIB -FS
|
||||
LDFLAGS += -APPCONTAINER -NXCOMPAT -DYNAMICBASE -MANIFEST:NO -LTCG -OPT:REF -SUBSYSTEM:CONSOLE -MANIFESTUAC:NO -OPT:ICF -ERRORREPORT:PROMPT -NOLOGO -TLBID:1 -DEBUG:FULL -WINMD:NO
|
||||
LIBS += WindowsApp.lib
|
||||
endif
|
||||
|
||||
CFLAGS += $(MSVC2017CompileFlags)
|
||||
CXXFLAGS += $(MSVC2017CompileFlags)
|
||||
|
||||
TargetArchMoniker = $(subst $(WinPartition)_,,$(PlatformSuffix))
|
||||
|
||||
CC = cl.exe
|
||||
CXX = cl.exe
|
||||
|
||||
reg_query = $(call filter_out2,$(subst $2,,$(shell reg query "$2" -v "$1" 2>nul)))
|
||||
fix_path = $(subst $(SPACE),\ ,$(subst \,/,$1))
|
||||
|
||||
ProgramFiles86w := $(shell cmd /c "echo %PROGRAMFILES(x86)%")
|
||||
ProgramFiles86 := $(shell cygpath "$(ProgramFiles86w)")
|
||||
|
||||
WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0)
|
||||
WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0)
|
||||
WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0)
|
||||
WindowsSdkDir ?= $(call reg_query,InstallationFolder,HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0)
|
||||
WindowsSdkDir := $(WindowsSdkDir)
|
||||
|
||||
WindowsSDKVersion ?= $(firstword $(foreach folder,$(subst $(subst \,/,$(WindowsSdkDir)Include/),,$(wildcard $(call fix_path,$(WindowsSdkDir)Include\*))),$(if $(wildcard $(call fix_path,$(WindowsSdkDir)Include/$(folder)/um/Windows.h)),$(folder),)))$(BACKSLASH)
|
||||
WindowsSDKVersion := $(WindowsSDKVersion)
|
||||
|
||||
VsInstallBuildTools = $(ProgramFiles86)/Microsoft Visual Studio/2017/BuildTools
|
||||
VsInstallEnterprise = $(ProgramFiles86)/Microsoft Visual Studio/2017/Enterprise
|
||||
VsInstallProfessional = $(ProgramFiles86)/Microsoft Visual Studio/2017/Professional
|
||||
VsInstallCommunity = $(ProgramFiles86)/Microsoft Visual Studio/2017/Community
|
||||
|
||||
VsInstallRoot ?= $(shell if [ -d "$(VsInstallBuildTools)" ]; then echo "$(VsInstallBuildTools)"; fi)
|
||||
ifeq ($(VsInstallRoot), )
|
||||
VsInstallRoot = $(shell if [ -d "$(VsInstallEnterprise)" ]; then echo "$(VsInstallEnterprise)"; fi)
|
||||
endif
|
||||
ifeq ($(VsInstallRoot), )
|
||||
VsInstallRoot = $(shell if [ -d "$(VsInstallProfessional)" ]; then echo "$(VsInstallProfessional)"; fi)
|
||||
endif
|
||||
ifeq ($(VsInstallRoot), )
|
||||
VsInstallRoot = $(shell if [ -d "$(VsInstallCommunity)" ]; then echo "$(VsInstallCommunity)"; fi)
|
||||
endif
|
||||
VsInstallRoot := $(VsInstallRoot)
|
||||
|
||||
VcCompilerToolsVer := $(shell cat "$(VsInstallRoot)/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt" | grep -o '[0-9\.]*')
|
||||
VcCompilerToolsDir := $(VsInstallRoot)/VC/Tools/MSVC/$(VcCompilerToolsVer)
|
||||
|
||||
WindowsSDKSharedIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\shared")
|
||||
WindowsSDKUCRTIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\ucrt")
|
||||
WindowsSDKUMIncludeDir := $(shell cygpath -w "$(WindowsSdkDir)\Include\$(WindowsSDKVersion)\um")
|
||||
WindowsSDKUCRTLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\$(WindowsSDKVersion)\ucrt\$(TargetArchMoniker)")
|
||||
WindowsSDKUMLibDir := $(shell cygpath -w "$(WindowsSdkDir)\Lib\$(WindowsSDKVersion)\um\$(TargetArchMoniker)")
|
||||
|
||||
# For some reason the HostX86 compiler doesn't like compiling for x64
|
||||
# ("no such file" opening a shared library), and vice-versa.
|
||||
# Work around it for now by using the strictly x86 compiler for x86, and x64 for x64.
|
||||
# NOTE: What about ARM?
|
||||
ifneq (,$(findstring x64,$(TargetArchMoniker)))
|
||||
VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX64
|
||||
else
|
||||
VCCompilerToolsBinDir := $(VcCompilerToolsDir)\bin\HostX86
|
||||
endif
|
||||
|
||||
PATH := $(shell IFS=$$'\n'; cygpath "$(VCCompilerToolsBinDir)/$(TargetArchMoniker)"):$(PATH)
|
||||
PATH := $(PATH):$(shell IFS=$$'\n'; cygpath "$(VsInstallRoot)/Common7/IDE")
|
||||
INCLUDE := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/include")
|
||||
LIB := $(shell IFS=$$'\n'; cygpath -w "$(VcCompilerToolsDir)/lib/$(TargetArchMoniker)")
|
||||
|
||||
export INCLUDE := $(INCLUDE);$(WindowsSDKSharedIncludeDir);$(WindowsSDKUCRTIncludeDir);$(WindowsSDKUMIncludeDir)
|
||||
export LIB := $(LIB);$(WindowsSDKUCRTLibDir);$(WindowsSDKUMLibDir)
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
PSS_STYLE :=2
|
||||
LDFLAGS += -DLL
|
||||
LIBM :=
|
||||
else
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
SHARED := -shared -s -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||
endif
|
||||
|
||||
LDFLAGS += $(LIBM)
|
||||
|
||||
ifeq ($(LTO),true)
|
||||
CFLAGS += -flto
|
||||
CXXFLAGS += -flto
|
||||
LD = g++
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
CFLAGS += -MTd -Od -Zi -DDEBUG -D_DEBUG
|
||||
CXXFLAGS += -MTd -Od -Zi -DDEBUG -D_DEBUG
|
||||
else
|
||||
CFLAGS += -O0 -g
|
||||
CXXFLAGS += -O0 -g
|
||||
endif
|
||||
else
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
CFLAGS += -MT -O2 -DNDEBUG
|
||||
CXXFLAGS += -MT -O2 -DNDEBUG
|
||||
else
|
||||
CFLAGS += -O3
|
||||
CXXFLAGS += -O3
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
OBJOUT = -Fo
|
||||
LINKOUT = -out:
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
LD ?= lib.exe
|
||||
STATIC_LINKING=0
|
||||
else
|
||||
LD = link.exe
|
||||
endif
|
||||
else
|
||||
OBJOUT = -o
|
||||
LINKOUT = -o
|
||||
LD = $(CXX)
|
||||
endif
|
||||
|
||||
include Makefile.common
|
||||
|
||||
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_CXX:.cpp=.o)
|
||||
|
||||
ifeq (,$(findstring windows_msvc2017,$(platform)))
|
||||
CFLAGS += -Wall
|
||||
CXXFLAGS += -Wall
|
||||
endif
|
||||
|
||||
CFLAGS += -D LIBRETRO $(fpic)
|
||||
CXXFLAGS += -D LIBRETRO $(fpic) -std=c++14
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
@echo "** BUILDING $(TARGET) FOR PLATFORM $(platform) **"
|
||||
ifeq ($(STATIC_LINKING), 1)
|
||||
ifneq (,$(findstring msvc,$(platform)))
|
||||
$(LD) $(LINKOUT)$@ $(OBJECTS)
|
||||
else
|
||||
$(AR) rcs $@ $(OBJECTS)
|
||||
endif
|
||||
else
|
||||
$(LD) $(fpic) $(SHARED) $(INCLUDES) $(LINKOUT)$@ $(OBJECTS) $(LDFLAGS)
|
||||
endif
|
||||
@echo "** BUILD SUCCESSFUL! GG NO RE **"
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(fpic) -c $< $(OBJOUT)$@
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) $(fpic) -c $< $(OBJOUT)$@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(TARGET)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
print-%:
|
||||
@echo '$*=$($*)'
|
121
Libretro/Makefile.common
Normal file
121
Libretro/Makefile.common
Normal file
@ -0,0 +1,121 @@
|
||||
SOURCES_C := $(SEVENZIP_DIR)/7zAlloc.c \
|
||||
$(SEVENZIP_DIR)/7zArcIn.c \
|
||||
$(SEVENZIP_DIR)/7zBuf.c \
|
||||
$(SEVENZIP_DIR)/7zCrc.c \
|
||||
$(SEVENZIP_DIR)/7zCrcOpt.c \
|
||||
$(SEVENZIP_DIR)/7zDec.c \
|
||||
$(SEVENZIP_DIR)/7zFile.c \
|
||||
$(SEVENZIP_DIR)/7zMemBuffer.c \
|
||||
$(SEVENZIP_DIR)/7zStream.c \
|
||||
$(SEVENZIP_DIR)/Bcj2.c \
|
||||
$(SEVENZIP_DIR)/Bra.c \
|
||||
$(SEVENZIP_DIR)/Bra86.c \
|
||||
$(SEVENZIP_DIR)/BraIA64.c \
|
||||
$(SEVENZIP_DIR)/CpuArch.c \
|
||||
$(SEVENZIP_DIR)/Delta.c \
|
||||
$(SEVENZIP_DIR)/Lzma2Dec.c \
|
||||
$(SEVENZIP_DIR)/LzmaDec.c \
|
||||
$(SEVENZIP_DIR)/Ppmd7.c \
|
||||
$(SEVENZIP_DIR)/Ppmd7Dec.c \
|
||||
$(SEVENZIP_DIR)/Precomp.c \
|
||||
|
||||
SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
|
||||
$(CORE_DIR)/AviRecorder.cpp \
|
||||
$(CORE_DIR)/BaseCartridge.cpp \
|
||||
$(CORE_DIR)/BaseControlDevice.cpp \
|
||||
$(CORE_DIR)/BaseRenderer.cpp \
|
||||
$(CORE_DIR)/BaseSoundManager.cpp \
|
||||
$(CORE_DIR)/BaseVideoFilter.cpp \
|
||||
$(CORE_DIR)/Breakpoint.cpp \
|
||||
$(CORE_DIR)/BreakpointManager.cpp \
|
||||
$(CORE_DIR)/CallstackManager.cpp \
|
||||
$(CORE_DIR)/CodeDataLogger.cpp \
|
||||
$(CORE_DIR)/Console.cpp \
|
||||
$(CORE_DIR)/ConsoleLock.cpp \
|
||||
$(CORE_DIR)/ControlManager.cpp \
|
||||
$(CORE_DIR)/Cpu.cpp \
|
||||
$(CORE_DIR)/Cpu.Instructions.cpp \
|
||||
$(CORE_DIR)/CpuDisUtils.cpp \
|
||||
$(CORE_DIR)/Debugger.cpp \
|
||||
$(CORE_DIR)/DebugHud.cpp \
|
||||
$(CORE_DIR)/DebugStats.cpp \
|
||||
$(CORE_DIR)/DefaultVideoFilter.cpp \
|
||||
$(CORE_DIR)/Disassembler.cpp \
|
||||
$(CORE_DIR)/DisassemblyInfo.cpp \
|
||||
$(CORE_DIR)/DmaController.cpp \
|
||||
$(CORE_DIR)/EmuSettings.cpp \
|
||||
$(CORE_DIR)/EventManager.cpp \
|
||||
$(CORE_DIR)/ExpressionEvaluator.cpp \
|
||||
$(CORE_DIR)/InternalRegisters.cpp \
|
||||
$(CORE_DIR)/KeyManager.cpp \
|
||||
$(CORE_DIR)/LabelManager.cpp \
|
||||
$(CORE_DIR)/MemoryAccessCounter.cpp \
|
||||
$(CORE_DIR)/MemoryDumper.cpp \
|
||||
$(CORE_DIR)/MemoryManager.cpp \
|
||||
$(CORE_DIR)/MessageManager.cpp \
|
||||
$(CORE_DIR)/NotificationManager.cpp \
|
||||
$(CORE_DIR)/NtscFilter.cpp \
|
||||
$(CORE_DIR)/Ppu.cpp \
|
||||
$(CORE_DIR)/PpuTools.cpp \
|
||||
$(CORE_DIR)/RegisterHandlerB.cpp \
|
||||
$(CORE_DIR)/RewindData.cpp \
|
||||
$(CORE_DIR)/RewindManager.cpp \
|
||||
$(CORE_DIR)/SaveStateManager.cpp \
|
||||
$(CORE_DIR)/ScaleFilter.cpp \
|
||||
$(CORE_DIR)/ScriptHost.cpp \
|
||||
$(CORE_DIR)/ScriptingContext.cpp \
|
||||
$(CORE_DIR)/ScriptManager.cpp \
|
||||
$(CORE_DIR)/ShortcutKeyHandler.cpp \
|
||||
$(CORE_DIR)/SoundMixer.cpp \
|
||||
$(CORE_DIR)/SoundResampler.cpp \
|
||||
$(CORE_DIR)/Spc.cpp \
|
||||
$(CORE_DIR)/Spc.Instructions.cpp \
|
||||
$(CORE_DIR)/SpcDisUtils.cpp \
|
||||
$(CORE_DIR)/SPC_DSP.cpp \
|
||||
$(CORE_DIR)/SPC_Filter.cpp \
|
||||
$(CORE_DIR)/stdafx.cpp \
|
||||
$(CORE_DIR)/TraceLogger.cpp \
|
||||
$(CORE_DIR)/VideoDecoder.cpp \
|
||||
$(CORE_DIR)/VideoRenderer.cpp \
|
||||
$(CORE_DIR)/WaveRecorder.cpp \
|
||||
$(UTIL_DIR)/ArchiveReader.cpp \
|
||||
$(UTIL_DIR)/AutoResetEvent.cpp \
|
||||
$(UTIL_DIR)/AviWriter.cpp \
|
||||
$(UTIL_DIR)/blip_buf.cpp \
|
||||
$(UTIL_DIR)/BpsPatcher.cpp \
|
||||
$(UTIL_DIR)/CamstudioCodec.cpp \
|
||||
$(UTIL_DIR)/CRC32.cpp \
|
||||
$(UTIL_DIR)/Equalizer.cpp \
|
||||
$(UTIL_DIR)/FolderUtilities.cpp \
|
||||
$(UTIL_DIR)/HexUtilities.cpp \
|
||||
$(UTIL_DIR)/IpsPatcher.cpp \
|
||||
$(UTIL_DIR)/md5.cpp \
|
||||
$(UTIL_DIR)/miniz.cpp \
|
||||
$(UTIL_DIR)/snes_ntsc.cpp \
|
||||
$(UTIL_DIR)/PlatformUtilities.cpp \
|
||||
$(UTIL_DIR)/PNGHelper.cpp \
|
||||
$(UTIL_DIR)/Serializer.cpp \
|
||||
$(UTIL_DIR)/sha1.cpp \
|
||||
$(UTIL_DIR)/SimpleLock.cpp \
|
||||
$(UTIL_DIR)/Socket.cpp \
|
||||
$(UTIL_DIR)/stb_vorbis.cpp \
|
||||
$(UTIL_DIR)/stdafx.cpp \
|
||||
$(UTIL_DIR)/SZReader.cpp \
|
||||
$(UTIL_DIR)/Timer.cpp \
|
||||
$(UTIL_DIR)/UpsPatcher.cpp \
|
||||
$(UTIL_DIR)/UTF8Util.cpp \
|
||||
$(UTIL_DIR)/VirtualFile.cpp \
|
||||
$(UTIL_DIR)/ZipReader.cpp \
|
||||
$(UTIL_DIR)/ZipWriter.cpp \
|
||||
$(UTIL_DIR)/ZmbvCodec.cpp \
|
||||
$(UTIL_DIR)/HQX/hq2x.cpp \
|
||||
$(UTIL_DIR)/HQX/hq3x.cpp \
|
||||
$(UTIL_DIR)/HQX/hq4x.cpp \
|
||||
$(UTIL_DIR)/HQX/init.cpp \
|
||||
$(UTIL_DIR)/KreedSaiEagle/2xSai.cpp \
|
||||
$(UTIL_DIR)/KreedSaiEagle/Super2xSai.cpp \
|
||||
$(UTIL_DIR)/KreedSaiEagle/SuperEagle.cpp \
|
||||
$(UTIL_DIR)/Scale2x/scale2x.cpp \
|
||||
$(UTIL_DIR)/Scale2x/scale3x.cpp \
|
||||
$(UTIL_DIR)/Scale2x/scalebit.cpp \
|
||||
$(UTIL_DIR)/xBRZ/xbrz.cpp \
|
27
Libretro/jni/Android.mk
Normal file
27
Libretro/jni/Android.mk
Normal file
@ -0,0 +1,27 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
ROOT_DIR := $(LOCAL_PATH)/../..
|
||||
CORE_DIR := $(ROOT_DIR)/Core
|
||||
LIBRETRO_DIR := $(ROOT_DIR)/Libretro
|
||||
SEVENZIP_DIR := $(ROOT_DIR)/SevenZip
|
||||
UTIL_DIR := $(ROOT_DIR)/Utilities
|
||||
|
||||
HAVE_NETWORK := 1
|
||||
|
||||
include $(LIBRETRO_DIR)/Makefile.common
|
||||
|
||||
COREFLAGS := -DLIBRETRO
|
||||
|
||||
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
|
||||
ifneq ($(GIT_VERSION)," unknown")
|
||||
COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
|
||||
endif
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := retro
|
||||
LOCAL_SRC_FILES := $(SOURCES_CXX) $(SOURCES_C)
|
||||
LOCAL_CFLAGS := $(COREFLAGS)
|
||||
LOCAL_CXXFLAGS := $(COREFLAGS) -std=c++11
|
||||
LOCAL_LDFLAGS := -Wl,-version-script=$(LIBRETRO_DIR)/link.T
|
||||
LOCAL_CPP_FEATURES := exceptions rtti
|
||||
include $(BUILD_SHARED_LIBRARY)
|
7
Libretro/jni/Application.mk
Normal file
7
Libretro/jni/Application.mk
Normal file
@ -0,0 +1,7 @@
|
||||
APP_STL:=c++_static
|
||||
APP_ABI := all
|
||||
|
||||
# Don't strip debug builds
|
||||
ifeq ($(NDK_DEBUG),1)
|
||||
cmd-strip :=
|
||||
endif
|
558
Libretro/libretro.cpp
Normal file
558
Libretro/libretro.cpp
Normal file
@ -0,0 +1,558 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include "LibretroRenderer.h"
|
||||
#include "LibretroSoundManager.h"
|
||||
#include "LibretroKeyManager.h"
|
||||
#include "LibretroMessageManager.h"
|
||||
#include "libretro.h"
|
||||
#include "../Core/Console.h"
|
||||
#include "../Core/BaseCartridge.h"
|
||||
#include "../Core/MemoryManager.h"
|
||||
#include "../Core/VideoDecoder.h"
|
||||
#include "../Core/VideoRenderer.h"
|
||||
#include "../Core/EmuSettings.h"
|
||||
#include "../Core/SaveStateManager.h"
|
||||
#include "../Utilities/snes_ntsc.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
#include "../Utilities/HexUtilities.h"
|
||||
|
||||
#define DEVICE_AUTO RETRO_DEVICE_JOYPAD
|
||||
#define DEVICE_GAMEPAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0)
|
||||
#define DEVICE_SNESMOUSE RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_MOUSE, 2)
|
||||
|
||||
static retro_log_printf_t logCallback = nullptr;
|
||||
static retro_environment_t retroEnv = nullptr;
|
||||
static unsigned _inputDevices[5] = { DEVICE_GAMEPAD, DEVICE_GAMEPAD, DEVICE_AUTO, DEVICE_AUTO, DEVICE_AUTO };
|
||||
static string _mesenVersion = "";
|
||||
static int32_t _saveStateSize = -1;
|
||||
|
||||
static std::shared_ptr<Console> _console;
|
||||
static std::unique_ptr<LibretroRenderer> _renderer;
|
||||
static std::unique_ptr<LibretroSoundManager> _soundManager;
|
||||
static std::unique_ptr<LibretroKeyManager> _keyManager;
|
||||
static std::unique_ptr<LibretroMessageManager> _messageManager;
|
||||
|
||||
static const char* MesenNtscFilter = "mesen_ntsc_filter";
|
||||
static const char* MesenRegion = "mesen_region";
|
||||
static const char* MesenAspectRatio = "mesen_aspect_ratio";
|
||||
static const char* MesenOverscanVertical = "mesen_overscan_vertical";
|
||||
static const char* MesenOverscanHorizontal = "mesen_overscan_horizontal";
|
||||
|
||||
extern "C" {
|
||||
void logMessage(retro_log_level level, const char* message)
|
||||
{
|
||||
if(logCallback) {
|
||||
logCallback(level, message);
|
||||
}
|
||||
}
|
||||
|
||||
RETRO_API unsigned retro_api_version()
|
||||
{
|
||||
return RETRO_API_VERSION;
|
||||
}
|
||||
|
||||
RETRO_API void retro_init()
|
||||
{
|
||||
struct retro_log_callback log;
|
||||
if(retroEnv(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) {
|
||||
logCallback = log.log;
|
||||
} else {
|
||||
logCallback = nullptr;
|
||||
}
|
||||
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
|
||||
_renderer.reset(new LibretroRenderer(_console, retroEnv));
|
||||
_soundManager.reset(new LibretroSoundManager(_console));
|
||||
_keyManager.reset(new LibretroKeyManager(_console));
|
||||
_messageManager.reset(new LibretroMessageManager(logCallback, retroEnv));
|
||||
|
||||
AudioConfig audioConfig = _console->GetSettings()->GetAudioConfig();
|
||||
audioConfig.SampleRate = 32000;
|
||||
_console->GetSettings()->SetAudioConfig(audioConfig);
|
||||
|
||||
PreferencesConfig preferences = _console->GetSettings()->GetPreferences();
|
||||
preferences.RewindBufferSize = 0;
|
||||
_console->GetSettings()->SetPreferences(preferences);
|
||||
}
|
||||
|
||||
RETRO_API void retro_deinit()
|
||||
{
|
||||
_renderer.reset();
|
||||
_soundManager.reset();
|
||||
_keyManager.reset();
|
||||
_messageManager.reset();
|
||||
|
||||
//_console->SaveBatteries();
|
||||
_console->Release();
|
||||
_console.reset();
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_environment(retro_environment_t env)
|
||||
{
|
||||
retroEnv = env;
|
||||
|
||||
static const struct retro_variable vars[] = {
|
||||
{ MesenNtscFilter, "NTSC filter; Disabled|Composite (Blargg)|S-Video (Blargg)|RGB (Blargg)|Monochrome (Blargg)" },
|
||||
{ MesenRegion, "Region; Auto|NTSC|PAL" },
|
||||
{ MesenOverscanVertical, "Vertical Overscan; None|8px|16px" },
|
||||
{ MesenOverscanHorizontal, "Horizontal Overscan; None|8px|16px" },
|
||||
{ MesenAspectRatio, "Aspect Ratio; Auto|No Stretching|NTSC|PAL|4:3|16:9" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads1[] = {
|
||||
//{ "Auto", DEVICE_AUTO },
|
||||
{ "SNES Controller", DEVICE_GAMEPAD },
|
||||
{ "SNES Mouse", DEVICE_SNESMOUSE },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_description pads2[] = {
|
||||
//{ "Auto", DEVICE_AUTO },
|
||||
{ "SNES Controller", DEVICE_GAMEPAD },
|
||||
{ "SNES Mouse", DEVICE_SNESMOUSE },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static const struct retro_controller_info ports[] = {
|
||||
{ pads1, 2 },
|
||||
{ pads2, 2 },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
retroEnv(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
|
||||
retroEnv(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_video_refresh(retro_video_refresh_t sendFrame)
|
||||
{
|
||||
_renderer->SetVideoCallback(sendFrame);
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_audio_sample(retro_audio_sample_t sendAudioSample)
|
||||
{
|
||||
_soundManager->SetSendAudioSample(sendAudioSample);
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t audioSampleBatch)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_input_poll(retro_input_poll_t pollInput)
|
||||
{
|
||||
_keyManager->SetPollInput(pollInput);
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_input_state(retro_input_state_t getInputState)
|
||||
{
|
||||
_keyManager->SetGetInputState(getInputState);
|
||||
}
|
||||
|
||||
RETRO_API void retro_reset()
|
||||
{
|
||||
_console->Reset();
|
||||
}
|
||||
|
||||
bool readVariable(const char* key, retro_variable &var)
|
||||
{
|
||||
var.key = key;
|
||||
var.value = nullptr;
|
||||
if(retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value != nullptr) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void update_settings()
|
||||
{
|
||||
struct retro_variable var = { };
|
||||
VideoConfig video = _console->GetSettings()->GetVideoConfig();
|
||||
EmulationConfig emulation = _console->GetSettings()->GetEmulationConfig();
|
||||
InputConfig input = _console->GetSettings()->GetInputConfig();
|
||||
video.Brightness = 0;
|
||||
video.Contrast = 0;
|
||||
video.Hue = 0;
|
||||
video.Saturation = 0;
|
||||
video.ScanlineIntensity = 0;
|
||||
|
||||
if(readVariable(MesenNtscFilter, var)) {
|
||||
string value = string(var.value);
|
||||
if(value == "Disabled") {
|
||||
video.VideoFilter = VideoFilterType::None;
|
||||
} else if(value == "Composite (Blargg)") {
|
||||
video.VideoFilter = VideoFilterType::NTSC;
|
||||
video.NtscArtifacts = 0;
|
||||
video.NtscBleed = 0;
|
||||
video.NtscFringing = 0;
|
||||
video.NtscGamma = 0;
|
||||
video.NtscResolution = 0;
|
||||
video.NtscSharpness = 0;
|
||||
video.NtscMergeFields = false;
|
||||
} else if(value == "S-Video (Blargg)") {
|
||||
video.VideoFilter = VideoFilterType::NTSC;
|
||||
video.NtscArtifacts = -1.0;
|
||||
video.NtscBleed = 0;
|
||||
video.NtscFringing = -1.0;
|
||||
video.NtscGamma = 0;
|
||||
video.NtscResolution = 0.2;
|
||||
video.NtscSharpness = 0.2;
|
||||
video.NtscMergeFields = false;
|
||||
} else if(value == "RGB (Blargg)") {
|
||||
video.VideoFilter = VideoFilterType::NTSC;
|
||||
video.NtscArtifacts = -1.0;
|
||||
video.NtscBleed = -1.0;
|
||||
video.NtscFringing = -1.0;
|
||||
video.NtscGamma = 0;
|
||||
video.NtscResolution = 0.7;
|
||||
video.NtscSharpness = 0.2;
|
||||
video.NtscMergeFields = false;
|
||||
} else if(value == "Monochrome (Blargg)") {
|
||||
video.VideoFilter = VideoFilterType::NTSC;
|
||||
video.Saturation = -1.0;
|
||||
video.NtscArtifacts = -0.2;
|
||||
video.NtscBleed = -1.0;
|
||||
video.NtscFringing = -0.2;
|
||||
video.NtscGamma = 0;
|
||||
video.NtscResolution = 0.2;
|
||||
video.NtscSharpness = 0.2;
|
||||
video.NtscMergeFields = false;
|
||||
}
|
||||
}
|
||||
|
||||
int overscanHorizontal = 0;
|
||||
int overscanVertical = 0;
|
||||
if(readVariable(MesenOverscanHorizontal, var)) {
|
||||
string value = string(var.value);
|
||||
if(value == "8px") {
|
||||
overscanHorizontal = 8;
|
||||
} else if(value == "16px") {
|
||||
overscanHorizontal = 16;
|
||||
}
|
||||
}
|
||||
|
||||
if(readVariable(MesenOverscanVertical, var)) {
|
||||
string value = string(var.value);
|
||||
if(value == "8px") {
|
||||
overscanVertical = 8;
|
||||
} else if(value == "16px") {
|
||||
overscanVertical = 16;
|
||||
}
|
||||
}
|
||||
|
||||
video.OverscanLeft = overscanHorizontal;
|
||||
video.OverscanRight = overscanHorizontal;
|
||||
video.OverscanTop = overscanVertical;
|
||||
video.OverscanBottom = overscanVertical;
|
||||
|
||||
if(readVariable(MesenAspectRatio, var)) {
|
||||
string value = string(var.value);
|
||||
if(value == "Auto") {
|
||||
video.AspectRatio = VideoAspectRatio::Auto;
|
||||
} else if(value == "No Stretching") {
|
||||
video.AspectRatio = VideoAspectRatio::NoStretching;
|
||||
} else if(value == "NTSC") {
|
||||
video.AspectRatio = VideoAspectRatio::NTSC;
|
||||
} else if(value == "PAL") {
|
||||
video.AspectRatio = VideoAspectRatio::PAL;
|
||||
} else if(value == "4:3") {
|
||||
video.AspectRatio = VideoAspectRatio::Standard;
|
||||
} else if(value == "16:9") {
|
||||
video.AspectRatio = VideoAspectRatio::Widescreen;
|
||||
}
|
||||
}
|
||||
|
||||
if(readVariable(MesenRegion, var)) {
|
||||
string value = string(var.value);
|
||||
if(value == "Auto") {
|
||||
emulation.Region = ConsoleRegion::Auto;
|
||||
} else if(value == "NTSC") {
|
||||
emulation.Region = ConsoleRegion::Ntsc;
|
||||
} else if(value == "PAL") {
|
||||
emulation.Region = ConsoleRegion::Pal;
|
||||
}
|
||||
}
|
||||
|
||||
auto getKeyCode = [=](int port, int retroKey) {
|
||||
return (port << 8) | (retroKey + 1);
|
||||
};
|
||||
|
||||
auto getKeyBindings = [=](int port) {
|
||||
KeyMappingSet keyMappings;
|
||||
keyMappings.TurboSpeed = 0;
|
||||
keyMappings.Mapping1.L = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_L);
|
||||
keyMappings.Mapping1.R = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_R);
|
||||
keyMappings.Mapping1.A = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_A);
|
||||
keyMappings.Mapping1.B = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_B);
|
||||
keyMappings.Mapping1.X = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_X);
|
||||
keyMappings.Mapping1.Y = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_Y);
|
||||
|
||||
keyMappings.Mapping1.Start = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_START);
|
||||
keyMappings.Mapping1.Select = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_SELECT);
|
||||
|
||||
keyMappings.Mapping1.Up = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_UP);
|
||||
keyMappings.Mapping1.Down = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_DOWN);
|
||||
keyMappings.Mapping1.Left = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_LEFT);
|
||||
keyMappings.Mapping1.Right = getKeyCode(port, RETRO_DEVICE_ID_JOYPAD_RIGHT);
|
||||
|
||||
return keyMappings;
|
||||
};
|
||||
|
||||
input.Controllers[0].Keys = getKeyBindings(0);
|
||||
input.Controllers[1].Keys = getKeyBindings(1);
|
||||
input.Controllers[2].Keys = getKeyBindings(2);
|
||||
input.Controllers[3].Keys = getKeyBindings(3);
|
||||
|
||||
_console->GetSettings()->SetVideoConfig(video);
|
||||
_console->GetSettings()->SetEmulationConfig(emulation);
|
||||
_console->GetSettings()->SetInputConfig(input);
|
||||
|
||||
retro_system_av_info avInfo = {};
|
||||
_renderer->GetSystemAudioVideoInfo(avInfo);
|
||||
retroEnv(RETRO_ENVIRONMENT_SET_GEOMETRY, &avInfo);
|
||||
}
|
||||
|
||||
RETRO_API void retro_run()
|
||||
{
|
||||
if(_console->GetSettings()->CheckFlag(EmulationFlags::MaximumSpeed)) {
|
||||
//Skip frames to speed up emulation while still outputting at 50/60 fps (needed for FDS fast forward while loading)
|
||||
_renderer->SetSkipMode(true);
|
||||
_soundManager->SetSkipMode(true);
|
||||
for(int i = 0; i < 9; i++) {
|
||||
//Attempt to speed up to 1000% speed
|
||||
_console->RunSingleFrame();
|
||||
}
|
||||
_renderer->SetSkipMode(false);
|
||||
_soundManager->SetSkipMode(false);
|
||||
}
|
||||
|
||||
bool updated = false;
|
||||
if(retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) {
|
||||
update_settings();
|
||||
}
|
||||
|
||||
_console->RunSingleFrame();
|
||||
|
||||
if(updated) {
|
||||
//Update geometry after running the frame, in case the console's region changed (affects "auto" aspect ratio)
|
||||
retro_system_av_info avInfo = {};
|
||||
_renderer->GetSystemAudioVideoInfo(avInfo);
|
||||
retroEnv(RETRO_ENVIRONMENT_SET_GEOMETRY, &avInfo);
|
||||
}
|
||||
}
|
||||
|
||||
RETRO_API size_t retro_serialize_size()
|
||||
{
|
||||
return _saveStateSize;
|
||||
}
|
||||
|
||||
RETRO_API bool retro_serialize(void *data, size_t size)
|
||||
{
|
||||
std::stringstream ss;
|
||||
_console->Serialize(ss);
|
||||
|
||||
string saveStateData = ss.str();
|
||||
memset(data, 0, size);
|
||||
memcpy(data, saveStateData.c_str(), std::min(size, saveStateData.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RETRO_API bool retro_unserialize(const void *data, size_t size)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.write((const char*)data, size);
|
||||
_console->Deserialize(ss, SaveStateManager::FileFormatVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
RETRO_API void retro_cheat_reset()
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *codeStr)
|
||||
{
|
||||
}
|
||||
|
||||
void update_input_descriptors()
|
||||
{
|
||||
vector<retro_input_descriptor> desc;
|
||||
|
||||
auto addDesc = [&desc](unsigned port, unsigned button, const char* name) {
|
||||
retro_input_descriptor d = { port, RETRO_DEVICE_JOYPAD, 0, button, name };
|
||||
desc.push_back(d);
|
||||
};
|
||||
|
||||
auto setupPlayerButtons = [addDesc](int port) {
|
||||
unsigned device = _inputDevices[port];
|
||||
if(device == DEVICE_AUTO) {
|
||||
if(port <= 3) {
|
||||
switch(_console->GetSettings()->GetInputConfig().Controllers[port].Type) {
|
||||
case ControllerType::SnesController: device = DEVICE_GAMEPAD; break;
|
||||
case ControllerType::SnesMouse: device = DEVICE_SNESMOUSE; break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(device == DEVICE_GAMEPAD) {
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_A, "A");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_B, "B");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_X, "X");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_Y, "Y");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_L, "L");
|
||||
addDesc(port, RETRO_DEVICE_ID_JOYPAD_R, "R");
|
||||
}
|
||||
};
|
||||
|
||||
setupPlayerButtons(0);
|
||||
setupPlayerButtons(1);
|
||||
|
||||
retro_input_descriptor end = { 0 };
|
||||
desc.push_back(end);
|
||||
|
||||
retroEnv(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc.data());
|
||||
}
|
||||
|
||||
void update_core_controllers()
|
||||
{
|
||||
InputConfig input = _console->GetSettings()->GetInputConfig();
|
||||
for(int port = 0; port < 2; port++) {
|
||||
ControllerType type = ControllerType::SnesController;
|
||||
switch(_inputDevices[port]) {
|
||||
case RETRO_DEVICE_NONE: type = ControllerType::None; break;
|
||||
case DEVICE_GAMEPAD: type = ControllerType::SnesController; break;
|
||||
case DEVICE_SNESMOUSE: type = ControllerType::SnesMouse; break;
|
||||
}
|
||||
input.Controllers[port].Type = type;
|
||||
}
|
||||
_console->GetSettings()->SetInputConfig(input);
|
||||
}
|
||||
|
||||
void retro_set_memory_maps()
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device)
|
||||
{
|
||||
if(port < 2 && _inputDevices[port] != device) {
|
||||
_inputDevices[port] = device;
|
||||
update_core_controllers();
|
||||
update_input_descriptors();
|
||||
}
|
||||
}
|
||||
|
||||
RETRO_API bool retro_load_game(const struct retro_game_info *game)
|
||||
{
|
||||
char *systemFolder;
|
||||
if(!retroEnv(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &systemFolder) || !systemFolder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char *saveFolder;
|
||||
if(!retroEnv(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &saveFolder)) {
|
||||
logMessage(RETRO_LOG_ERROR, "Could not find save directory.\n");
|
||||
}
|
||||
|
||||
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
|
||||
if(!retroEnv(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) {
|
||||
logMessage(RETRO_LOG_ERROR, "XRGB8888 is not supported.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Expect the following structure:
|
||||
// /saves/*.sav
|
||||
FolderUtilities::SetHomeFolder(systemFolder);
|
||||
FolderUtilities::SetFolderOverrides(saveFolder, "", "");
|
||||
|
||||
update_settings();
|
||||
|
||||
//Plug in 2 standard controllers by default, game database will switch the controller types for recognized games
|
||||
/*
|
||||
_console->GetSettings()->SetControllerType(0, ControllerType::SnesController);
|
||||
_console->GetSettings()->SetControllerType(1, ControllerType::SnesController);
|
||||
_console->GetSettings()->SetControllerType(2, ControllerType::None);
|
||||
_console->GetSettings()->SetControllerType(3, ControllerType::None);*/
|
||||
|
||||
VirtualFile romData(game->data, game->size, game->path);
|
||||
VirtualFile patch;
|
||||
bool result = _console->LoadRom(romData, patch);
|
||||
|
||||
if(result) {
|
||||
update_core_controllers();
|
||||
update_input_descriptors();
|
||||
|
||||
//Savestates in Mesen may change size over time
|
||||
//Retroarch doesn't like this for netplay or rewinding - it requires the states to always be the exact same size
|
||||
//So we need to send a large enough size to Retroarch to ensure Mesen's state will always fit within that buffer.
|
||||
std::stringstream ss;
|
||||
_console->Serialize(ss);
|
||||
|
||||
//Round up to the next 1kb multiple
|
||||
_saveStateSize = ((ss.str().size() * 2) + 0x400) & ~0x3FF;
|
||||
retro_set_memory_maps();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RETRO_API void retro_unload_game()
|
||||
{
|
||||
_console->Stop(false);
|
||||
}
|
||||
|
||||
RETRO_API unsigned retro_get_region()
|
||||
{
|
||||
ConsoleRegion region = _console->GetRegion();
|
||||
return region == ConsoleRegion::Ntsc ? RETRO_REGION_NTSC : RETRO_REGION_PAL;
|
||||
}
|
||||
|
||||
RETRO_API void retro_get_system_info(struct retro_system_info *info)
|
||||
{
|
||||
if(!_console) {
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
}
|
||||
_mesenVersion = _console->GetSettings()->GetVersionString();
|
||||
|
||||
info->library_name = "Mesen-S";
|
||||
info->library_version = _mesenVersion.c_str();
|
||||
info->need_fullpath = false;
|
||||
info->valid_extensions = "sfc|smc|fig|swc";
|
||||
info->block_extract = false;
|
||||
}
|
||||
|
||||
RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info)
|
||||
{
|
||||
_renderer->GetSystemAudioVideoInfo(*info, SNES_NTSC_OUT_WIDTH(256), 239 * 2);
|
||||
}
|
||||
|
||||
RETRO_API void *retro_get_memory_data(unsigned id)
|
||||
{
|
||||
switch(id) {
|
||||
case RETRO_MEMORY_SAVE_RAM: return _console->GetCartridge()->DebugGetSaveRam();
|
||||
case RETRO_MEMORY_SYSTEM_RAM: return _console->GetMemoryManager()->DebugGetWorkRam();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RETRO_API size_t retro_get_memory_size(unsigned id)
|
||||
{
|
||||
switch(id) {
|
||||
case RETRO_MEMORY_SAVE_RAM: _console->GetCartridge()->DebugGetSaveRamSize(); break;
|
||||
case RETRO_MEMORY_SYSTEM_RAM: return MemoryManager::WorkRamSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
2323
Libretro/libretro.h
Normal file
2323
Libretro/libretro.h
Normal file
File diff suppressed because it is too large
Load Diff
5
Libretro/link.T
Normal file
5
Libretro/link.T
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
global: retro_*;
|
||||
local: *;
|
||||
};
|
||||
|
30
Mesen-S.sln
30
Mesen-S.sln
@ -50,6 +50,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SevenZip", "SevenZip\SevenZ
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Lua", "Lua\Lua.vcxproj", "{B609E0A0-5050-4871-91D6-E760633BCDD1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Libretro", "Libretro\Libretro.vcxproj", "{4432139E-528B-44DE-961C-B37CD5E92E0E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{B5330148-E8C7-46BA-B54E-69BE59EA337D} = {B5330148-E8C7-46BA-B54E-69BE59EA337D}
|
||||
{78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0} = {78FEF1A1-6DF1-4CBB-A373-AE6FA7CE5CE0}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -304,7 +310,6 @@ Global
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|Any CPU.ActiveCfg = Libretro|Win32
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|x64.ActiveCfg = Libretro|x64
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|x64.Build.0 = Libretro|x64
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|x86.ActiveCfg = Libretro|Win32
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Libretro|x86.Build.0 = Libretro|Win32
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.PGO Optimize|Any CPU.ActiveCfg = PGO Optimize|Win32
|
||||
@ -322,6 +327,29 @@ Global
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x64.Build.0 = Release|x64
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B609E0A0-5050-4871-91D6-E760633BCDD1}.Release|x86.Build.0 = Release|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|Any CPU.ActiveCfg = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x64.ActiveCfg = Libretro|x64
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x64.Build.0 = Libretro|x64
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x86.ActiveCfg = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Libretro|x86.Build.0 = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|Any CPU.ActiveCfg = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|Any CPU.Build.0 = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|x64.ActiveCfg = Libretro|x64
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|x86.ActiveCfg = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Optimize|x86.Build.0 = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|Any CPU.ActiveCfg = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|Any CPU.Build.0 = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|x64.ActiveCfg = Libretro|x64
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|x86.ActiveCfg = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.PGO Profile|x86.Build.0 = Libretro|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|x64.ActiveCfg = Release|x64
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4432139E-528B-44DE-961C-B37CD5E92E0E}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -24,9 +24,7 @@ The following should be added over time (in no particular order):
|
||||
* Netplay
|
||||
* Cheats
|
||||
* Additions/improvements in the debugging tools
|
||||
* Lua scripting
|
||||
* Support for the enhancement chips used in some games
|
||||
* Libretro core (once the emulation core is stable/accurate enough)
|
||||
|
||||
## Compiling
|
||||
|
||||
|
6
makefile
6
makefile
@ -63,7 +63,7 @@ endif
|
||||
|
||||
OBJFOLDER=obj.$(MESENPLATFORM)
|
||||
SHAREDLIB=libMesenSCore.$(MESENPLATFORM).dll
|
||||
LIBRETROLIB=mesens_libretro.$(MESENPLATFORM).so
|
||||
LIBRETROLIB=mesen-s_libretro.$(MESENPLATFORM).so
|
||||
RELEASEFOLDER=bin/$(MESENPLATFORM)/Release
|
||||
|
||||
COREOBJ=$(patsubst Core/%.cpp,Core/$(OBJFOLDER)/%.o,$(wildcard Core/*.cpp))
|
||||
@ -143,10 +143,10 @@ InteropDLL/$(OBJFOLDER)/$(SHAREDLIB): $(SEVENZIPOBJ) $(LUAOBJ) $(UTILOBJ) $(CORE
|
||||
cp $(SHAREDLIB) bin/pgohelperlib.so
|
||||
mv $(SHAREDLIB) InteropDLL/$(OBJFOLDER)
|
||||
|
||||
Libretro/$(OBJFOLDER)/$(LIBRETROLIB): $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) $(LUAOBJ) Libretro/libretro.cpp
|
||||
Libretro/$(OBJFOLDER)/$(LIBRETROLIB): $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) Libretro/libretro.cpp
|
||||
mkdir -p bin
|
||||
mkdir -p Libretro/$(OBJFOLDER)
|
||||
$(CPPC) $(GCCOPTIONS) -Wl,-z,defs -shared -o $(LIBRETROLIB) Libretro/*.cpp $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) $(LUAOBJ) -pthread $(FSLIB)
|
||||
$(CPPC) $(GCCOPTIONS) -Wl,-z,defs -shared -o $(LIBRETROLIB) Libretro/*.cpp $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) -pthread
|
||||
cp $(LIBRETROLIB) bin/pgohelperlib.so
|
||||
mv $(LIBRETROLIB) Libretro/$(OBJFOLDER)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user