summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2019-11-26 15:25:19 +1100
committerStenzek <stenzek@gmail.com>2019-12-28 08:56:27 +1000
commit5a65031611349e22bdcd694479f11c91d87afca7 (patch)
tree4693fab8401d13e95d19a5443d8fd7e4924780d0 /Source/Core
parent0755f9297957881e5c487378a7ba0a9fe92cbd42 (diff)
Add a Win32 NoGUI platform and project
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinNoGUI/CMakeLists.txt4
-rw-r--r--Source/Core/DolphinNoGUI/DolphinNoGUI.exe.manifest30
-rw-r--r--Source/Core/DolphinNoGUI/DolphinNoGUI.rc6
-rw-r--r--Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj107
-rw-r--r--Source/Core/DolphinNoGUI/DolphinNoGUI.vcxproj.filters21
-rw-r--r--Source/Core/DolphinNoGUI/MainNoGUI.cpp17
-rw-r--r--Source/Core/DolphinNoGUI/Platform.h5
-rw-r--r--Source/Core/DolphinNoGUI/PlatformWin32.cpp201
-rw-r--r--Source/Core/DolphinNoGUI/resource.h24
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) -&gt; $(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