diff options
| author | Stenzek <stenzek@gmail.com> | 2019-11-26 15:25:19 +1100 |
|---|---|---|
| committer | Stenzek <stenzek@gmail.com> | 2019-12-28 08:56:27 +1000 |
| commit | 5a65031611349e22bdcd694479f11c91d87afca7 (patch) | |
| tree | 4693fab8401d13e95d19a5443d8fd7e4924780d0 /Source/Core | |
| parent | 0755f9297957881e5c487378a7ba0a9fe92cbd42 (diff) | |
Add a Win32 NoGUI platform and project
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/DolphinNoGUI/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/DolphinNoGUI.exe.manifest | 30 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/DolphinNoGUI.rc | 6 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj | 107 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj.filters | 21 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/MainNoGUI.cpp | 17 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/Platform.h | 5 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/PlatformWin32.cpp | 201 | ||||
| -rw-r--r-- | Source/Core/DolphinNoGUI/resource.h | 24 |
9 files changed, 415 insertions, 0 deletions
diff --git a/Source/Core/DolphinNoGUI/CMakeLists.txt b/Source/Core/DolphinNoGUI/CMakeLists.txt index 6247dac2d0..3943582ad2 100644 --- a/Source/Core/DolphinNoGUI/CMakeLists.txt +++ b/Source/Core/DolphinNoGUI/CMakeLists.txt @@ -9,6 +9,10 @@ if(ENABLE_X11 AND X11_FOUND) target_sources(dolphin-nogui PRIVATE PlatformX11.cpp) endif() +if(WIN32) + target_sources(dolphin-nogui PRIVATE PlatformWin32.cpp) +endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") target_sources(dolphin-nogui PRIVATE PlatformFBDev.cpp) endif() diff --git a/Source/Core/DolphinNoGUI/DolphinNoGUI.exe.manifest b/Source/Core/DolphinNoGUI/DolphinNoGUI.exe.manifest new file mode 100644 index 0000000000..69f9e43d44 --- /dev/null +++ b/Source/Core/DolphinNoGUI/DolphinNoGUI.exe.manifest @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> +<assemblyIdentity + version="1.0.0.0" + processorArchitecture="amd64" + name="DolphinTeam.DolphinEmuNoGUI" + type="win32" +/> +<description>Dolphin NoGUI Frontend</description> +<dependency> + <dependentAssembly> + <assemblyIdentity + type="win32" + name="Microsoft.Windows.Common-Controls" + version="6.0.0.0" + processorArchitecture="*" + publicKeyToken="6595b64144ccf1df" + language="*" + /> + </dependentAssembly> +</dependency> +<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> + </application> +</compatibility> +</assembly>
\ No newline at end of file diff --git a/Source/Core/DolphinNoGUI/DolphinNoGUI.rc b/Source/Core/DolphinNoGUI/DolphinNoGUI.rc new file mode 100644 index 0000000000..b1471b1760 --- /dev/null +++ b/Source/Core/DolphinNoGUI/DolphinNoGUI.rc @@ -0,0 +1,6 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" +IDI_ICON1 ICON "..\\..\\..\\Installer\\Dolphin.ico" +"dolphin" ICON "..\\..\\..\\Installer\\Dolphin.ico" + diff --git a/Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj b/Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj new file mode 100644 index 0000000000..2efd1ea4ce --- /dev/null +++ b/Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj @@ -0,0 +1,107 @@ +<?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|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{974E563D-23F8-4E8F-9083-F62876B04E08}</ProjectGuid> + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <UseDebugLibraries>true</UseDebugLibraries> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <UseDebugLibraries>false</UseDebugLibraries> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="..\..\VSProps\Base.props" /> + <Import Project="..\..\VSProps\PCHUse.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup /> + <ItemDefinitionGroup> + <Link> + <AdditionalDependencies>avrt.lib;iphlpapi.lib;winmm.lib;setupapi.lib;rpcrt4.lib;comctl32.lib;Shlwapi.lib;discord-rpc.lib;opengl32.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>$(ExternalsDir)ffmpeg\lib;$(IntDir)..\discord-rpc\bin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <SubSystem>Console</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\Externals\cpp-optparse\cpp-optparse.vcxproj"> + <Project>{c636d9d1-82fe-42b5-9987-63b7d4836341}</Project> + </ProjectReference> + <ProjectReference Include="..\Core\Core.vcxproj"> + <Project>{e54cf649-140e-4255-81a5-30a673c1fb36}</Project> + </ProjectReference> + <ProjectReference Include="..\UICommon\UICommon.vcxproj"> + <Project>{604c8368-f34a-4d55-82c8-cc92a0c13254}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoBackends\D3D\D3D.vcxproj"> + <Project>{96020103-4ba5-4fd2-b4aa-5b6d24492d4e}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoBackends\Null\Null.vcxproj"> + <Project>{53a5391b-737e-49a8-bc8f-312ada00736f}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoBackends\OGL\OGL.vcxproj"> + <Project>{ec1a314c-5588-4506-9c1e-2e58e5817f75}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoBackends\Software\Software.vcxproj"> + <Project>{a4c423aa-f57c-46c7-a172-d1a777017d29}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoBackends\Vulkan\Vulkan.vcxproj"> + <Project>{29f29a19-f141-45ad-9679-5a2923b49da3}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoCommon\VideoCommon.vcxproj"> + <Project>{3de9ee35-3e91-4f27-a014-2866ad8c3fe3}</Project> + </ProjectReference> + <ProjectReference Include="..\VideoBackends\D3D12\D3D12.vcxproj"> + <Project>{570215b7-e32f-4438-95ae-c8d955f9fca3}</Project> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <ClCompile Include="MainNoGUI.cpp" /> + <ClCompile Include="Platform.cpp" /> + <ClCompile Include="PlatformHeadless.cpp" /> + <ClCompile Include="PlatformWin32.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> + <!--Copy the .exe to binary output folder--> + <ItemGroup> + <SourceFiles Include="$(TargetPath)" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Platform.h" /> + </ItemGroup> + <ItemGroup> + <Manifest Include="DolphinNoGUI.exe.manifest" /> + </ItemGroup> + <ItemGroup> + <Text Include="CMakeLists.txt" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="DolphinNoGUI.rc" /> + </ItemGroup> + <Target Name="AfterBuild" Inputs="@(SourceFiles)" Outputs="@(SourceFiles -> '$(BinaryOutputDir)%(Filename)%(Extension)')"> + <Message Text="Copy: @(SourceFiles) -> $(BinaryOutputDir)" Importance="High" /> + <Copy SourceFiles="@(SourceFiles)" DestinationFolder="$(BinaryOutputDir)" /> + </Target> +</Project>
\ No newline at end of file diff --git a/Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj.filters b/Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj.filters new file mode 100644 index 0000000000..1a368e0465 --- /dev/null +++ b/Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj.filters @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="Platform.cpp" /> + <ClCompile Include="PlatformHeadless.cpp" /> + <ClCompile Include="MainNoGUI.cpp" /> + <ClCompile Include="PlatformWin32.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="Platform.h" /> + </ItemGroup> + <ItemGroup> + <Manifest Include="DolphinNoGUI.exe.manifest" /> + </ItemGroup> + <ItemGroup> + <Text Include="CMakeLists.txt" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="DolphinNoGUI.rc" /> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 8c27992201..14fac966c9 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -12,8 +12,11 @@ #include <string> #ifndef _WIN32 #include <unistd.h> +#else +#include <Windows.h> #endif +#include "Common/StringUtil.h" #include "Core/Analytics.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" @@ -121,6 +124,11 @@ static std::unique_ptr<Platform> GetPlatform(const optparse::Values& options) return Platform::CreateFBDevPlatform(); #endif +#ifdef _WIN32 + if (platform_name == "win32" || platform_name.empty()) + return Platform::CreateWin32Platform(); +#endif + if (platform_name == "headless" || platform_name.empty()) return Platform::CreateHeadlessPlatform(); @@ -143,6 +151,10 @@ int main(int argc, char* argv[]) , "x11" #endif +#ifdef _WIN32 + , + "win32" +#endif }); optparse::Values& options = CommandLineParse::ParseArguments(parser.get(), argc, argv); @@ -198,6 +210,10 @@ int main(int argc, char* argv[]) s_platform->Stop(); }); +#ifdef _WIN32 + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); +#else // Shut down cleanly on SIGINT and SIGTERM struct sigaction sa; sa.sa_handler = signal_handler; @@ -205,6 +221,7 @@ int main(int argc, char* argv[]) sa.sa_flags = SA_RESETHAND; sigaction(SIGINT, &sa, nullptr); sigaction(SIGTERM, &sa, nullptr); +#endif DolphinAnalytics::Instance().ReportDolphinStart("nogui"); diff --git a/Source/Core/DolphinNoGUI/Platform.h b/Source/Core/DolphinNoGUI/Platform.h index af39492447..b0d98e58be 100644 --- a/Source/Core/DolphinNoGUI/Platform.h +++ b/Source/Core/DolphinNoGUI/Platform.h @@ -35,10 +35,15 @@ public: #ifdef HAVE_X11 static std::unique_ptr<Platform> CreateX11Platform(); #endif + #ifdef __linux__ static std::unique_ptr<Platform> CreateFBDevPlatform(); #endif +#ifdef _WIN32 + static std::unique_ptr<Platform> CreateWin32Platform(); +#endif + protected: void UpdateRunningFlag(); diff --git a/Source/Core/DolphinNoGUI/PlatformWin32.cpp b/Source/Core/DolphinNoGUI/PlatformWin32.cpp new file mode 100644 index 0000000000..add981b361 --- /dev/null +++ b/Source/Core/DolphinNoGUI/PlatformWin32.cpp @@ -0,0 +1,201 @@ +// Copyright 2019 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinNoGUI/Platform.h" + +#include "Common/MsgHandler.h" +#include "Core/Config/MainSettings.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/State.h" + +#include <Windows.h> +#include <climits> +#include <cstdio> + +#include "VideoCommon/RenderBase.h" +#include "resource.h" + +namespace +{ +class PlatformWin32 : public Platform +{ +public: + ~PlatformWin32() override; + + bool Init() override; + void SetTitle(const std::string& string) override; + void MainLoop() override; + + WindowSystemInfo GetWindowSystemInfo() const; + +private: + static constexpr TCHAR WINDOW_CLASS_NAME[] = _T("DolphinNoGUI"); + + static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + bool RegisterRenderWindowClass(); + bool CreateRenderWindow(); + void UpdateWindowPosition(); + void ProcessEvents(); + + HWND m_hwnd{}; + + int m_window_x = Config::Get(Config::MAIN_RENDER_WINDOW_XPOS); + int m_window_y = Config::Get(Config::MAIN_RENDER_WINDOW_YPOS); + int m_window_width = Config::Get(Config::MAIN_RENDER_WINDOW_WIDTH); + int m_window_height = Config::Get(Config::MAIN_RENDER_WINDOW_HEIGHT); +}; + +PlatformWin32::~PlatformWin32() +{ + if (m_hwnd) + DestroyWindow(m_hwnd); +} + +bool PlatformWin32::RegisterRenderWindowClass() +{ + WNDCLASSEX wc = {}; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(nullptr); + wc.hIcon = LoadIcon(NULL, IDI_ICON1); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = WINDOW_CLASS_NAME; + wc.hIconSm = LoadIcon(NULL, IDI_ICON1); + + if (!RegisterClassEx(&wc)) + { + MessageBox(nullptr, _T("Window registration failed."), _T("Error"), MB_ICONERROR | MB_OK); + return false; + } + + return true; +} + +bool PlatformWin32::CreateRenderWindow() +{ + m_hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WINDOW_CLASS_NAME, _T("Dolphin"), WS_OVERLAPPEDWINDOW, + m_window_x < 0 ? CW_USEDEFAULT : m_window_x, + m_window_y < 0 ? CW_USEDEFAULT : m_window_y, m_window_width, + m_window_height, nullptr, nullptr, GetModuleHandle(nullptr), this); + if (!m_hwnd) + { + MessageBox(nullptr, _T("CreateWindowEx failed."), _T("Error"), MB_ICONERROR | MB_OK); + return false; + } + + ShowWindow(m_hwnd, SW_SHOW); + UpdateWindow(m_hwnd); + return true; +} + +bool PlatformWin32::Init() +{ + if (!RegisterRenderWindowClass() || !CreateRenderWindow()) + return false; + + // TODO: Enter fullscreen if enabled. + if (Config::Get(Config::MAIN_FULLSCREEN)) + { + ProcessEvents(); + } + + UpdateWindowPosition(); + return true; +} + +void PlatformWin32::SetTitle(const std::string& string) +{ + SetWindowTextW(m_hwnd, UTF8ToUTF16(string).c_str()); +} + +void PlatformWin32::MainLoop() +{ + while (IsRunning()) + { + UpdateRunningFlag(); + Core::HostDispatchJobs(); + ProcessEvents(); + UpdateWindowPosition(); + + // TODO: Is this sleep appropriate? + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } +} + +WindowSystemInfo PlatformWin32::GetWindowSystemInfo() const +{ + WindowSystemInfo wsi; + wsi.type = WindowSystemType::Windows; + wsi.render_surface = reinterpret_cast<void*>(m_hwnd); + return wsi; +} + +void PlatformWin32::UpdateWindowPosition() +{ + if (m_window_fullscreen) + return; + + RECT rc = {}; + if (!GetWindowRect(m_hwnd, &rc)) + return; + + m_window_x = rc.left; + m_window_y = rc.top; + m_window_width = rc.right - rc.left; + m_window_height = rc.bottom - rc.top; +} + +void PlatformWin32::ProcessEvents() +{ + MSG msg; + while (PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +LRESULT PlatformWin32::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + PlatformWin32* platform = reinterpret_cast<PlatformWin32*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + switch (msg) + { + case WM_NCCREATE: + { + platform = + reinterpret_cast<PlatformWin32*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams); + SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(platform)); + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + case WM_SIZE: + { + if (g_renderer) + g_renderer->ResizeSurface(); + } + break; + + case WM_CLOSE: + platform->RequestShutdown(); + break; + + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + + return 0; +} +} // namespace + +std::unique_ptr<Platform> Platform::CreateWin32Platform() +{ + return std::make_unique<PlatformWin32>(); +} diff --git a/Source/Core/DolphinNoGUI/resource.h b/Source/Core/DolphinNoGUI/resource.h new file mode 100644 index 0000000000..18fcdb7f0b --- /dev/null +++ b/Source/Core/DolphinNoGUI/resource.h @@ -0,0 +1,24 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DolphinNoGui.rc +// +#ifdef RC_INVOKED +#define IDI_ICON1 101 +#else +#define IDI_ICON1 MAKEINTRESOURCE(101) +#endif + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif |
