UWP: Hook up basic touch/mouse input. Start work on loading from a StorageFile. Getting closer to starting to boot a game

This commit is contained in:
Henrik Rydgard 2017-02-27 11:32:40 +01:00 committed by Henrik Rydgård
parent 86f4559748
commit 4ced81b1df
22 changed files with 630 additions and 38 deletions

View File

@ -280,7 +280,7 @@ void FreeAlignedMemory(void* ptr) {
bool PlatformIsWXExclusive() {
// Only iOS really needs this mode currently. Even without block linking, still should be much faster than IR JIT.
// This might also come in useful for UWP (Universal Windows Platform) if I'm understanding things correctly.
#ifdef IOS
#if defined(IOS) || PPSSPP_PLATFORM(UWP)
return true;
#else
// Returning true here lets you test the W^X path on Windows and other non-W^X platforms.

View File

@ -35,9 +35,22 @@
#include "Core/ELF/PBPReader.h"
#include "Core/ELF/ParamSFO.h"
// Gross, gross hack! But necessary for UWP, fitting it in neatly would be a major refactor
FileLoader *g_OverriddenLoader;
IdentifiedFileType g_OverriddenFiletype;
void OverrideNextLoader(FileLoader *fileLoader, IdentifiedFileType fileType) {
g_OverriddenLoader = fileLoader;
g_OverriddenFiletype = fileType;
}
FileLoader *ConstructFileLoader(const std::string &filename) {
if (filename.find("http://") == 0 || filename.find("https://") == 0)
return new CachingFileLoader(new DiskCachingFileLoader(new RetryingFileLoader(new HTTPFileLoader(filename))));
if (filename == "override://") {
g_OverriddenLoader = nullptr;
return g_OverriddenLoader;
}
return new LocalFileLoader(filename);
}

View File

@ -18,6 +18,7 @@
#pragma once
#include <string>
#include "Common/CommonTypes.h"
enum class IdentifiedFileType {
ERROR_IDENTIFYING,
@ -100,5 +101,7 @@ std::string ResolvePBPFile(const std::string &filename);
IdentifiedFileType Identify_File(FileLoader *fileLoader);
void OverrideNextLoader(FileLoader *fileLoader, IdentifiedFileType fileType);
// Can modify the string filename, as it calls IdentifyFile above.
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string);

View File

@ -228,7 +228,7 @@ bool GameInfo::LoadFromPath(const std::string &gamePath) {
title = File::GetFilename(filePath_);
}
return GetFileLoader()->Exists();
return fileLoader ? fileLoader->Exists() : true;
}
FileLoader *GameInfo::GetFileLoader() {

View File

@ -18,6 +18,7 @@
#include <cmath>
#include <algorithm>
#include "ppsspp_config.h"
#include "base/colorutil.h"
#include "base/display.h"
#include "base/timeutil.h"
@ -857,8 +858,12 @@ void MainScreen::CreateViews() {
gold->OnClick.Handle(this, &MainScreen::OnSupport);
gold->SetIcon(I_ICONGOLD);
#endif
#if !PPSSPP_PLATFORM(UWP)
// Having an exit button is against UWP guidelines.
rightColumnItems->Add(new Spacer(25.0));
rightColumnItems->Add(new Choice(mm->T("Exit")))->OnClick.Handle(this, &MainScreen::OnExit);
#endif
if (vertical) {
root_ = new LinearLayout(ORIENT_VERTICAL);
@ -972,6 +977,8 @@ UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) {
g_Config.Save();
screenManager()->switchScreen(new EmuScreen(fileName.toStdString()));
}
#elif PPSSPP_PLATFORM(UWP)
System_SendMessage("browse_file", "");
#elif defined(USING_WIN_UI)
MainWindow::BrowseAndBoot("");
#endif

View File

@ -1,6 +1,10 @@
#include "pch.h"
#include "App.h"
#include <mutex>
#include "input/input_state.h"
#include <ppltasks.h>
using namespace UWP;
@ -76,6 +80,14 @@ 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->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerMoved);
window->PointerEntered += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerEntered);
window->PointerExited += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerExited);
window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerPressed);
window->PointerReleased += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerReleased);
window->PointerCaptureLost += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerCaptureLost);
window->PointerWheelChanged += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerWheelChanged);
m_deviceResources->SetWindow(window);
}
@ -87,11 +99,53 @@ void App::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyE
m_main->OnKeyUp(args->KeyStatus.ScanCode, args->VirtualKey);
}
void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
int pointerId = args->CurrentPoint->PointerId;
float X = args->CurrentPoint->Position.X;
float Y = args->CurrentPoint->Position.Y;
int64_t timestamp = args->CurrentPoint->Timestamp;
m_main->OnTouchEvent(TOUCH_MOVE, pointerId, X, Y, timestamp);
}
void App::OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
}
void App::OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
}
void App::OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
int pointerId = args->CurrentPoint->PointerId;
float X = args->CurrentPoint->Position.X;
float Y = args->CurrentPoint->Position.Y;
int64_t timestamp = args->CurrentPoint->Timestamp;
m_main->OnTouchEvent(TOUCH_DOWN|TOUCH_MOVE, pointerId, X, Y, timestamp);
sender->SetPointerCapture();
}
void App::OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
int pointerId = args->CurrentPoint->PointerId;
float X = args->CurrentPoint->Position.X;
float Y = args->CurrentPoint->Position.Y;
int64_t timestamp = args->CurrentPoint->Timestamp;
m_main->OnTouchEvent(TOUCH_UP|TOUCH_MOVE, pointerId, X, Y, timestamp);
sender->ReleasePointerCapture();
}
void App::OnPointerCaptureLost(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
}
void App::OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
int pointerId = args->CurrentPoint->PointerId;
float X = args->CurrentPoint->Position.X;
float Y = args->CurrentPoint->Position.Y;
int64_t timestamp = args->CurrentPoint->Timestamp;
m_main->OnTouchEvent(TOUCH_WHEEL, pointerId, X, Y, timestamp);
}
// Initializes scene resources, or loads a previously saved app state.
void App::Load(Platform::String^ entryPoint) {
if (m_main == nullptr) {
m_main = std::unique_ptr<PPSSPP_UWPMain>(new PPSSPP_UWPMain(m_deviceResources));
m_main = std::unique_ptr<PPSSPP_UWPMain>(new PPSSPP_UWPMain(this, m_deviceResources));
}
}
@ -130,10 +184,7 @@ void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
create_task([this, deferral]() {
m_deviceResources->Trim();
// Insert your code here.
m_deviceResources->Trim();
deferral->Complete();
});
}
@ -148,8 +199,7 @@ void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) {
// Window event handlers.
void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
{
void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) {
m_deviceResources->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height));
m_main->CreateWindowSizeDependentResources();
}

View File

@ -7,8 +7,7 @@
namespace UWP
{
// Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events.
ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
{
ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView {
public:
App();
@ -39,6 +38,14 @@ namespace UWP
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 OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerCaptureLost(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
private:
std::shared_ptr<DX::DeviceResources> m_deviceResources;
std::unique_ptr<PPSSPP_UWPMain> m_main;

View File

@ -288,7 +288,6 @@
<ClInclude Include="..\..\ext\native\ui\ui_screen.h" />
<ClInclude Include="..\..\ext\native\ui\view.h" />
<ClInclude Include="..\..\ext\native\ui\viewgroup.h" />
<ClInclude Include="..\..\ext\native\ui\virtual_input.h" />
<ClInclude Include="..\..\ext\native\util\const_map.h" />
<ClInclude Include="..\..\ext\native\util\hash\hash.h" />
<ClInclude Include="..\..\ext\native\util\random\rng.h" />
@ -969,7 +968,6 @@
<ClCompile Include="..\..\ext\native\ui\ui_screen.cpp" />
<ClCompile Include="..\..\ext\native\ui\view.cpp" />
<ClCompile Include="..\..\ext\native\ui\viewgroup.cpp" />
<ClCompile Include="..\..\ext\native\ui\virtual_input.cpp" />
<ClCompile Include="..\..\ext\native\util\hash\hash.cpp" />
<ClCompile Include="..\..\ext\native\util\text\parsers.cpp" />
<ClCompile Include="..\..\ext\native\util\text\utf8.cpp" />

View File

@ -163,9 +163,6 @@
<ClCompile Include="..\..\ext\native\ui\viewgroup.cpp">
<Filter>ui</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\native\ui\virtual_input.cpp">
<Filter>ui</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\native\math\lin\matrix4x4.cpp">
<Filter>math</Filter>
</ClCompile>
@ -608,9 +605,6 @@
<ClInclude Include="..\..\ext\native\ui\viewgroup.h">
<Filter>ui</Filter>
</ClInclude>
<ClInclude Include="..\..\ext\native\ui\virtual_input.h">
<Filter>ui</Filter>
</ClInclude>
<ClInclude Include="..\..\ext\native\math\lin\matrix4x4.h">
<Filter>math</Filter>
</ClInclude>

View File

@ -3,10 +3,12 @@
#include <mutex>
#include "base/basictypes.h"
#include "Common/FileUtil.h"
#include "Common/Log.h"
#include "Common/LogManager.h"
#include "Core/System.h"
#include "Core/Loaders.h"
#include "base/NativeApp.h"
#include "base/timeutil.h"
#include "input/input_state.h"
@ -18,22 +20,32 @@
#include "Common/DirectXHelper.h"
#include "NKCodeFromWindowsSystem.h"
#include "XAudioSoundStream.h"
#include "UWPHost.h"
#include "StorageFileLoader.h"
using namespace UWP;
using namespace Windows::Foundation;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
using namespace Windows::System::Threading;
using namespace Windows::ApplicationModel::DataTransfer;
using namespace Concurrency;
namespace UWP {
// UGLY!
PPSSPP_UWPMain *g_main;
// TODO: Use Microsoft::WRL::ComPtr<> for D3D11 objects?
// TODO: See https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/WindowsAudioSession for WASAPI with UWP
// TODO: Low latency input: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/LowLatencyInput/cpp
// Loads and initializes application assets when the application is loaded.
PPSSPP_UWPMain::PPSSPP_UWPMain(const std::shared_ptr<DX::DeviceResources>& deviceResources) :
PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResources>& deviceResources) :
app_(app),
m_deviceResources(deviceResources)
{
g_main = this;
host = new UWPHost();
// Register to be notified if the Device is lost or recreated
m_deviceResources->RegisterDeviceNotify(this);
@ -65,7 +77,6 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(const std::shared_ptr<DX::DeviceResources>& devic
langRegion = "en_US";
}
char configFilename[MAX_PATH] = { 0 };
char controlsConfigFilename[MAX_PATH] = { 0 };
@ -83,6 +94,7 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(const std::shared_ptr<DX::DeviceResources>& devic
bool debugLogLevel = false;
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D11;
g_Config.bSeparateCPUThread = false;
#ifdef _DEBUG
g_Config.bEnableLogging = true;
@ -124,8 +136,7 @@ void PPSSPP_UWPMain::CreateWindowSizeDependentResources() {
// 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() {
InputState input{};
NativeUpdate(input);
NativeUpdate();
time_update();
auto context = m_deviceResources->GetD3DDeviceContext();
@ -186,6 +197,40 @@ void PPSSPP_UWPMain::OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKe
}
}
void PPSSPP_UWPMain::OnTouchEvent(int touchEvent, int touchId, float x, float y, double timestamp) {
// It appears that Windows' touchIds start from 1. Let's fix that.
touchId--;
TouchInput input{};
input.id = touchId;
input.x = x;
input.y = y;
input.flags = touchEvent;
input.timestamp = timestamp;
NativeTouch(input);
KeyInput key{};
key.deviceId = DEVICE_ID_MOUSE;
if (touchEvent & TOUCH_DOWN) {
key.keyCode = NKCODE_EXT_MOUSEBUTTON_1;
key.flags = KEY_DOWN;
NativeKey(key);
}
if (touchEvent & TOUCH_UP) {
key.keyCode = NKCODE_EXT_MOUSEBUTTON_1;
key.flags = KEY_UP;
NativeKey(key);
}
}
void PPSSPP_UWPMain::OnSuspend() {
// TODO
}
void PPSSPP_UWPMain::LoadStorageFile(StorageFile ^file) {
OverrideNextLoader(new StorageFileLoader(file), FILETYPE_PSP_ISO);
NativeMessageReceived("boot", "override://");
}
UWPGraphicsContext::UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources) {
draw_ = Draw::T3DCreateD3D11Context(resources->GetD3DDevice(), resources->GetD3DDeviceContext(), resources->GetD3DDevice(), resources->GetD3DDeviceContext(), 0);
@ -199,16 +244,20 @@ void UWPGraphicsContext::SwapInterval(int interval) {
}
} // namespace UWP
std::string System_GetProperty(SystemProperty prop) {
static bool hasCheckedGPUDriverVersion = false;
switch (prop) {
case SYSPROP_NAME:
return "Windows 10";
return "Windows 10 Universal";
case SYSPROP_LANGREGION:
return "en_US"; // TODO UWP
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();
if (view) {
string text = await view->GetTextAsync();
}
*/
return "";
case SYSPROP_GPUDRIVER_VERSION:
return "";
@ -225,24 +274,55 @@ int System_GetPropertyInt(SystemProperty prop) {
return 60000;
case SYSPROP_DEVICE_TYPE:
return DEVICE_TYPE_DESKTOP;
case SYSPROP_HAS_FILE_BROWSER:
return true;
default:
return -1;
}
}
void System_SendMessage(const char *command, const char *parameter) {
// TODO UWP
using namespace concurrency;
if (!strcmp(command, "finish")) {
// Not really supposed to support this under UWP.
} else if (!strcmp(command, "browse_file")) {
auto picker = ref new Windows::Storage::Pickers::FileOpenPicker();
picker->ViewMode = Pickers::PickerViewMode::List;
picker->FileTypeFilter->Append(".cso");
picker->FileTypeFilter->Append(".iso");
picker->FileTypeFilter->Append(".bin");
create_task(picker->PickSingleFileAsync()).then([](StorageFile ^file){
g_main->LoadStorageFile(file);
/*
std::thread([file] {
create_task(file->OpenReadAsync()).then([](IRandomAccessStreamWithContentType^ imgStream) {
imgStream->Seek(0);
IBuffer ^buffer = ref new Streams::Buffer(2048);
auto readTask = create_task(imgStream->ReadAsync(buffer, 2048, InputStreamOptions::None));
readTask.wait();
});
}).detach();
*/
});
}
}
void LaunchBrowser(const char *url) {
// TODO UWP
Platform::String ^pstr = ref new Platform::String(ConvertUTF8ToWString(url).c_str());
auto uri = ref new Windows::Foundation::Uri(pstr);
create_task(Windows::System::Launcher::LaunchUriAsync(uri)).then([](bool b) {});
}
void Vibrate(int length_ms) {
// Ignore on PC
// TODO: Use Windows::Phone::Devices::Notification where available
}
void System_AskForPermission(SystemPermission permission) {}
void System_AskForPermission(SystemPermission permission) {
// Do nothing
}
PermissionStatus System_GetPermissionStatus(SystemPermission permission) {
return PERMISSION_STATUS_GRANTED;

View File

@ -1,13 +1,18 @@
#pragma once
#include <mutex>
#include "thin3d/thin3d.h"
#include "input/input_state.h"
#include "Common/GraphicsContext.h"
#include "Common/DeviceResources.h"
// Renders Direct2D and 3D content on the screen.
namespace UWP {
ref class App;
class UWPGraphicsContext : public GraphicsContext {
public:
UWPGraphicsContext(std::shared_ptr<DX::DeviceResources> resources);
@ -28,7 +33,7 @@ private:
class PPSSPP_UWPMain : public DX::IDeviceNotify
{
public:
PPSSPP_UWPMain(const std::shared_ptr<DX::DeviceResources>& deviceResources);
PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResources>& deviceResources);
~PPSSPP_UWPMain();
void CreateWindowSizeDependentResources();
bool Render();
@ -42,7 +47,17 @@ public:
void OnKeyDown(int scanCode, Windows::System::VirtualKey virtualKey, int repeatCount);
void OnKeyUp(int scanCode, Windows::System::VirtualKey virtualKey);
void OnTouchEvent(int touchEvent, int touchId, float x, float y, double timestamp);
// Save state fast if we can!
void OnSuspend();
void Close();
void LoadStorageFile(Windows::Storage::StorageFile ^file);
private:
App ^app_;
// Cached pointer to device resources.
std::shared_ptr<DX::DeviceResources> m_deviceResources;

91
UWP/StorageFileLoader.cpp Normal file
View File

@ -0,0 +1,91 @@
#include "pch.h"
#include "ppltasks.h"
#include "StorageFileLoader.h"
using namespace Concurrency;
using namespace Windows::Storage;
using namespace Windows::Storage::Streams;
StorageFileLoader::StorageFileLoader(Windows::Storage::StorageFile ^file) {
create_task(file->OpenReadAsync()).then([this](IRandomAccessStreamWithContentType ^stream) {
stream_ = stream;
active_ = true;
thread_ = std::thread([this]() { this->threadfunc(); });
});
}
StorageFileLoader::~StorageFileLoader() {
active_ = false;
thread_.join();
}
void StorageFileLoader::threadfunc() {
std::unique_lock<std::mutex> lock(mutex_);
while (active_) {
cond_.wait(lock);
std::unique_lock<std::mutex> lock(mutexResponse_);
while (operations_.size()) {
Operation op = operations_.front();
operations_.pop();
switch (op.type) {
case OpType::READ: {
op.buffer = ref new Streams::Buffer(op.size);
auto task = create_task(stream_->ReadAsync(op.buffer, op.size, Streams::InputStreamOptions::None));
task.wait();
break;
responses_.push(op);
}
default:
break;
}
}
// OK, done with all operations.
condResponse_.notify_one();
}
}
bool StorageFileLoader::Exists() {
return true;
}
bool StorageFileLoader::ExistsFast() {
return true;
}
bool StorageFileLoader::IsDirectory() {
return false;
}
s64 StorageFileLoader::FileSize() {
return 0;
}
std::string StorageFileLoader::Path() const { return ""; }
std::string StorageFileLoader::Extension() { return ""; }
void StorageFileLoader::Seek(s64 absolutePos) {
seekPos_ = absolutePos;
}
size_t StorageFileLoader::Read(size_t bytes, size_t count, void *data, Flags flags) {
{
std::unique_lock<std::mutex> lock(mutex_);
operations_.push(Operation{ OpType::READ, seekPos_, (int64_t)(bytes * count) });
cond_.notify_one();
}
// OK, now wait for response...
{
std::unique_lock<std::mutex> responseLock(mutexResponse_);
condResponse_.wait(responseLock);
Operation resp = responses_.front();
responses_.pop();
// memcpy(data, bytes * count, )
return 0;
}
}
size_t StorageFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) {
return 0;
}

56
UWP/StorageFileLoader.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
#include "pch.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
class StorageFileLoader : public FileLoader {
public:
StorageFileLoader(Windows::Storage::StorageFile ^file);
~StorageFileLoader();
bool Exists() override;
bool ExistsFast() override;
bool IsDirectory() override;
s64 FileSize() override;
std::string Path() const override;
std::string Extension() override;
void Seek(s64 absolutePos) override;
size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE);
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE);
private:
void threadfunc();
enum class OpType {
READ,
};
struct Operation {
OpType type;
int64_t offset;
int64_t size;
Windows::Storage::Streams::Buffer ^buffer;
};
bool active_ = false;
std::thread thread_;
Windows::Storage::Streams::IRandomAccessStreamWithContentType ^stream_;
std::condition_variable cond_;
std::mutex mutex_;
std::condition_variable condResponse_;
std::mutex mutexResponse_;
std::queue<Operation> operations_;
int64_t seekPos_ = 0;
std::queue<Operation> responses_;
};

View File

@ -116,6 +116,7 @@
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
@ -130,6 +131,7 @@
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@ -144,6 +146,7 @@
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -158,6 +161,7 @@
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -172,6 +176,7 @@
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -186,6 +191,7 @@
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
@ -222,12 +228,15 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\ppsspp_config.h" />
<ClInclude Include="..\Windows\XinputDevice.h" />
<ClInclude Include="App.h" />
<ClInclude Include="Common\DeviceResources.h" />
<ClInclude Include="NKCodeFromWindowsSystem.h" />
<ClInclude Include="PPSSPP_UWPMain.h" />
<ClInclude Include="Common\DirectXHelper.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="StorageFileLoader.h" />
<ClInclude Include="UWPHost.h" />
<ClInclude Include="XAudioSoundStream.h" />
</ItemGroup>
<ItemGroup>
@ -239,6 +248,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\Windows\XinputDevice.cpp" />
<ClCompile Include="App.cpp" />
<ClCompile Include="Common\DeviceResources.cpp" />
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
@ -251,6 +261,8 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="StorageFileLoader.cpp" />
<ClCompile Include="UWPHost.cpp" />
<ClCompile Include="XAudioSoundStream.cpp" />
</ItemGroup>
<ItemGroup>

View File

@ -46,6 +46,9 @@
<ClCompile Include="XAudioSoundStream.cpp" />
<ClCompile Include="PPSSPP_UWPMain.cpp" />
<ClCompile Include="NKCodeFromWindowsSystem.cpp" />
<ClCompile Include="StorageFileLoader.cpp" />
<ClCompile Include="UWPHost.cpp" />
<ClCompile Include="..\Windows\XinputDevice.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="App.h" />
@ -54,6 +57,9 @@
<ClInclude Include="XAudioSoundStream.h" />
<ClInclude Include="PPSSPP_UWPMain.h" />
<ClInclude Include="NKCodeFromWindowsSystem.h" />
<ClInclude Include="StorageFileLoader.h" />
<ClInclude Include="UWPHost.h" />
<ClInclude Include="..\Windows\XinputDevice.h" />
</ItemGroup>
<ItemGroup>
<Image Include="Assets\StoreLogo.png">

189
UWP/UWPHost.cpp Normal file
View File

@ -0,0 +1,189 @@
// Copyright (c) 2012- 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 "ppsspp_config.h"
#include "file/file_util.h"
#include "base/NativeApp.h"
#include "input/input_state.h"
#include "Common/StringUtils.h"
#include "Core/Core.h"
#include "Core/Config.h"
#include "Core/CoreParameter.h"
#include "Core/System.h"
#include "Core/Debugger/SymbolMap.h"
#include "UI/OnScreenDisplay.h"
#include "Windows/XinputDevice.h"
#include "Windows/DSoundStream.h"
#include "UWP/XAudioSoundStream.h"
#include "UWP/UWPHost.h"
UWPHost::UWPHost() {
// add first XInput device to respond
input.push_back(std::shared_ptr<InputDevice>(new XinputDevice()));
}
UWPHost::~UWPHost() {
}
void UWPHost::SetConsolePosition() {
}
void UWPHost::UpdateConsolePosition() {
}
bool UWPHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) {
// Done elsewhere
return true;
}
void UWPHost::ShutdownGraphics() {
// Done elsewhere
}
void UWPHost::SetWindowTitle(const char *message) {
// Should really be done differently
}
void UWPHost::InitSound() {
}
void UWPHost::UpdateSound() {
}
void UWPHost::ShutdownSound() {
}
void UWPHost::UpdateUI() {
}
void UWPHost::UpdateMemView() {
}
void UWPHost::UpdateDisassembly() {
}
void UWPHost::SetDebugMode(bool mode) {
}
void UWPHost::PollControllers() {
bool doPad = true;
for (auto iter = this->input.begin(); iter != this->input.end(); iter++)
{
auto device = *iter;
if (!doPad && device->IsPad())
continue;
if (device->UpdateState() == InputDevice::UPDATESTATE_SKIP_PAD)
doPad = false;
}
/*
g_mouseDeltaX *= 0.9f;
g_mouseDeltaY *= 0.9f;
// TODO: Tweak!
float scaleFactor = g_dpi_scale * 0.01f;
float mx = std::max(-1.0f, std::min(1.0f, g_mouseDeltaX * scaleFactor));
float my = std::max(-1.0f, std::min(1.0f, g_mouseDeltaY * scaleFactor));
AxisInput axisX, axisY;
axisX.axisId = JOYSTICK_AXIS_MOUSE_REL_X;
axisX.deviceId = DEVICE_ID_MOUSE;
axisX.value = mx;
axisY.axisId = JOYSTICK_AXIS_MOUSE_REL_Y;
axisY.deviceId = DEVICE_ID_MOUSE;
axisY.value = my;
*/
}
void UWPHost::BootDone() {
g_symbolMap->SortSymbols();
SetDebugMode(false);
Core_EnableStepping(false);
}
static std::string SymbolMapFilename(const char *currentFilename, char* ext) {
FileInfo info;
std::string result = currentFilename;
// can't fail, definitely exists if it gets this far
getFileInfo(currentFilename, &info);
if (info.isDirectory) {
#ifdef _WIN32
char* slash = "\\";
#else
char* slash = "/";
#endif
if (!endsWith(result, slash))
result += slash;
return result + ".ppsspp-symbols" + ext;
} else {
size_t dot = result.rfind('.');
if (dot == result.npos)
return result + ext;
result.replace(dot, result.npos, ext);
return result;
}
}
bool UWPHost::AttemptLoadSymbolMap() {
bool result1 = g_symbolMap->LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str(), ".ppmap").c_str());
// Load the old-style map file.
if (!result1)
result1 = g_symbolMap->LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str(), ".map").c_str());
bool result2 = g_symbolMap->LoadNocashSym(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str(), ".sym").c_str());
return result1 || result2;
}
void UWPHost::SaveSymbolMap() {
g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str(), ".ppmap").c_str());
}
bool UWPHost::IsDebuggingEnabled() {
return false;
}
bool UWPHost::CanCreateShortcut() {
return false; // Turn on when below function fixed
}
bool UWPHost::CreateDesktopShortcut(std::string argumentPath, std::string gameTitle) {
// TODO: not working correctly
return false;
}
void UWPHost::GoFullscreen(bool viewFullscreen) {
// TODO
}
void UWPHost::ToggleDebugConsoleVisibility() {
// N/A
}
void UWPHost::NotifyUserMessage(const std::string &message, float duration, u32 color, const char *id) {
osm.Show(message, duration, color, -1, true, id);
}

56
UWP/UWPHost.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
#include "Core/Host.h"
#include <list>
#include <memory>
#include "Windows/InputDevice.h"
class UWPHost : public Host {
public:
UWPHost();
~UWPHost();
void UpdateMemView() override;
void UpdateDisassembly() override;
void UpdateUI() override;
void SetDebugMode(bool mode) override;
// If returns false, will return a null context
bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override;
void PollControllers() override;
void ShutdownGraphics() override;
void InitSound() override;
void UpdateSound() override;
void ShutdownSound() override;
bool IsDebuggingEnabled() override;
void BootDone() override;
bool AttemptLoadSymbolMap() override;
void SaveSymbolMap() override;
void SetWindowTitle(const char *message) override;
bool GPUDebuggingActive() override { return false; }
void GPUNotifyCommand(u32 pc) override {}
void GPUNotifyDisplay(u32 framebuf, u32 stride, int format) override {}
void GPUNotifyDraw() override {}
void GPUNotifyTextureAttachment(u32 addr) override {}
void ToggleDebugConsoleVisibility() override;
bool CanCreateShortcut() override;
bool CreateDesktopShortcut(std::string argumentPath, std::string title) override;
void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override;
void GoFullscreen(bool) override;
GraphicsContext *GetGraphicsContext() { return nullptr; }
private:
void SetConsolePosition();
void UpdateConsolePosition();
std::list<std::shared_ptr<InputDevice>> input;
};

View File

@ -1,5 +1,3 @@
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
#include <mutex>
#include "base/timeutil.h"
@ -26,6 +24,7 @@
#include <tchar.h>
#include <process.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedExchange)
static std::mutex emuThreadLock;

View File

@ -1,4 +1,6 @@
#include <limits.h>
#include "ppsspp_config.h"
#include <climits>
#include <algorithm>
#include "base/NativeApp.h"
@ -11,6 +13,8 @@
// Utilities to dynamically load XInput. Adapted from SDL.
#if !PPSSPP_PLATFORM(UWP)
typedef DWORD (WINAPI *XInputGetState_t) (DWORD dwUserIndex, XINPUT_STATE* pState);
typedef DWORD (WINAPI *XInputSetState_t) (DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
typedef DWORD (WINAPI *XInputGetCapabilities_t) (DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities);
@ -66,6 +70,14 @@ static void UnloadXInputDLL() {
}
}
#else
static int LoadXInputDLL() { return 0; }
static void UnloadXInputDLL() {}
#define PPSSPP_XInputGetState XInputGetState
#define PPSSPP_XInputSetState XInputSetState
#define PPSSPP_XInputGetCapabilities XInputGetCapabilities
#endif
#ifndef XUSER_MAX_COUNT
#define XUSER_MAX_COUNT 4
#endif
@ -201,8 +213,10 @@ bool NormalizedDeadzoneDiffers(u8 x1, u8 x2, const u8 thresh) {
}
int XinputDevice::UpdateState() {
#if !PPSSPP_PLATFORM(UWP)
if (!s_pXInputDLL)
return 0;
#endif
bool anySuccess = false;
for (int i = 0; i < XUSER_MAX_COUNT; i++) {

View File

@ -212,6 +212,8 @@ int System_GetPropertyInt(SystemProperty prop) {
return DEVICE_TYPE_DESKTOP;
case SYSPROP_DISPLAY_DPI:
return ScreenDPI();
case SYSPROP_HAS_FILE_BROWSER:
return true;
default:
return -1;
}

View File

@ -152,6 +152,8 @@ enum SystemProperty {
SYSPROP_CLIPBOARD_TEXT,
SYSPROP_GPUDRIVER_VERSION,
SYSPROP_HAS_FILE_BROWSER,
// Available as Int:
SYSPROP_SYSTEMVERSION,
SYSPROP_DISPLAY_XRES,

View File

@ -111,9 +111,7 @@ int time_now_ms() {
void sleep_ms(int ms) {
#ifdef _WIN32
#ifndef METRO
Sleep(ms);
#endif
#else
usleep(ms * 1000);
#endif