CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/UWP/App.cpp
Views: 1401
1
#include "ppsspp_config.h"
2
3
#include "pch.h"
4
#include "App.h"
5
6
#include <ppltasks.h>
7
#include <mutex>
8
9
#include "Common/Net/HTTPClient.h"
10
#include "Common/Net/Resolve.h"
11
12
#include "Common/File/VFS/VFS.h"
13
#include "Common/File/VFS/DirectoryReader.h"
14
#include "Common/Data/Encoding/Utf8.h"
15
#include "Common/Input/InputState.h"
16
#include "Common/System/NativeApp.h"
17
#include "Common/System/System.h"
18
#include "Common/Log/LogManager.h"
19
#include "Core/System.h"
20
#include "Core/Config.h"
21
#include "Core/Core.h"
22
#include "UWPHelpers/LaunchItem.h"
23
#include <UWPUtil.h>
24
25
using namespace UWP;
26
27
using namespace concurrency;
28
using namespace Windows::ApplicationModel;
29
using namespace Windows::ApplicationModel::Core;
30
using namespace Windows::ApplicationModel::Activation;
31
using namespace Windows::UI::Core;
32
using namespace Windows::UI::Input;
33
using namespace Windows::System;
34
using namespace Windows::Foundation;
35
using namespace Windows::Graphics::Display;
36
37
// The main function is only used to initialize our IFrameworkView class.
38
[Platform::MTAThread]
39
int main(Platform::Array<Platform::String^>^) {
40
auto direct3DApplicationSource = ref new Direct3DApplicationSource();
41
CoreApplication::Run(direct3DApplicationSource);
42
return 0;
43
}
44
45
IFrameworkView^ Direct3DApplicationSource::CreateView() {
46
return ref new App();
47
}
48
49
App::App() :
50
m_windowClosed(false),
51
m_windowVisible(true)
52
{
53
}
54
55
void App::InitialPPSSPP() {
56
// Initial net
57
net::Init();
58
59
// Get install location
60
auto packageDirectory = Package::Current->InstalledPath;
61
const Path& exePath = Path(FromPlatformString(packageDirectory));
62
g_VFS.Register("", new DirectoryReader(exePath / "Content"));
63
g_VFS.Register("", new DirectoryReader(exePath));
64
65
// Mount a filesystem
66
g_Config.flash0Directory = exePath / "assets/flash0";
67
68
// Prepare for initialization
69
std::wstring internalDataFolderW = ApplicationData::Current->LocalFolder->Path->Data();
70
g_Config.internalDataDirectory = Path(internalDataFolderW);
71
g_Config.memStickDirectory = g_Config.internalDataDirectory;
72
73
// On Win32 it makes more sense to initialize the system directories here
74
// because the next place it was called was in the EmuThread, and it's too late by then.
75
CreateSysDirectories();
76
77
LogManager::Init(&g_Config.bEnableLogging);
78
79
// Set the config path to local state by default
80
// it will be overrided by `NativeInit` if there is custom memStick
81
g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM));
82
g_Config.Load();
83
84
if (g_Config.bFirstRun) {
85
// Clear `memStickDirectory` to show memory stick screen on first start
86
g_Config.memStickDirectory.clear();
87
}
88
89
// Since we don't have any async operation in `NativeInit`
90
// it's better to call it here
91
const char* argv[2] = { "fake", nullptr };
92
std::string cacheFolder = ConvertWStringToUTF8(ApplicationData::Current->TemporaryFolder->Path->Data());
93
// We will not be able to use `argv`
94
// since launch parameters usually handled by `OnActivated`
95
// and `OnActivated` will be invoked later, even after `PPSSPP_UWPMain(..)`
96
// so we are handling launch cases using `LaunchItem`
97
NativeInit(1, argv, "", "", cacheFolder.c_str());
98
99
// Override backend, `DIRECT3D11` is the only way for UWP apps
100
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
101
102
// Calling `NativeInit` before will help us to deal with custom configs
103
// such as custom adapter, so it's better to initial render device here
104
m_deviceResources = std::make_shared<DX::DeviceResources>();
105
m_deviceResources->CreateWindowSizeDependentResources();
106
}
107
108
// The first method called when the IFrameworkView is being created.
109
void App::Initialize(CoreApplicationView^ applicationView) {
110
// Register event handlers for app lifecycle. This example includes Activated, so that we
111
// can make the CoreWindow active and start rendering on the window.
112
applicationView->Activated +=
113
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
114
115
CoreApplication::Suspending +=
116
ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
117
118
CoreApplication::Resuming +=
119
ref new EventHandler<Platform::Object^>(this, &App::OnResuming);
120
}
121
122
// Called when the CoreWindow object is created (or re-created).
123
void App::SetWindow(CoreWindow^ window) {
124
window->SizeChanged +=
125
ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
126
127
window->VisibilityChanged +=
128
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
129
130
window->Closed +=
131
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
132
133
DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
134
135
currentDisplayInformation->DpiChanged +=
136
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged);
137
138
currentDisplayInformation->OrientationChanged +=
139
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged);
140
141
DisplayInformation::DisplayContentsInvalidated +=
142
ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);
143
144
window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyDown);
145
window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &App::OnKeyUp);
146
window->CharacterReceived += ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(this, &App::OnCharacterReceived);
147
148
window->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerMoved);
149
window->PointerEntered += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerEntered);
150
window->PointerExited += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerExited);
151
window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerPressed);
152
window->PointerReleased += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerReleased);
153
window->PointerCaptureLost += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerCaptureLost);
154
window->PointerWheelChanged += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerWheelChanged);
155
156
if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.Phone.UI.Input.HardwareButtons")) {
157
m_hardwareButtons.insert(HardwareButton::BACK);
158
}
159
160
if (Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily == "Windows.Mobile") {
161
m_isPhone = true;
162
}
163
164
Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->
165
BackRequested += ref new Windows::Foundation::EventHandler<
166
Windows::UI::Core::BackRequestedEventArgs^>(
167
this, &App::App_BackRequested);
168
169
InitialPPSSPP();
170
}
171
172
bool App::HasBackButton() {
173
if (m_hardwareButtons.count(HardwareButton::BACK) != 0)
174
return true;
175
else
176
return false;
177
}
178
179
void App::App_BackRequested(Platform::Object^ sender, Windows::UI::Core::BackRequestedEventArgs^ e) {
180
if (m_isPhone) {
181
e->Handled = m_main->OnHardwareButton(HardwareButton::BACK);
182
} else {
183
e->Handled = true;
184
}
185
}
186
187
void App::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) {
188
m_main->OnKeyDown(args->KeyStatus.ScanCode, args->VirtualKey, args->KeyStatus.RepeatCount);
189
}
190
191
void App::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) {
192
m_main->OnKeyUp(args->KeyStatus.ScanCode, args->VirtualKey);
193
}
194
195
void App::OnCharacterReceived(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args) {
196
m_main->OnCharacterReceived(args->KeyStatus.ScanCode, args->KeyCode);
197
}
198
199
void App::OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
200
int pointerId = touchMap_.TouchId(args->CurrentPoint->PointerId);
201
if (pointerId < 0)
202
return;
203
float X = args->CurrentPoint->Position.X;
204
float Y = args->CurrentPoint->Position.Y;
205
int64_t timestamp = args->CurrentPoint->Timestamp;
206
m_main->OnTouchEvent(TOUCH_MOVE, pointerId, X, Y, (double)timestamp);
207
}
208
209
void App::OnPointerEntered(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
210
}
211
212
void App::OnPointerExited(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
213
}
214
215
void App::OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
216
int pointerId = touchMap_.TouchId(args->CurrentPoint->PointerId);
217
if (pointerId < 0)
218
pointerId = touchMap_.AddNewTouch(args->CurrentPoint->PointerId);
219
220
float X = args->CurrentPoint->Position.X;
221
float Y = args->CurrentPoint->Position.Y;
222
int64_t timestamp = args->CurrentPoint->Timestamp;
223
m_main->OnTouchEvent(TOUCH_DOWN|TOUCH_MOVE, pointerId, X, Y, (double)timestamp);
224
if (!m_isPhone) {
225
sender->SetPointerCapture();
226
}
227
}
228
229
void App::OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
230
int pointerId = touchMap_.RemoveTouch(args->CurrentPoint->PointerId);
231
if (pointerId < 0)
232
return;
233
float X = args->CurrentPoint->Position.X;
234
float Y = args->CurrentPoint->Position.Y;
235
int64_t timestamp = args->CurrentPoint->Timestamp;
236
m_main->OnTouchEvent(TOUCH_UP|TOUCH_MOVE, pointerId, X, Y, (double)timestamp);
237
if (!m_isPhone) {
238
sender->ReleasePointerCapture();
239
}
240
}
241
242
void App::OnPointerCaptureLost(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
243
}
244
245
void App::OnPointerWheelChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args) {
246
int pointerId = 0; // irrelevant
247
float delta = (float)args->CurrentPoint->GetCurrentPoint(args->CurrentPoint->PointerId)->Properties->MouseWheelDelta;
248
m_main->OnMouseWheel(delta);
249
}
250
251
// Initializes scene resources, or loads a previously saved app state.
252
void App::Load(Platform::String^ entryPoint) {
253
if (m_main == nullptr) {
254
m_main = std::unique_ptr<PPSSPP_UWPMain>(new PPSSPP_UWPMain(this, m_deviceResources));
255
}
256
}
257
258
// This method is called after the window becomes active.
259
void App::Run() {
260
while (!m_windowClosed) {
261
if (m_windowVisible) {
262
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
263
m_main->Render();
264
// TODO: Adopt some practices from m_deviceResources->Present();
265
} else {
266
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
267
}
268
}
269
}
270
271
// Required for IFrameworkView.
272
// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
273
// class is torn down while the app is in the foreground.
274
void App::Uninitialize() {
275
}
276
277
// Application lifecycle event handlers.
278
void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) {
279
// Run() won't start until the CoreWindow is activated.
280
CoreWindow::GetForCurrentThread()->Activate();
281
// On mobile, we force-enter fullscreen mode.
282
if (m_isPhone)
283
g_Config.iForceFullScreen = 1;
284
285
if (g_Config.UseFullScreen())
286
Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()->TryEnterFullScreenMode();
287
288
//Detect if app started or activated by launch item (file, uri)
289
DetectLaunchItem(args);
290
}
291
292
void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {
293
// Save app state asynchronously after requesting a deferral. Holding a deferral
294
// indicates that the application is busy performing suspending operations. Be
295
// aware that a deferral may not be held indefinitely. After about five seconds,
296
// the app will be forced to exit.
297
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
298
auto app = this;
299
300
create_task([app, deferral]() {
301
g_Config.Save("App::OnSuspending");
302
app->m_deviceResources->Trim();
303
deferral->Complete();
304
});
305
}
306
307
void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) {
308
// Restore any data or state that was unloaded on suspend. By default, data
309
// and state are persisted when resuming from suspend. Note that this event
310
// does not occur if the app was previously terminated.
311
312
// Insert your code here.
313
}
314
315
// Window event handlers.
316
317
void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) {
318
auto view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
319
g_Config.bFullScreen = view->IsFullScreenMode;
320
g_Config.iForceFullScreen = -1;
321
322
float width = sender->Bounds.Width;
323
float height = sender->Bounds.Height;
324
float scale = m_deviceResources->GetDpi() / 96.0f;
325
326
m_deviceResources->SetLogicalSize(Size(width, height));
327
if (m_main) {
328
m_main->CreateWindowSizeDependentResources();
329
}
330
331
PSP_CoreParameter().pixelWidth = (int)(width * scale);
332
PSP_CoreParameter().pixelHeight = (int)(height * scale);
333
if (UpdateScreenScale((int)width, (int)height)) {
334
System_PostUIMessage(UIMessage::GPU_DISPLAY_RESIZED);
335
}
336
}
337
338
void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) {
339
m_windowVisible = args->Visible;
340
}
341
342
void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) {
343
m_windowClosed = true;
344
}
345
346
// DisplayInformation event handlers.
347
348
void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) {
349
// Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
350
// if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
351
// you should always retrieve it using the GetDpi method.
352
// See DeviceResources.cpp for more details.
353
m_deviceResources->SetDpi(sender->LogicalDpi);
354
m_main->CreateWindowSizeDependentResources();
355
}
356
357
void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args) {
358
m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation);
359
m_main->CreateWindowSizeDependentResources();
360
}
361
362
void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) {
363
m_deviceResources->ValidateDevice();
364
}
365
366