mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
UWP improvements 2
This commit is contained in:
parent
fb80dcacf7
commit
04d72ebe54
21 changed files with 401 additions and 200 deletions
|
@ -64,14 +64,10 @@ static EShLanguage GetShLanguageFromStage(const ShaderStage stage) {
|
|||
|
||||
void ShaderTranslationInit() {
|
||||
// TODO: We have TLS issues on UWP
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
glslang::InitializeProcess();
|
||||
#endif
|
||||
}
|
||||
void ShaderTranslationShutdown() {
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
glslang::FinalizeProcess();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct Builtin {
|
||||
|
@ -229,11 +225,6 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, const ShaderLan
|
|||
return result;
|
||||
}
|
||||
|
||||
#if PPSSPP_PLATFORM(UWP)
|
||||
*errorMessage = "No shader translation available (UWP)";
|
||||
return false;
|
||||
#endif
|
||||
|
||||
errorMessage->clear();
|
||||
|
||||
glslang::TProgram program;
|
||||
|
|
|
@ -305,7 +305,7 @@ void PostLoadConfig() {
|
|||
else
|
||||
g_i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath);
|
||||
|
||||
#if !PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
||||
#if !PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(UWP)
|
||||
CreateSysDirectories();
|
||||
#endif
|
||||
}
|
||||
|
|
65
UWP/App.cpp
65
UWP/App.cpp
|
@ -3,17 +3,20 @@
|
|||
#include "pch.h"
|
||||
#include "App.h"
|
||||
|
||||
#include <ppltasks.h>
|
||||
#include <mutex>
|
||||
|
||||
#include "Common/Net/HTTPClient.h"
|
||||
#include "Common/Net/Resolve.h"
|
||||
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/Input/InputState.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/LogManager.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Core.h"
|
||||
|
||||
#include <ppltasks.h>
|
||||
|
||||
#include "UWPHelpers/LaunchItem.h"
|
||||
|
||||
using namespace UWP;
|
||||
|
@ -27,7 +30,6 @@ using namespace Windows::UI::Input;
|
|||
using namespace Windows::System;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Graphics::Display;
|
||||
using namespace Windows::Storage;
|
||||
|
||||
// The main function is only used to initialize our IFrameworkView class.
|
||||
[Platform::MTAThread]
|
||||
|
@ -47,6 +49,50 @@ App::App() :
|
|||
{
|
||||
}
|
||||
|
||||
void App::InitialPPSSPP() {
|
||||
// Initial net
|
||||
net::Init();
|
||||
|
||||
//Prepare for initialization
|
||||
std::wstring internalDataFolderW = ApplicationData::Current->LocalFolder->Path->Data();
|
||||
g_Config.internalDataDirectory = Path(internalDataFolderW);
|
||||
g_Config.memStickDirectory = g_Config.internalDataDirectory;
|
||||
|
||||
// On Win32 it makes more sense to initialize the system directories here
|
||||
// because the next place it was called was in the EmuThread, and it's too late by then.
|
||||
CreateSysDirectories();
|
||||
|
||||
LogManager::Init(&g_Config.bEnableLogging);
|
||||
|
||||
// Set the config path to local state by default
|
||||
// it will be overrided by `NativeInit` if there is custom memStick
|
||||
g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM));
|
||||
g_Config.Load();
|
||||
|
||||
if (g_Config.bFirstRun) {
|
||||
// Clear `memStickDirectory` to show memory stick screen on first start
|
||||
g_Config.memStickDirectory.clear();
|
||||
}
|
||||
|
||||
// Since we don't have any async operation in `NativeInit`
|
||||
// it's better to call it here
|
||||
const char* argv[2] = { "fake", nullptr };
|
||||
std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data());
|
||||
// Ee will not be able to use `argv`
|
||||
// since launch parameters usually handled by `OnActivated`
|
||||
// and `OnActivated` will be invoked later, even after `PPSSPP_UWPMain(..)`
|
||||
// so we are handling launch cases using `LaunchItem`
|
||||
NativeInit(1, argv, "", "", cacheFolder.c_str());
|
||||
|
||||
// Override backend, `DIRECT3D11` is the only way for UWP apps
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
|
||||
// Calling `NativeInit` before will help us to deal with custom configs
|
||||
// such as custom adapter, so it's better to initial render device here
|
||||
m_deviceResources = std::make_shared<DX::DeviceResources>();
|
||||
m_deviceResources->CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
// The first method called when the IFrameworkView is being created.
|
||||
void App::Initialize(CoreApplicationView^ applicationView) {
|
||||
// Register event handlers for app lifecycle. This example includes Activated, so that we
|
||||
|
@ -59,10 +105,6 @@ void App::Initialize(CoreApplicationView^ applicationView) {
|
|||
|
||||
CoreApplication::Resuming +=
|
||||
ref new EventHandler<Platform::Object^>(this, &App::OnResuming);
|
||||
|
||||
// At this point we have access to the device.
|
||||
// We can create the device-dependent resources.
|
||||
m_deviceResources = std::make_shared<DX::DeviceResources>();
|
||||
}
|
||||
|
||||
// Called when the CoreWindow object is created (or re-created).
|
||||
|
@ -89,6 +131,7 @@ void App::SetWindow(CoreWindow^ window) {
|
|||
|
||||
window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyDown);
|
||||
window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyUp);
|
||||
window->CharacterReceived += ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &App::OnCharacterReceived);
|
||||
|
||||
window->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerMoved);
|
||||
window->PointerEntered += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerEntered);
|
||||
|
@ -111,7 +154,7 @@ void App::SetWindow(CoreWindow^ window) {
|
|||
Windows::UI::Core::BackRequestedEventArgs^>(
|
||||
this, &App::App_BackRequested);
|
||||
|
||||
m_deviceResources->SetWindow(window);
|
||||
InitialPPSSPP();
|
||||
}
|
||||
|
||||
bool App::HasBackButton() {
|
||||
|
@ -137,6 +180,10 @@ void App::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyE
|
|||
m_main->OnKeyUp(args->KeyStatus.ScanCode, args->VirtualKey);
|
||||
}
|
||||
|
||||
void App::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args) {
|
||||
m_main->OnCharacterReceived(args->KeyStatus.ScanCode, args->KeyCode);
|
||||
}
|
||||
|
||||
void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
|
||||
int pointerId = touchMap_.TouchId(args->CurrentPoint->PointerId);
|
||||
if (pointerId < 0)
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace UWP {
|
|||
// Input
|
||||
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
|
||||
void OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
|
||||
|
||||
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
|
@ -94,6 +95,7 @@ namespace UWP {
|
|||
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
|
||||
|
||||
void App_BackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ e);
|
||||
void InitialPPSSPP();
|
||||
|
||||
private:
|
||||
std::shared_ptr<DX::DeviceResources> m_deviceResources;
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#include "DeviceResources.h"
|
||||
#include "DirectXHelper.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
|
||||
using namespace D2D1;
|
||||
using namespace DirectX;
|
||||
using namespace Microsoft::WRL;
|
||||
|
@ -125,7 +129,7 @@ void DX::DeviceResources::CreateDeviceIndependentResources()
|
|||
}
|
||||
|
||||
// Configures the Direct3D device, and stores handles to it and the device context.
|
||||
void DX::DeviceResources::CreateDeviceResources()
|
||||
void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter)
|
||||
{
|
||||
// This flag adds support for surfaces with a different color channel ordering
|
||||
// than the API default. It is required for compatibility with Direct2D.
|
||||
|
@ -159,10 +163,10 @@ void DX::DeviceResources::CreateDeviceResources()
|
|||
// Create the Direct3D 11 API device object and a corresponding context.
|
||||
ComPtr<ID3D11Device> device;
|
||||
ComPtr<ID3D11DeviceContext> context;
|
||||
|
||||
auto hardwareType = (vAdapter != nullptr ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE);
|
||||
HRESULT hr = D3D11CreateDevice(
|
||||
nullptr, // Specify nullptr to use the default adapter.
|
||||
D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver.
|
||||
vAdapter, // Specify nullptr to use the default adapter.
|
||||
hardwareType, // Create a device using the hardware graphics driver.
|
||||
0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
|
||||
creationFlags, // Set debug and Direct2D compatibility flags.
|
||||
featureLevels, // List of feature levels this app can support.
|
||||
|
@ -194,6 +198,14 @@ void DX::DeviceResources::CreateDeviceResources()
|
|||
);
|
||||
}
|
||||
|
||||
if (!vAdapter && CreateAdaptersList(device)) {
|
||||
// While fetching the adapters list
|
||||
// we will check if the configs has custom adapter
|
||||
// then will recall this function to create device with custom adapter
|
||||
// so we have to stop here, if the `CreateAdaptersList` return true
|
||||
return;
|
||||
}
|
||||
|
||||
// Store pointers to the Direct3D 11.3 API device and immediate context.
|
||||
DX::ThrowIfFailed(
|
||||
device.As(&m_d3dDevice)
|
||||
|
@ -203,14 +215,25 @@ void DX::DeviceResources::CreateDeviceResources()
|
|||
context.As(&m_d3dContext)
|
||||
);
|
||||
|
||||
// Create the Direct2D device object and a corresponding context.
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice.As(&dxgiDevice)
|
||||
m_d3dDevice.As(&m_dxgiDevice)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
|
||||
m_dxgiDevice->GetAdapter(&m_dxgiAdapter)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_dxgiAdapter->GetParent(IID_PPV_ARGS(&m_dxgiFactory))
|
||||
);
|
||||
|
||||
// Create the Direct2D device object and a corresponding context.
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice.As(&m_dxgiDevice)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
m_d2dFactory->CreateDevice(m_dxgiDevice.Get(), &m_d2dDevice)
|
||||
);
|
||||
|
||||
DX::ThrowIfFailed(
|
||||
|
@ -221,9 +244,53 @@ void DX::DeviceResources::CreateDeviceResources()
|
|||
);
|
||||
}
|
||||
|
||||
bool DX::DeviceResources::CreateAdaptersList(ComPtr<ID3D11Device> device) {
|
||||
ComPtr<IDXGIDevice3> dxgi_device;
|
||||
DX::ThrowIfFailed(
|
||||
device.As(&dxgi_device)
|
||||
);
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter> deviceAdapter;
|
||||
dxgi_device->GetAdapter(&deviceAdapter);
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory4> deviceFactory;
|
||||
deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory));
|
||||
|
||||
UINT i = 0;
|
||||
IDXGIAdapter* pAdapter;
|
||||
IDXGIAdapter* customAdapter = nullptr;
|
||||
while (deviceFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
DXGI_ADAPTER_DESC vAdapterDesc;
|
||||
pAdapter->GetDesc(&vAdapterDesc);
|
||||
auto adapterDescription = ConvertWStringToUTF8(vAdapterDesc.Description);
|
||||
m_vAdapters.push_back(adapterDescription);
|
||||
if (g_Config.sD3D11Device == adapterDescription) {
|
||||
customAdapter = pAdapter;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
deviceFactory->Release();
|
||||
|
||||
bool reCreateDevice = false;
|
||||
if (customAdapter) {
|
||||
reCreateDevice = true;
|
||||
// Recreate device with custom adapter
|
||||
CreateDeviceResources(customAdapter);
|
||||
}
|
||||
|
||||
return reCreateDevice;
|
||||
}
|
||||
|
||||
// These resources need to be recreated every time the window size is changed.
|
||||
void DX::DeviceResources::CreateWindowSizeDependentResources()
|
||||
{
|
||||
// Window pointer was previously submited by `SetWindow` called from (App.cpp)
|
||||
// we don't have to do that since we can easily get the current window
|
||||
auto coreWindow = CoreWindow::GetForCurrentThread();
|
||||
|
||||
SetWindow(coreWindow);
|
||||
|
||||
// Clear the previous window size specific context.
|
||||
ID3D11RenderTargetView* nullViews[] = {nullptr};
|
||||
m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
|
||||
|
@ -287,27 +354,11 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
|
|||
swapChainDesc.Scaling = scaling;
|
||||
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
|
||||
// This sequence obtains the DXGI factory that was used to create the Direct3D device above.
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
DX::ThrowIfFailed(
|
||||
m_d3dDevice.As(&dxgiDevice)
|
||||
);
|
||||
|
||||
ComPtr<IDXGIAdapter> dxgiAdapter;
|
||||
DX::ThrowIfFailed(
|
||||
dxgiDevice->GetAdapter(&dxgiAdapter)
|
||||
);
|
||||
|
||||
ComPtr<IDXGIFactory4> dxgiFactory;
|
||||
DX::ThrowIfFailed(
|
||||
dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
|
||||
);
|
||||
|
||||
ComPtr<IDXGISwapChain1> swapChain;
|
||||
DX::ThrowIfFailed(
|
||||
dxgiFactory->CreateSwapChainForCoreWindow(
|
||||
m_dxgiFactory->CreateSwapChainForCoreWindow(
|
||||
m_d3dDevice.Get(),
|
||||
reinterpret_cast<IUnknown*>(m_window.Get()),
|
||||
reinterpret_cast<IUnknown*>(coreWindow),
|
||||
&swapChainDesc,
|
||||
nullptr,
|
||||
&swapChain
|
||||
|
@ -320,7 +371,7 @@ void DX::DeviceResources::CreateWindowSizeDependentResources()
|
|||
// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
|
||||
// ensures that the application will only render after each VSync, minimizing power consumption.
|
||||
DX::ThrowIfFailed(
|
||||
dxgiDevice->SetMaximumFrameLatency(1)
|
||||
m_dxgiDevice->SetMaximumFrameLatency(1)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -461,7 +512,6 @@ void DX::DeviceResources::SetWindow(CoreWindow^ window)
|
|||
{
|
||||
DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
|
||||
|
||||
m_window = window;
|
||||
if (Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily == L"Windows.Xbox")
|
||||
{
|
||||
const auto hdi = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView();
|
||||
|
@ -494,8 +544,6 @@ void DX::DeviceResources::SetWindow(CoreWindow^ window)
|
|||
m_currentOrientation = currentDisplayInformation->CurrentOrientation;
|
||||
|
||||
m_d2dContext->SetDpi(m_dpi, m_dpi);
|
||||
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
|
||||
// This method is called in the event handler for the SizeChanged event.
|
||||
|
@ -515,10 +563,8 @@ void DX::DeviceResources::SetDpi(float dpi)
|
|||
{
|
||||
m_dpi = dpi;
|
||||
|
||||
// When the display DPI changes, the logical size of the window (measured in Dips) also changes and needs to be updated.
|
||||
m_logicalSize = Windows::Foundation::Size(m_window->Bounds.Width, m_window->Bounds.Height);
|
||||
|
||||
m_d2dContext->SetDpi(m_dpi, m_dpi);
|
||||
// When the display DPI changes, the logical size of the window (measured in Dips)
|
||||
// also changes and needs to be updated.
|
||||
CreateWindowSizeDependentResources();
|
||||
}
|
||||
}
|
||||
|
@ -540,18 +586,8 @@ void DX::DeviceResources::ValidateDevice()
|
|||
// was created or if the device has been removed.
|
||||
|
||||
// First, get the information for the default adapter from when the device was created.
|
||||
|
||||
ComPtr<IDXGIDevice3> dxgiDevice;
|
||||
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
|
||||
|
||||
ComPtr<IDXGIAdapter> deviceAdapter;
|
||||
DX::ThrowIfFailed(dxgiDevice->GetAdapter(&deviceAdapter));
|
||||
|
||||
ComPtr<IDXGIFactory4> deviceFactory;
|
||||
DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory)));
|
||||
|
||||
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
|
||||
DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, &previousDefaultAdapter));
|
||||
DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));
|
||||
|
||||
DXGI_ADAPTER_DESC1 previousDesc;
|
||||
DX::ThrowIfFailed(previousDefaultAdapter->GetDesc1(&previousDesc));
|
||||
|
@ -575,9 +611,6 @@ void DX::DeviceResources::ValidateDevice()
|
|||
FAILED(m_d3dDevice->GetDeviceRemovedReason()))
|
||||
{
|
||||
// Release references to resources related to the old device.
|
||||
dxgiDevice = nullptr;
|
||||
deviceAdapter = nullptr;
|
||||
deviceFactory = nullptr;
|
||||
previousDefaultAdapter = nullptr;
|
||||
|
||||
// Create a new device and swap chain.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace DX
|
||||
{
|
||||
|
@ -14,6 +17,7 @@ namespace DX
|
|||
{
|
||||
public:
|
||||
DeviceResources();
|
||||
void CreateWindowSizeDependentResources();
|
||||
void SetWindow(Windows::UI::Core::CoreWindow^ window);
|
||||
void SetLogicalSize(Windows::Foundation::Size logicalSize);
|
||||
void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation);
|
||||
|
@ -52,16 +56,24 @@ namespace DX
|
|||
|
||||
DXGI_MODE_ROTATION ComputeDisplayRotation();
|
||||
|
||||
std::vector <std::string> GetAdapters() const { return m_vAdapters; };
|
||||
|
||||
private:
|
||||
void CreateDeviceIndependentResources();
|
||||
void CreateDeviceResources();
|
||||
void CreateWindowSizeDependentResources();
|
||||
void CreateDeviceResources(IDXGIAdapter* vAdapter = nullptr);
|
||||
void UpdateRenderTargetSize();
|
||||
bool CreateAdaptersList(Microsoft::WRL::ComPtr<ID3D11Device> device);
|
||||
|
||||
// Direct3D objects.
|
||||
Microsoft::WRL::ComPtr<ID3D11Device3> m_d3dDevice;
|
||||
Microsoft::WRL::ComPtr<ID3D11DeviceContext3> m_d3dContext;
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
|
||||
Microsoft::WRL::ComPtr<IDXGIDevice3> m_dxgiDevice;
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory4> m_dxgiFactory;
|
||||
Microsoft::WRL::ComPtr<IDXGIAdapter> m_dxgiAdapter;
|
||||
|
||||
// Direct3D adapters
|
||||
std::vector <std::string> m_vAdapters;
|
||||
|
||||
// Direct3D rendering objects. Required for 3D.
|
||||
Microsoft::WRL::ComPtr<ID3D11RenderTargetView1> m_d3dRenderTargetView;
|
||||
|
@ -77,9 +89,6 @@ namespace DX
|
|||
Microsoft::WRL::ComPtr<IDWriteFactory3> m_dwriteFactory;
|
||||
Microsoft::WRL::ComPtr<IWICImagingFactory2> m_wicFactory;
|
||||
|
||||
// Cached reference to the Window.
|
||||
Platform::Agile<Windows::UI::Core::CoreWindow> m_window;
|
||||
|
||||
// Cached device properties.
|
||||
D3D_FEATURE_LEVEL m_d3dFeatureLevel;
|
||||
Windows::Foundation::Size m_d3dRenderTargetSize;
|
||||
|
|
|
@ -73,6 +73,7 @@ std::map<Windows::System::VirtualKey, InputKeyCode> virtualKeyCodeToNKCode{
|
|||
{ VirtualKey::PageUp, NKCODE_PAGE_UP },
|
||||
{ VirtualKey::PageDown, NKCODE_PAGE_DOWN },
|
||||
{ VirtualKey::Delete, NKCODE_FORWARD_DEL },
|
||||
{ VirtualKey::Back, NKCODE_DEL },
|
||||
{ VirtualKey::End, NKCODE_MOVE_END },
|
||||
{ VirtualKey::Tab, NKCODE_TAB },
|
||||
{ VirtualKey::Down, NKCODE_DPAD_DOWN },
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "Common/System/Display.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/System/Request.h"
|
||||
#include <Common/OSVersion.h>
|
||||
#include "Common/OSVersion.h"
|
||||
|
||||
#include "Core/System.h"
|
||||
#include "Core/Loaders.h"
|
||||
|
@ -38,10 +38,11 @@
|
|||
#include "UWPUtil.h"
|
||||
#include "App.h"
|
||||
|
||||
// UWP Storage helper includes
|
||||
// UWP Helpers includes
|
||||
#include "UWPHelpers/StorageManager.h"
|
||||
#include "UWPHelpers/StorageAsync.h"
|
||||
#include "UWPHelpers/LaunchItem.h"
|
||||
#include <UWPHelpers/InputHelpers.h>
|
||||
|
||||
using namespace UWP;
|
||||
using namespace Windows::Foundation;
|
||||
|
@ -53,9 +54,7 @@ using namespace Windows::Devices::Enumeration;
|
|||
using namespace Concurrency;
|
||||
|
||||
// UGLY!
|
||||
PPSSPP_UWPMain *g_main;
|
||||
extern WindowsAudioBackend *winAudioBackend;
|
||||
std::string langRegion;
|
||||
std::list<std::unique_ptr<InputDevice>> g_input;
|
||||
|
||||
// TODO: Use Microsoft::WRL::ComPtr<> for D3D11 objects?
|
||||
|
@ -67,87 +66,29 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResourc
|
|||
app_(app),
|
||||
m_deviceResources(deviceResources)
|
||||
{
|
||||
g_main = this;
|
||||
|
||||
net::Init();
|
||||
|
||||
// Register to be notified if the Device is lost or recreated
|
||||
m_deviceResources->RegisterDeviceNotify(this);
|
||||
|
||||
// create_task(KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::RemovableDevices)).then([this](StorageFolder ^));
|
||||
|
||||
// TODO: Change the timer settings if you want something other than the default variable timestep mode.
|
||||
// e.g. for 60 FPS fixed timestep update logic, call:
|
||||
/*
|
||||
m_timer.SetFixedTimeStep(true);
|
||||
m_timer.SetTargetElapsedSeconds(1.0 / 60);
|
||||
*/
|
||||
|
||||
ctx_.reset(new UWPGraphicsContext(deviceResources));
|
||||
|
||||
const Path &exePath = File::GetExeDirectory();
|
||||
// Get install location
|
||||
auto packageDirectory = Package::Current->InstalledPath;
|
||||
const Path &exePath = Path(FromPlatformString(packageDirectory));
|
||||
g_VFS.Register("", new DirectoryReader(exePath / "Content"));
|
||||
g_VFS.Register("", new DirectoryReader(exePath));
|
||||
|
||||
wchar_t lcCountry[256];
|
||||
|
||||
if (0 != GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, lcCountry, 256)) {
|
||||
langRegion = ConvertWStringToUTF8(lcCountry);
|
||||
for (size_t i = 0; i < langRegion.size(); i++) {
|
||||
if (langRegion[i] == '-')
|
||||
langRegion[i] = '_';
|
||||
}
|
||||
} else {
|
||||
langRegion = "en_US";
|
||||
}
|
||||
|
||||
std::wstring internalDataFolderW = ApplicationData::Current->LocalFolder->Path->Data();
|
||||
g_Config.internalDataDirectory = Path(internalDataFolderW);
|
||||
g_Config.memStickDirectory = g_Config.internalDataDirectory;
|
||||
// Mount a filesystem
|
||||
g_Config.flash0Directory = exePath / "assets/flash0";
|
||||
|
||||
// On Win32 it makes more sense to initialize the system directories here
|
||||
// because the next place it was called was in the EmuThread, and it's too late by then.
|
||||
CreateSysDirectories();
|
||||
|
||||
LogManager::Init(&g_Config.bEnableLogging);
|
||||
|
||||
// Load config up here, because those changes below would be overwritten
|
||||
// if it's not loaded here first.
|
||||
g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM));
|
||||
g_Config.Load();
|
||||
|
||||
if (g_Config.bFirstRun) {
|
||||
g_Config.memStickDirectory.clear();
|
||||
}
|
||||
|
||||
bool debugLogLevel = false;
|
||||
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
|
||||
if (debugLogLevel) {
|
||||
#if _DEBUG
|
||||
LogManager::GetInstance()->SetAllLogLevels(LogTypes::LDEBUG);
|
||||
}
|
||||
|
||||
// Set log file location
|
||||
if (g_Config.bEnableLogging) {
|
||||
LogManager::GetInstance()->ChangeFileLog(GetLogFile().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *argv[2] = { "fake", nullptr };
|
||||
int argc = 1;
|
||||
|
||||
std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data());
|
||||
|
||||
// 'PPSSPP_UWPMain' is getting called before 'OnActivated'
|
||||
// this make detecting launch items on startup hard
|
||||
// I think 'Init' process must be moved out and invoked from 'OnActivated' one time only
|
||||
// currently launchItem will work fine but we cannot skip logo screen
|
||||
// we should pass file path to 'argv' using 'GetLaunchItemPath(args)'
|
||||
// instead of depending on 'boot_filename' (LaunchItem.cpp)
|
||||
NativeInit(argc, argv, "", "", cacheFolder.c_str());
|
||||
|
||||
// At this point we have main requirements initialized (Log, Config, NativeInit, Device)
|
||||
NativeInitGraphics(ctx_.get());
|
||||
NativeResized();
|
||||
|
||||
|
@ -185,15 +126,10 @@ void PPSSPP_UWPMain::CreateWindowSizeDependentResources() {
|
|||
ctx_->GetDrawContext()->HandleEvent(Draw::Event::GOT_BACKBUFFER, width, height, m_deviceResources->GetBackBufferRenderTargetView());
|
||||
}
|
||||
|
||||
// Renders the current frame according to the current application state.
|
||||
// Returns true if the frame was rendered and is ready to be displayed.
|
||||
bool PPSSPP_UWPMain::Render() {
|
||||
static bool hasSetThreadName = false;
|
||||
if (!hasSetThreadName) {
|
||||
SetCurrentThreadName("UWPRenderThread");
|
||||
hasSetThreadName = true;
|
||||
}
|
||||
|
||||
void PPSSPP_UWPMain::UpdateScreenState() {
|
||||
// This code was included into the render loop directly
|
||||
// based on my test I don't understand why it should be called each loop
|
||||
// is it better to call it on demand only, like when screen state changed?
|
||||
auto context = m_deviceResources->GetD3DDeviceContext();
|
||||
|
||||
switch (m_deviceResources->ComputeDisplayRotation()) {
|
||||
|
@ -232,6 +168,18 @@ bool PPSSPP_UWPMain::Render() {
|
|||
g_display.dp_yres = g_display.pixel_yres * g_display.dpi_scale_y;
|
||||
|
||||
context->RSSetViewports(1, &viewport);
|
||||
}
|
||||
|
||||
// Renders the current frame according to the current application state.
|
||||
// Returns true if the frame was rendered and is ready to be displayed.
|
||||
bool PPSSPP_UWPMain::Render() {
|
||||
static bool hasSetThreadName = false;
|
||||
if (!hasSetThreadName) {
|
||||
SetCurrentThreadName("UWPRenderThread");
|
||||
hasSetThreadName = true;
|
||||
}
|
||||
|
||||
UpdateScreenState();
|
||||
|
||||
NativeFrame(ctx_.get());
|
||||
return true;
|
||||
|
@ -271,6 +219,17 @@ void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKe
|
|||
}
|
||||
}
|
||||
|
||||
void PPSSPP_UWPMain::OnCharacterReceived(int scanCode, unsigned int keyCode) {
|
||||
// TODO: Once on-screen keyboard show/hide solved, add `InputPaneVisible()` as extra condition
|
||||
if (!PSP_IsInited() && !IsCtrlOnHold()) {
|
||||
KeyInput key{};
|
||||
key.deviceId = DEVICE_ID_KEYBOARD;
|
||||
key.keyCode = (InputKeyCode)keyCode;
|
||||
key.flags = KEY_DOWN | KEY_CHAR;
|
||||
NativeKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
void PPSSPP_UWPMain::OnMouseWheel(float delta) {
|
||||
InputKeyCode key = NKCODE_EXT_MOUSEWHEEL_UP;
|
||||
if (delta < 0) {
|
||||
|
@ -335,7 +294,7 @@ void PPSSPP_UWPMain::OnSuspend() {
|
|||
|
||||
|
||||
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
|
||||
std::vector<std::string> adapterNames;
|
||||
std::vector<std::string> adapterNames = resources->GetAdapters();
|
||||
|
||||
draw_ = Draw::T3DCreateD3D11Context(
|
||||
resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetSwapChain(), resources->GetDeviceFeatureLevel(), 0, adapterNames, g_Config.iInflightFrames);
|
||||
|
@ -353,7 +312,7 @@ std::string System_GetProperty(SystemProperty prop) {
|
|||
case SYSPROP_NAME:
|
||||
return GetWindowsVersion();
|
||||
case SYSPROP_LANGREGION:
|
||||
return langRegion;
|
||||
return GetLangRegion();
|
||||
case SYSPROP_CLIPBOARD_TEXT:
|
||||
/* TODO: Need to either change this API or do this on a thread in an ugly fashion.
|
||||
DataPackageView ^view = Clipboard::GetContent();
|
||||
|
@ -412,13 +371,17 @@ int System_GetPropertyInt(SystemProperty prop) {
|
|||
case SYSPROP_DISPLAY_XRES:
|
||||
{
|
||||
CoreWindow^ corewindow = CoreWindow::GetForCurrentThread();
|
||||
if (corewindow) {
|
||||
return (int)corewindow->Bounds.Width;
|
||||
}
|
||||
}
|
||||
case SYSPROP_DISPLAY_YRES:
|
||||
{
|
||||
CoreWindow^ corewindow = CoreWindow::GetForCurrentThread();
|
||||
if (corewindow) {
|
||||
return (int)corewindow->Bounds.Height;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -464,7 +427,12 @@ bool System_GetPropertyBool(SystemProperty prop) {
|
|||
case SYSPROP_CAN_JIT:
|
||||
return true;
|
||||
case SYSPROP_HAS_KEYBOARD:
|
||||
return true;
|
||||
{
|
||||
// Do actual check
|
||||
// touch devices has input pane, we need to depend on it
|
||||
// I don't know any possible way to display input dialog in non-xaml apps
|
||||
return isKeybaordAvailable() || isTouchAvailable();
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -576,6 +544,24 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
|
|||
if (!param1.empty() && !strcmp(param1.c_str(), "menu")) {
|
||||
CloseLaunchItem();
|
||||
}
|
||||
else if (!strcmp(param1.c_str(), "show_keyboard")) {
|
||||
// Must be performed from UI thread
|
||||
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||
CoreDispatcherPriority::Normal,
|
||||
ref new Windows::UI::Core::DispatchedHandler([]()
|
||||
{
|
||||
ShowInputPane();
|
||||
}));
|
||||
}
|
||||
else if (!strcmp(param1.c_str(), "hide_keyboard")) {
|
||||
// Must be performed from UI thread
|
||||
Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
|
||||
CoreDispatcherPriority::Normal,
|
||||
ref new Windows::UI::Core::DispatchedHandler([]()
|
||||
{
|
||||
HideInputPane();
|
||||
}));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case SystemRequestType::COPY_TO_CLIPBOARD:
|
||||
|
@ -695,20 +681,3 @@ std::string GetCPUBrandString() {
|
|||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// Emulation of TlsAlloc for Windows 10. Used by glslang. Doesn't actually seem to work, other than fixing the linking errors?
|
||||
|
||||
extern "C" {
|
||||
DWORD WINAPI __imp_TlsAlloc() {
|
||||
return FlsAlloc(nullptr);
|
||||
}
|
||||
BOOL WINAPI __imp_TlsFree(DWORD index) {
|
||||
return FlsFree(index);
|
||||
}
|
||||
BOOL WINAPI __imp_TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) {
|
||||
return FlsSetValue(dwTlsIndex, lpTlsValue);
|
||||
}
|
||||
LPVOID WINAPI __imp_TlsGetValue(DWORD dwTlsIndex) {
|
||||
return FlsGetValue(dwTlsIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResources>& deviceResources);
|
||||
~PPSSPP_UWPMain();
|
||||
void CreateWindowSizeDependentResources();
|
||||
void UpdateScreenState();
|
||||
bool Render();
|
||||
|
||||
// IDeviceNotify
|
||||
|
@ -44,6 +45,7 @@ public:
|
|||
// Not sure whether this abstraction is worth it.
|
||||
void OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount);
|
||||
void OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKey);
|
||||
void OnCharacterReceived(int scanCode,unsigned int keyCode);
|
||||
|
||||
void OnTouchEvent(int touchEvent, int touchId, float x, float y, double timestamp);
|
||||
|
||||
|
@ -57,8 +59,6 @@ public:
|
|||
void OnSuspend();
|
||||
void Close();
|
||||
|
||||
void LoadStorageFile(Windows::Storage::StorageFile ^file);
|
||||
|
||||
private:
|
||||
App ^app_;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
||||
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.15.4.0" />
|
||||
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.16.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="0ad29e1a-1069-4cf5-8c97-620892505f0c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP - PSP emulator</DisplayName>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
||||
<Identity Name="32617401-c880-44d1-ba5a-c0b46feba525" Publisher="CN=Henrik" Version="1.15.4.0" />
|
||||
<Identity Name="32617401-c880-44d1-ba5a-c0b46feba525" Publisher="CN=Henrik" Version="1.16.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="32617401-c880-44d1-ba5a-c0b46feba525" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP Gold - PSP emulator</DisplayName>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
|
||||
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.15.4.0" />
|
||||
<Identity Name="0ad29e1a-1069-4cf5-8c97-620892505f0c" Publisher="CN=Henrik" Version="1.16.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="0ad29e1a-1069-4cf5-8c97-620892505f0c" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>PPSSPP - PSP emulator</DisplayName>
|
||||
|
|
|
@ -77,7 +77,6 @@
|
|||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
|
||||
<AppxBundle>Never</AppxBundle>
|
||||
<PackageCertificateThumbprint>C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA</PackageCertificateThumbprint>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppInstallerUpdateFrequency>0</AppInstallerUpdateFrequency>
|
||||
<AppInstallerCheckForUpdateFrequency>OnApplicationRun</AppInstallerCheckForUpdateFrequency>
|
||||
|
@ -372,6 +371,7 @@
|
|||
<ClInclude Include="PPSSPP_UWPMain.h" />
|
||||
<ClInclude Include="Common\DirectXHelper.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="UWPHelpers\InputHelpers.h" />
|
||||
<ClInclude Include="UWPUtil.h" />
|
||||
<ClInclude Include="XAudioSoundStream.h" />
|
||||
<ClInclude Include="UWPHelpers\StorageAccess.h" />
|
||||
|
@ -398,6 +398,7 @@
|
|||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\InputHelpers.cpp" />
|
||||
<ClCompile Include="XAudioSoundStream.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -126,6 +126,9 @@
|
|||
<ClCompile Include="UWPHelpers\LaunchItem.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UWPHelpers\InputHelpers.cpp">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="App.h" />
|
||||
|
@ -145,6 +148,9 @@
|
|||
<ClInclude Include="..\Windows\InputDevice.h">
|
||||
<Filter>Input</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UWPHelpers\InputHelpers.h">
|
||||
<Filter>UWPHelpers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Assets\StoreLogo.png">
|
||||
|
|
95
UWP/UWPHelpers/InputHelpers.cpp
Normal file
95
UWP/UWPHelpers/InputHelpers.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
// Copyright (c) 2023- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
|
||||
#include "InputHelpers.h"
|
||||
#include "UWPUtil.h"
|
||||
#include "NKCodeFromWindowsSystem.h"
|
||||
#include "Common/Log.h"
|
||||
|
||||
using namespace Windows::System;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::UI::Core;
|
||||
using namespace Windows::UI::ViewManagement;
|
||||
using namespace Windows::ApplicationModel::Core;
|
||||
using namespace Windows::Data::Xml::Dom;
|
||||
using namespace Windows::UI::Notifications;
|
||||
|
||||
#pragma region Input Keyboard
|
||||
|
||||
bool isKeybaordAvailable() {
|
||||
Windows::Devices::Input::KeyboardCapabilities^ keyboardCapabilities = ref new Windows::Devices::Input::KeyboardCapabilities();
|
||||
bool hasKeyboard = keyboardCapabilities->KeyboardPresent != 0;
|
||||
return hasKeyboard;
|
||||
}
|
||||
|
||||
bool isTouchAvailable() {
|
||||
Windows::Devices::Input::TouchCapabilities^ touchCapabilities = ref new Windows::Devices::Input::TouchCapabilities();
|
||||
bool hasTouch = touchCapabilities->TouchPresent != 0;
|
||||
return hasTouch;
|
||||
}
|
||||
|
||||
bool keyboardVisible = false;
|
||||
bool InputPaneVisible() {
|
||||
return keyboardVisible;
|
||||
}
|
||||
|
||||
|
||||
void ShowInputPane() {
|
||||
VERBOSE_LOG(COMMON, "ShowInputKeyboard");
|
||||
InputPane::GetForCurrentView()->TryShow();
|
||||
keyboardVisible = true;
|
||||
}
|
||||
|
||||
void HideInputPane() {
|
||||
VERBOSE_LOG(COMMON, "HideInputKeyboard");
|
||||
InputPane::GetForCurrentView()->TryHide();
|
||||
keyboardVisible = false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Keys Status
|
||||
bool IsCapsLockOn() {
|
||||
auto capsLockState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::CapitalLock);
|
||||
return (capsLockState == CoreVirtualKeyStates::Locked);
|
||||
}
|
||||
bool IsShiftOnHold() {
|
||||
auto shiftState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::Shift);
|
||||
return (shiftState == CoreVirtualKeyStates::Down);
|
||||
}
|
||||
bool IsCtrlOnHold() {
|
||||
auto ctrlState = CoreApplication::MainView->CoreWindow->GetKeyState(VirtualKey::Control);
|
||||
return (ctrlState == CoreVirtualKeyStates::Down);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Misc
|
||||
std::string GetLangRegion() {
|
||||
std::string langRegion = "en_US";
|
||||
wchar_t lcCountry[256];
|
||||
|
||||
if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, lcCountry, 256) != FALSE) {
|
||||
langRegion = ConvertWStringToUTF8(lcCountry);
|
||||
for (size_t i = 0; i < langRegion.size(); i++) {
|
||||
if (langRegion[i] == '-')
|
||||
langRegion[i] = '_';
|
||||
}
|
||||
}
|
||||
return langRegion;
|
||||
}
|
||||
#pragma endregion
|
37
UWP/UWPHelpers/InputHelpers.h
Normal file
37
UWP/UWPHelpers/InputHelpers.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2023- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
// Input Devices
|
||||
bool isKeybaordAvailable();
|
||||
bool isTouchAvailable();
|
||||
|
||||
// Input Pane
|
||||
bool InputPaneVisible();
|
||||
void ShowInputPane();
|
||||
void HideInputPane();
|
||||
|
||||
|
||||
// Keys Status
|
||||
bool IsCapsLockOn();
|
||||
bool IsShiftOnHold();
|
||||
bool IsCtrlOnHold();
|
||||
|
||||
// Misc
|
||||
std::string GetLangRegion();
|
|
@ -21,18 +21,15 @@
|
|||
#include <regex>
|
||||
|
||||
#include "LaunchItem.h"
|
||||
#include "StorageAccess.h"
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include <Common/System/System.h>
|
||||
#include <Common/File/Path.h>
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/File/Path.h"
|
||||
#include "UWPUtil.h"
|
||||
|
||||
|
||||
extern void AddItemToFutureList(IStorageItem^ item);
|
||||
|
||||
// Temporary to handle startup items
|
||||
// See remarks at 'PPSSPP_UWPMain.cpp', above 'NativeInit(..)'
|
||||
extern Path boot_filename;
|
||||
#include <ppl.h>
|
||||
#include <ppltasks.h>
|
||||
|
||||
#pragma region LaunchItemClass
|
||||
class LaunchItem {
|
||||
|
@ -93,10 +90,13 @@ public:
|
|||
|
||||
void Start() {
|
||||
if (IsValid()) {
|
||||
concurrency::create_task([&] {
|
||||
SetState(true);
|
||||
std::string path = GetFilePath();
|
||||
// Delay to be able to launch on startup too
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
System_PostUIMessage("boot", path.c_str());
|
||||
boot_filename = Path(path); // Temporary to handle startup items
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,6 @@ public:
|
|||
}
|
||||
}
|
||||
launchOnExit = std::string();
|
||||
boot_filename.clear(); // Temporary to handle startup items
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "Common/File/Path.h"
|
||||
|
||||
using namespace Platform;
|
||||
using namespace Windows::Storage;
|
||||
using namespace Windows::Foundation;
|
||||
using namespace Windows::Foundation::Collections;
|
||||
using namespace Windows::Storage::AccessCache;
|
||||
|
|
|
@ -15,12 +15,18 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
// This header meant to be included within the storage manager
|
||||
// don't use it within PPSSPP core
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
using namespace Windows::Storage;
|
||||
|
||||
// Local settings
|
||||
std::string GetDataFromLocalSettings(std::string key);
|
||||
bool AddDataToLocalSettings(std::string key, std::string data, bool replace);
|
||||
void AddItemToFutureList(IStorageItem^ item);
|
||||
std::list<std::string> GetFutureAccessList();
|
||||
|
|
|
@ -87,7 +87,7 @@ std::string GetMusicFolder() {
|
|||
std::string GetPreviewPath(std::string path) {
|
||||
std::string pathView = path;
|
||||
pathView = ReplaceAll(pathView, "/", "\\");
|
||||
std::string currentMemoryStick = ConvertWStringToUTF8(g_Config.memStickDirectory.ToWString());
|
||||
std::string currentMemoryStick = GetPSPFolder();
|
||||
// Ensure memStick sub path replaced by 'ms:'
|
||||
pathView = ReplaceAll(pathView, currentMemoryStick + "\\", "ms:\\");
|
||||
auto appData = ReplaceAll(GetLocalFolder(), "\\LocalState", "");
|
||||
|
@ -349,6 +349,13 @@ bool OpenFolder(std::string path) {
|
|||
bool GetDriveFreeSpace(Path path, int64_t& space) {
|
||||
|
||||
bool state = false;
|
||||
if (path.empty()) {
|
||||
// This case happen on first start only
|
||||
path = Path(GetPSPFolder());
|
||||
if (g_Config.memStickDirectory.empty()) {
|
||||
g_Config.memStickDirectory = path;
|
||||
}
|
||||
}
|
||||
Platform::String^ wString = ref new Platform::String(path.ToWString().c_str());
|
||||
StorageFolder^ storageItem;
|
||||
ExecuteTask(storageItem, StorageFolder::GetFolderFromPathAsync(wString));
|
||||
|
@ -377,7 +384,7 @@ bool GetDriveFreeSpace(Path path, int64_t& space) {
|
|||
#pragma region Logs
|
||||
std::string GetLogFile() {
|
||||
std::string logFile;
|
||||
Path logFilePath = Path(GetPSPFolder() + "\\PSP\\ppsspp.txt");
|
||||
Path logFilePath = Path(GetPSPFolder() + "\\PSP\\ppsspplog.txt");
|
||||
HANDLE h = CreateFile2FromAppW(logFilePath.ToWString().c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS, nullptr);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
logFile = logFilePath.ToString();
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "Common/File/DirListing.h"
|
||||
|
||||
#include "StorageAccess.h"
|
||||
#include "StoragePickers.h"
|
||||
|
||||
// Locations
|
||||
|
|
Loading…
Add table
Reference in a new issue