Initial commit

This commit is contained in:
Connor McLaughlin
2019-09-09 17:01:26 +10:00
commit 2149ab4d69
237 changed files with 493349 additions and 0 deletions

View File

@ -0,0 +1,11 @@
set(SRCS
main.cpp
sdl_audio_mixer.cpp
sdl_audio_mixer.h
sdl_interface.cpp
sdl_interface.h
)
add_executable(pse-sdl ${SRCS})
target_include_directories(pse-sdl PRIVATE "${SDL2_INCLUDE_DIRS}")
target_link_libraries(pse-sdl pse imgui "${SDL2_LIBRARIES}")

84
src/pse-sdl/main.cpp Normal file
View File

@ -0,0 +1,84 @@
#include "YBaseLib/Assert.h"
#include "YBaseLib/Log.h"
#include "YBaseLib/StringConverter.h"
#include "sdl_interface.h"
#include "pse/types.h"
#include "pse/system.h"
#include <SDL.h>
#include <cstdio>
static int NoGUITest()
{
std::unique_ptr<System> system = std::make_unique<System>();
if (!system->Initialize())
return -1;
system->Reset();
while (true)
system->RunFrame();
return 0;
}
static int Run(int argc, char* argv[])
{
if (argc < 2)
{
std::fprintf(stderr, "Usage: %s <path to system ini> [save state index]\n", argv[0]);
return -1;
}
// init sdl
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
{
Panic("SDL initialization failed");
return -1;
}
// create display and host interface
std::unique_ptr<SDLInterface> host_interface = SDLInterface::Create();
if (!host_interface)
{
Panic("Failed to create host interface");
SDL_Quit();
return -1;
}
// create system
s32 state_index = -1;
if (argc > 2)
state_index = StringConverter::StringToInt32(argv[2]);
if (!host_interface->InitializeSystem(argv[1], state_index))
{
host_interface.reset();
SDL_Quit();
return -1;
}
// run
host_interface->Run();
// done
host_interface.reset();
SDL_Quit();
return 0;
}
// SDL requires the entry point declared without c++ decoration
#undef main
int main(int argc, char* argv[])
{
// set log flags
g_pLog->SetConsoleOutputParams(true, nullptr, LOGLEVEL_DEBUG);
#ifdef Y_BUILD_CONFIG_RELEASE
g_pLog->SetFilterLevel(LOGLEVEL_INFO);
// g_pLog->SetFilterLevel(LOGLEVEL_PROFILE);
#else
// g_pLog->SetFilterLevel(LOGLEVEL_TRACE);
g_pLog->SetFilterLevel(LOGLEVEL_DEBUG);
#endif
return NoGUITest();
//return Run(argc, argv);
}

378
src/pse-sdl/pse-sdl.vcxproj Normal file
View File

@ -0,0 +1,378 @@
<?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="DebugFast|Win32">
<Configuration>DebugFast</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="DebugFast|x64">
<Configuration>DebugFast</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseLTCG|Win32">
<Configuration>ReleaseLTCG</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseLTCG|x64">
<Configuration>ReleaseLTCG</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\dep\imgui\imgui.vcxproj">
<Project>{bb08260f-6fbc-46af-8924-090ee71360c6}</Project>
</ProjectReference>
<ProjectReference Include="..\..\dep\YBaseLib\Source\YBaseLib.vcxproj">
<Project>{b56ce698-7300-4fa5-9609-942f1d05c5a2}</Project>
</ProjectReference>
<ProjectReference Include="..\common\common.vcxproj">
<Project>{ee054e08-3799-4a59-a422-18259c105ffd}</Project>
</ProjectReference>
<ProjectReference Include="..\pse\pse.vcxproj">
<Project>{868b98c8-65a1-494b-8346-250a73a48c0a}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="sdl_audio_mixer.cpp" />
<ClCompile Include="sdl_interface.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="sdl_audio_mixer.h" />
<ClInclude Include="sdl_interface.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{DAA8F93D-9C17-4DE2-BD0B-57891E0FF0D9}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>pse-sdl</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" 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)'=='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)'=='ReleaseLTCG|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|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)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|x64'">
<IntDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
<TargetName>$(ProjectName)-$(Platform)-$(Configuration)</TargetName>
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(Platform)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32-debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64-debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32-debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<LanguageStandard>stdcpp17</LanguageStandard>
<SupportJustMyCode>false</SupportJustMyCode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64-debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>false</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
<OmitFramePointers>true</OmitFramePointers>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>false</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLTCG|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)dep\msvc\include;$(SolutionDir)dep\msvc\include\SDL;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\nativefiledialog\include;$(SolutionDir)dep\glad\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LanguageStandard>stdcpp17</LanguageStandard>
<OmitFramePointers>true</OmitFramePointers>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>SDL2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)dep\msvc\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="sdl_audio_mixer.cpp" />
<ClCompile Include="sdl_interface.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="sdl_audio_mixer.h" />
<ClInclude Include="sdl_interface.h" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,129 @@
#include "sdl_audio_mixer.h"
#include "YBaseLib/Timer.h"
#include <SDL_audio.h>
using namespace Audio;
inline SDL_AudioFormat GetSDLAudioFormat(SampleFormat format)
{
switch (format)
{
case SampleFormat::Signed8:
return AUDIO_S8;
case SampleFormat::Unsigned8:
return AUDIO_U8;
case SampleFormat::Signed16:
return AUDIO_S16SYS;
case SampleFormat::Unsigned16:
return AUDIO_U16SYS;
case SampleFormat::Signed32:
return AUDIO_S32SYS;
case SampleFormat::Float32:
return AUDIO_F32;
}
Panic("Unhandled format");
return AUDIO_U8;
}
SDLAudioMixer::SDLAudioMixer(SDL_AudioDeviceID device_id, float output_sample_rate)
: Mixer(output_sample_rate), m_device_id(device_id)
{
}
SDLAudioMixer::~SDLAudioMixer()
{
SDL_CloseAudioDevice(m_device_id);
}
std::unique_ptr<SDLAudioMixer> SDLAudioMixer::Create()
{
auto mixer = std::make_unique<SDLAudioMixer>(0, 44100.0f);
SDL_AudioSpec spec = {44100, AUDIO_F32, static_cast<Uint8>(NumOutputChannels), 0, 4096, 0, 0,
RenderCallback, mixer.get()};
SDL_AudioSpec obtained_spec;
SDL_AudioDeviceID device_id = SDL_OpenAudioDevice(nullptr, 0, &spec, &obtained_spec, 0);
if (device_id == 0)
return nullptr;
mixer->m_device_id = device_id;
SDL_PauseAudioDevice(device_id, SDL_FALSE);
return mixer;
}
void SDLAudioMixer::RenderSamples(Audio::OutputFormatType* buf, size_t num_samples)
{
CheckRenderBufferSize(num_samples);
std::fill_n(buf, num_samples * NumOutputChannels, 0.0f);
for (auto& channel : m_channels)
{
channel->ReadSamples(m_render_buffer.data(), num_samples);
// Don't bother mixing it if we're muted.
if (m_muted)
continue;
// If the format is the same, we can just copy it as-is..
if (channel->GetChannels() == 1)
{
// Mono -> stereo
for (ssize_t idx = ssize_t(num_samples) - 1; idx >= 0; idx--)
{
float sample = m_render_buffer[idx];
m_render_buffer[idx * 2 + 0] = sample;
m_render_buffer[idx * 2 + 1] = sample;
}
}
else if (channel->GetChannels() != NumOutputChannels)
{
SDL_AudioCVT cvt;
int err = SDL_BuildAudioCVT(&cvt, AUDIO_F32, Truncate8(channel->GetChannels()), int(m_output_sample_rate),
AUDIO_F32, Truncate8(NumOutputChannels), int(m_output_sample_rate));
if (err != 1)
Panic("Failed to set up audio conversion");
cvt.len = int(channel->GetChannels() * sizeof(float));
cvt.buf = reinterpret_cast<Uint8*>(m_render_buffer.data());
err = SDL_ConvertAudio(&cvt);
if (err != 0)
Panic("Failed to convert audio");
}
// Mix channels together.
const Audio::OutputFormatType* mix_src = reinterpret_cast<const Audio::OutputFormatType*>(m_render_buffer.data());
Audio::OutputFormatType* mix_dst = buf;
for (size_t i = 0; i < num_samples * NumOutputChannels; i++)
{
// TODO: Saturation/clamping here
*(mix_dst++) += *(mix_src++);
}
}
#if 0
static FILE* fp = nullptr;
if (!fp)
fp = fopen("D:\\mixed.raw", "wb");
if (fp)
{
fwrite(buf, sizeof(float), num_samples * NumOutputChannels, fp);
fflush(fp);
}
#endif
}
void SDLAudioMixer::RenderCallback(void* userdata, Uint8* stream, int len)
{
SDLAudioMixer* mixer = static_cast<SDLAudioMixer*>(userdata);
Audio::OutputFormatType* buf = reinterpret_cast<Audio::OutputFormatType*>(stream);
size_t num_samples = size_t(len) / NumOutputChannels / sizeof(Audio::OutputFormatType);
if (num_samples > 0)
mixer->RenderSamples(buf, num_samples);
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "common/audio.h"
#include <SDL_audio.h>
class SDLAudioMixer : public Audio::Mixer
{
public:
SDLAudioMixer(SDL_AudioDeviceID device_id, float output_sample_rate);
virtual ~SDLAudioMixer();
static std::unique_ptr<SDLAudioMixer> Create();
protected:
void RenderSamples(Audio::OutputFormatType* buf, size_t num_samples);
static void RenderCallback(void* userdata, Uint8* stream, int len);
private:
SDL_AudioDeviceID m_device_id;
};

View File

@ -0,0 +1,579 @@
#include "sdl_interface.h"
#include "YBaseLib/ByteStream.h"
#include "YBaseLib/Error.h"
#include "common/display_renderer_d3d.h"
#include "imgui.h"
#include "imgui_impl_opengl3.h"
#include "imgui_impl_sdl.h"
#include "pse/system.h"
#include <SDL.h>
#include <cinttypes>
#include <glad.h>
#ifdef Y_COMPILER_MSVC
#include "imgui_impl_dx11.h"
#include <SDL_syswm.h>
#endif
SDLInterface::SDLInterface(SDL_Window* window, std::unique_ptr<DisplayRenderer> display_renderer,
std::unique_ptr<MixerType> mixer)
: m_window(window), m_display_renderer(std::move(display_renderer)), m_mixer(std::move(mixer))
{
}
SDLInterface::~SDLInterface()
{
m_mixer.reset();
switch (m_display_renderer->GetBackendType())
{
#ifdef Y_COMPILER_MSVC
case DisplayRenderer::BackendType::Direct3D:
{
ImGui_ImplDX11_Shutdown();
ImGui::DestroyContext();
m_display_renderer.reset();
}
break;
#endif
case DisplayRenderer::BackendType::OpenGL:
{
SDL_GLContext context = SDL_GL_GetCurrentContext();
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
m_display_renderer.reset();
SDL_GL_MakeCurrent(nullptr, nullptr);
SDL_GL_DeleteContext(context);
}
break;
default:
{
ImGui::DestroyContext();
m_display_renderer.reset();
}
break;
}
}
std::unique_ptr<SDLInterface> SDLInterface::Create(
DisplayRenderer::BackendType display_renderer_backend /* = DisplayRenderer::GetDefaultBackendType() */)
{
constexpr u32 DEFAULT_WINDOW_WIDTH = 900;
constexpr u32 DEFAULT_WINDOW_HEIGHT = 700;
constexpr u32 MAIN_MENU_BAR_HEIGHT = 20;
// Create window.
u32 window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
if (display_renderer_backend == DisplayRenderer::BackendType::OpenGL)
window_flags |= SDL_WINDOW_OPENGL;
auto window = std::unique_ptr<SDL_Window, void (*)(SDL_Window*)>(
SDL_CreateWindow("PCE - Initializing...", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DEFAULT_WINDOW_WIDTH,
DEFAULT_WINDOW_HEIGHT, window_flags),
[](SDL_Window* win) { SDL_DestroyWindow(win); });
if (!window)
{
Panic("Failed to create window");
return nullptr;
}
DisplayRenderer::WindowHandleType window_handle = nullptr;
if (display_renderer_backend == DisplayRenderer::BackendType::OpenGL)
{
// We need a GL context. TODO: Move this to common.
SDL_GLContext gl_context = SDL_GL_CreateContext(window.get());
if (!gl_context || SDL_GL_MakeCurrent(window.get(), gl_context) != 0 || !gladLoadGL())
{
Panic("Failed to create GL context");
return nullptr;
}
}
#ifdef Y_COMPILER_MSVC
if (display_renderer_backend == DisplayRenderer::BackendType::Direct3D)
{
// Get window handle from SDL window
SDL_SysWMinfo info = {};
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(window.get(), &info))
{
Panic("SDL_GetWindowWMInfo failed");
return nullptr;
}
window_handle = info.info.win.window;
}
#endif
// Create renderer.
auto display_renderer =
DisplayRenderer::Create(display_renderer_backend, window_handle, DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
if (!display_renderer)
{
Panic("Failed to create display");
return nullptr;
}
display_renderer->SetTopPadding(MAIN_MENU_BAR_HEIGHT);
// Create audio renderer.
auto mixer = MixerType::Create();
if (!mixer)
{
Panic("Failed to create audio mixer");
return nullptr;
}
// Initialize imgui.
ImGui::CreateContext();
ImGui::GetIO().IniFilename = nullptr;
switch (display_renderer->GetBackendType())
{
#ifdef Y_COMPILER_MSVC
case DisplayRenderer::BackendType::Direct3D:
{
if (!ImGui_ImplSDL2_InitForD3D(window.get()) ||
!ImGui_ImplDX11_Init(static_cast<DisplayRendererD3D*>(display_renderer.get())->GetD3DDevice(),
static_cast<DisplayRendererD3D*>(display_renderer.get())->GetD3DContext()))
{
return nullptr;
}
ImGui_ImplDX11_NewFrame();
ImGui_ImplSDL2_NewFrame(window.get());
ImGui::NewFrame();
}
break;
#endif
case DisplayRenderer::BackendType::OpenGL:
{
if (!ImGui_ImplSDL2_InitForOpenGL(window.get(), SDL_GL_GetCurrentContext()) || !ImGui_ImplOpenGL3_Init())
return nullptr;
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(window.get());
ImGui::NewFrame();
}
break;
default:
break;
}
return std::make_unique<SDLInterface>(window.release(), std::move(display_renderer), std::move(mixer));
}
TinyString SDLInterface::GetSaveStateFilename(u32 index)
{
return TinyString::FromFormat("savestate_%u.bin", index);
}
bool SDLInterface::InitializeSystem(const char* filename, s32 save_state_index /* = -1 */)
{
Error error;
m_system = std::make_unique<System>();
if (!m_system->Initialize())
{
m_system.reset();
return false;
}
#if 0
if (save_state_index >= 0)
{
// Load the save state.
if (!HostInterface::LoadSystemState(GetSaveStateFilename(static_cast<u32>(save_state_index)), &error))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Loading save state failed", error.GetErrorCodeAndDescription(),
m_window);
}
}
#endif
// Resume execution.
m_running = true;
return true;
}
void SDLInterface::ReportMessage(const char* message)
{
AddOSDMessage(message, 3.0f);
}
bool SDLInterface::IsWindowFullscreen() const
{
return ((SDL_GetWindowFlags(m_window) & SDL_WINDOW_FULLSCREEN) != 0);
}
static inline u32 SDLButtonToHostButton(u32 button)
{
// SDL left = 1, middle = 2, right = 3 :/
switch (button)
{
case 1:
return 0;
case 2:
return 2;
case 3:
return 1;
default:
return 0xFFFFFFFF;
}
}
bool SDLInterface::HandleSDLEvent(const SDL_Event* event)
{
if (PassEventToImGui(event))
return true;
switch (event->type)
{
#if 0
case SDL_MOUSEBUTTONDOWN:
{
u32 button = SDLButtonToHostButton(event->button.button);
if (IsMouseGrabbed())
{
ExecuteMouseButtonChangeCallbacks(button, true);
return true;
}
}
break;
case SDL_MOUSEBUTTONUP:
{
u32 button = SDLButtonToHostButton(event->button.button);
if (IsMouseGrabbed())
{
ExecuteMouseButtonChangeCallbacks(button, false);
return true;
}
else
{
// Are we capturing the mouse?
if (button == 0)
GrabMouse();
}
}
break;
case SDL_MOUSEMOTION:
{
if (!IsMouseGrabbed())
return false;
s32 dx = event->motion.xrel;
s32 dy = event->motion.yrel;
ExecuteMousePositionChangeCallbacks(dx, dy);
return true;
}
break;
case SDL_KEYDOWN:
{
// Release mouse key combination
if (((event->key.keysym.sym == SDLK_LCTRL || event->key.keysym.sym == SDLK_RCTRL) &&
(SDL_GetModState() & KMOD_ALT) != 0) ||
((event->key.keysym.sym == SDLK_LALT || event->key.keysym.sym == SDLK_RALT) &&
(SDL_GetModState() & KMOD_CTRL) != 0))
{
// But don't consume the key event.
ReleaseMouse();
}
// Create keyboard event.
// TODO: Since we have crap in the input polling, we can't return true here.
GenScanCode scancode;
if (MapSDLScanCode(&scancode, event->key.keysym.scancode))
{
ExecuteKeyboardCallbacks(scancode, true);
return false;
}
}
break;
case SDL_KEYUP:
{
// Create keyboard event.
// TODO: Since we have crap in the input polling, we can't return true here.
GenScanCode scancode;
if (MapSDLScanCode(&scancode, event->key.keysym.scancode))
{
ExecuteKeyboardCallbacks(scancode, false);
return false;
}
}
break;
#endif
case SDL_WINDOWEVENT:
{
if (event->window.event == SDL_WINDOWEVENT_RESIZED)
m_display_renderer->WindowResized(u32(event->window.data1), u32(event->window.data2));
}
break;
case SDL_QUIT:
m_running = false;
break;
}
return false;
}
bool SDLInterface::PassEventToImGui(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
switch (event->type)
{
case SDL_MOUSEWHEEL:
{
if (event->wheel.x > 0)
io.MouseWheelH += 1;
if (event->wheel.x < 0)
io.MouseWheelH -= 1;
if (event->wheel.y > 0)
io.MouseWheel += 1;
if (event->wheel.y < 0)
io.MouseWheel -= 1;
return io.WantCaptureMouse;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
bool down = event->type == SDL_MOUSEBUTTONDOWN;
if (event->button.button == SDL_BUTTON_LEFT)
io.MouseDown[0] = down;
if (event->button.button == SDL_BUTTON_RIGHT)
io.MouseDown[1] = down;
if (event->button.button == SDL_BUTTON_MIDDLE)
io.MouseDown[2] = down;
return io.WantCaptureMouse;
}
case SDL_MOUSEMOTION:
{
io.MousePos.x = float(event->motion.x);
io.MousePos.y = float(event->motion.y);
return io.WantCaptureMouse;
}
case SDL_TEXTINPUT:
{
io.AddInputCharactersUTF8(event->text.text);
return io.WantCaptureKeyboard;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
int key = event->key.keysym.scancode;
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
io.KeysDown[key] = (event->type == SDL_KEYDOWN);
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
return io.WantCaptureKeyboard;
}
}
return false;
}
void SDLInterface::Render()
{
if (!m_display_renderer->BeginFrame())
return;
m_display_renderer->RenderDisplays();
RenderImGui();
const DisplayRenderer::BackendType backend_type = m_display_renderer->GetBackendType();
switch (backend_type)
{
#ifdef Y_COMPILER_MSVC
case DisplayRenderer::BackendType::Direct3D:
{
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
m_display_renderer->EndFrame();
ImGui_ImplSDL2_NewFrame(m_window);
ImGui_ImplDX11_NewFrame();
}
break;
#endif
case DisplayRenderer::BackendType::OpenGL:
{
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
m_display_renderer->EndFrame();
SDL_GL_SwapWindow(m_window);
ImGui_ImplSDL2_NewFrame(m_window);
ImGui_ImplOpenGL3_NewFrame();
}
break;
default:
break;
}
ImGui::NewFrame();
}
void SDLInterface::RenderImGui()
{
RenderMainMenuBar();
RenderOSDMessages();
ImGui::Render();
}
void SDLInterface::RenderMainMenuBar()
{
if (!ImGui::BeginMainMenuBar())
return;
if (ImGui::BeginMenu("System"))
{
if (ImGui::MenuItem("Reset"))
m_system->Reset();
ImGui::Separator();
#if 0
if (ImGui::MenuItem("Enable Speed Limiter", nullptr, IsSpeedLimiterEnabled()))
SetSpeedLimiterEnabled(!IsSpeedLimiterEnabled());
#endif
ImGui::Separator();
if (ImGui::BeginMenu("Load State"))
{
for (u32 i = 1; i <= 8; i++)
{
if (ImGui::MenuItem(TinyString::FromFormat("State %u", i).GetCharArray()))
DoLoadState(i);
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Save State"))
{
for (u32 i = 1; i <= 8; i++)
{
if (ImGui::MenuItem(TinyString::FromFormat("State %u", i).GetCharArray()))
DoSaveState(i);
}
ImGui::EndMenu();
}
if (ImGui::MenuItem("Exit"))
m_running = false;
ImGui::EndMenu();
}
if (ImGui::BeginMenu("View"))
{
if (ImGui::MenuItem("Fullscreen", nullptr, IsWindowFullscreen()))
SDL_SetWindowFullscreen(m_window, IsWindowFullscreen() ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
void SDLInterface::AddOSDMessage(const char* message, float duration /*= 2.0f*/)
{
OSDMessage msg;
msg.text = message;
msg.duration = duration;
std::unique_lock<std::mutex> lock(m_osd_messages_lock);
m_osd_messages.push_back(std::move(msg));
}
void SDLInterface::RenderOSDMessages()
{
constexpr ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing;
std::unique_lock<std::mutex> lock(m_osd_messages_lock);
auto iter = m_osd_messages.begin();
float position_x = 10.0f;
float position_y = 10.0f + 20.0f;
u32 index = 0;
while (iter != m_osd_messages.end())
{
const OSDMessage& msg = *iter;
const double time = msg.time.GetTimeSeconds();
const float time_remaining = static_cast<float>(msg.duration - time);
if (time_remaining <= 0.0f)
{
iter = m_osd_messages.erase(iter);
continue;
}
const float opacity = std::min(time_remaining, 1.0f);
ImGui::SetNextWindowPos(ImVec2(position_x, position_y));
ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, opacity);
if (ImGui::Begin(SmallString::FromFormat("osd_%u", index++), nullptr, window_flags))
{
ImGui::TextUnformatted(msg.text);
position_y += ImGui::GetWindowSize().y + (4.0f * ImGui::GetIO().DisplayFramebufferScale.x);
}
ImGui::End();
ImGui::PopStyleVar();
++iter;
}
}
void SDLInterface::DoLoadState(u32 index)
{
#if 0
Error error;
if (!LoadSystemState(TinyString::FromFormat("savestate_%u.bin", index), &error))
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Loading save state failed", error.GetErrorCodeAndDescription(),
m_window);
}
#endif
}
void SDLInterface::DoSaveState(u32 index)
{
#if 0
SaveSystemState(TinyString::FromFormat("savestate_%u.bin", index));
#endif
}
void SDLInterface::Run()
{
while (m_running)
{
for (;;)
{
SDL_Event ev;
if (SDL_PollEvent(&ev))
HandleSDLEvent(&ev);
else
break;
}
m_system->RunFrame();
Render();
}
}

View File

@ -0,0 +1,70 @@
#pragma once
#include "common/display_renderer.h"
#include "pse-sdl/sdl_audio_mixer.h"
#include <array>
#include <deque>
#include <mutex>
struct SDL_Window;
union SDL_Event;
class System;
class SDLInterface
{
public:
using MixerType = SDLAudioMixer;
// using MixerType = Audio::NullMixer;
SDLInterface(SDL_Window* window, std::unique_ptr<DisplayRenderer> display_renderer,
std::unique_ptr<MixerType> mixer);
~SDLInterface();
static std::unique_ptr<SDLInterface>
Create(DisplayRenderer::BackendType display_renderer_backend = DisplayRenderer::GetDefaultBackendType());
static TinyString GetSaveStateFilename(u32 index);
bool InitializeSystem(const char* filename, s32 save_state_index = -1);
DisplayRenderer* GetDisplayRenderer() const { return m_display_renderer.get(); }
Audio::Mixer* GetAudioMixer() const { return m_mixer.get(); }
void ReportMessage(const char* message);
void Run();
// Adds OSD messages, duration is in seconds.
void AddOSDMessage(const char* message, float duration = 2.0f);
protected:
struct OSDMessage
{
String text;
Timer time;
float duration;
};
// We only pass mouse input through if it's grabbed
bool IsWindowFullscreen() const;
void RenderImGui();
void DoLoadState(u32 index);
void DoSaveState(u32 index);
bool HandleSDLEvent(const SDL_Event* event);
bool PassEventToImGui(const SDL_Event* event);
void Render();
void RenderMainMenuBar();
void RenderOSDMessages();
SDL_Window* m_window;
std::unique_ptr<DisplayRenderer> m_display_renderer;
std::unique_ptr<MixerType> m_mixer;
std::unique_ptr<System> m_system;
std::deque<OSDMessage> m_osd_messages;
std::mutex m_osd_messages_lock;
bool m_running = false;
};