summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2019-04-24 22:53:21 -0400
committerGravatar GitHub2019-04-24 22:53:21 -0400
commit53f746fa9a41647d69cdbd52de7e49de4acbfe6b (patch)
tree7b62619ffedc3012d131c63c12451779d22e8fd9
parentMerge pull request #2404 from lioncash/unicode (diff)
parentweb_browser: Make OpenPage non-const (diff)
downloadyuzu-53f746fa9a41647d69cdbd52de7e49de4acbfe6b.tar.gz
yuzu-53f746fa9a41647d69cdbd52de7e49de4acbfe6b.tar.xz
yuzu-53f746fa9a41647d69cdbd52de7e49de4acbfe6b.zip
Merge pull request #2228 from DarkLordZach/applet-manager-p1
applets: Add AppletManager and implement PhotoViewer and Error applets
-rw-r--r--src/core/CMakeLists.txt10
-rw-r--r--src/core/core.cpp50
-rw-r--r--src/core/core.h29
-rw-r--r--src/core/frontend/applets/error.cpp34
-rw-r--r--src/core/frontend/applets/error.h37
-rw-r--r--src/core/frontend/applets/general_frontend.cpp27
-rw-r--r--src/core/frontend/applets/general_frontend.h28
-rw-r--r--src/core/hle/service/am/am.cpp27
-rw-r--r--src/core/hle/service/am/applets/applets.cpp82
-rw-r--r--src/core/hle/service/am/applets/applets.h55
-rw-r--r--src/core/hle/service/am/applets/error.cpp182
-rw-r--r--src/core/hle/service/am/applets/error.h47
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp (renamed from src/core/hle/service/am/applets/stub_applet.cpp)56
-rw-r--r--src/core/hle/service/am/applets/general_backend.h48
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp6
-rw-r--r--src/core/hle/service/am/applets/profile_select.h4
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp7
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h4
-rw-r--r--src/core/hle/service/am/applets/stub_applet.h24
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp4
-rw-r--r--src/core/hle/service/am/applets/web_browser.h4
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/applets/error.cpp59
-rw-r--r--src/yuzu/applets/error.h33
-rw-r--r--src/yuzu/main.cpp17
-rw-r--r--src/yuzu/main.h3
26 files changed, 764 insertions, 115 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c59107102..2ace866ee 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -88,6 +88,10 @@ add_library(core STATIC
88 file_sys/vfs_vector.h 88 file_sys/vfs_vector.h
89 file_sys/xts_archive.cpp 89 file_sys/xts_archive.cpp
90 file_sys/xts_archive.h 90 file_sys/xts_archive.h
91 frontend/applets/error.cpp
92 frontend/applets/error.h
93 frontend/applets/general_frontend.cpp
94 frontend/applets/general_frontend.h
91 frontend/applets/profile_select.cpp 95 frontend/applets/profile_select.cpp
92 frontend/applets/profile_select.h 96 frontend/applets/profile_select.h
93 frontend/applets/software_keyboard.cpp 97 frontend/applets/software_keyboard.cpp
@@ -177,12 +181,14 @@ add_library(core STATIC
177 hle/service/am/applet_oe.h 181 hle/service/am/applet_oe.h
178 hle/service/am/applets/applets.cpp 182 hle/service/am/applets/applets.cpp
179 hle/service/am/applets/applets.h 183 hle/service/am/applets/applets.h
184 hle/service/am/applets/error.cpp
185 hle/service/am/applets/error.h
186 hle/service/am/applets/general_backend.cpp
187 hle/service/am/applets/general_backend.h
180 hle/service/am/applets/profile_select.cpp 188 hle/service/am/applets/profile_select.cpp
181 hle/service/am/applets/profile_select.h 189 hle/service/am/applets/profile_select.h
182 hle/service/am/applets/software_keyboard.cpp 190 hle/service/am/applets/software_keyboard.cpp
183 hle/service/am/applets/software_keyboard.h 191 hle/service/am/applets/software_keyboard.h
184 hle/service/am/applets/stub_applet.cpp
185 hle/service/am/applets/stub_applet.h
186 hle/service/am/applets/web_browser.cpp 192 hle/service/am/applets/web_browser.cpp
187 hle/service/am/applets/web_browser.h 193 hle/service/am/applets/web_browser.h
188 hle/service/am/idle.cpp 194 hle/service/am/idle.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 175a5f2ea..7106151bd 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -18,13 +18,18 @@
18#include "core/file_sys/registered_cache.h" 18#include "core/file_sys/registered_cache.h"
19#include "core/file_sys/vfs_concat.h" 19#include "core/file_sys/vfs_concat.h"
20#include "core/file_sys/vfs_real.h" 20#include "core/file_sys/vfs_real.h"
21#include "core/frontend/applets/error.h"
22#include "core/frontend/applets/general_frontend.h"
23#include "core/frontend/applets/profile_select.h"
24#include "core/frontend/applets/software_keyboard.h"
25#include "core/frontend/applets/web_browser.h"
21#include "core/gdbstub/gdbstub.h" 26#include "core/gdbstub/gdbstub.h"
22#include "core/hle/kernel/client_port.h" 27#include "core/hle/kernel/client_port.h"
23#include "core/hle/kernel/kernel.h" 28#include "core/hle/kernel/kernel.h"
24#include "core/hle/kernel/process.h" 29#include "core/hle/kernel/process.h"
25#include "core/hle/kernel/scheduler.h" 30#include "core/hle/kernel/scheduler.h"
26#include "core/hle/kernel/thread.h" 31#include "core/hle/kernel/thread.h"
27#include "core/hle/service/am/applets/software_keyboard.h" 32#include "core/hle/service/am/applets/applets.h"
28#include "core/hle/service/service.h" 33#include "core/hle/service/service.h"
29#include "core/hle/service/sm/sm.h" 34#include "core/hle/service/sm/sm.h"
30#include "core/loader/loader.h" 35#include "core/loader/loader.h"
@@ -110,12 +115,7 @@ struct System::Impl {
110 content_provider = std::make_unique<FileSys::ContentProviderUnion>(); 115 content_provider = std::make_unique<FileSys::ContentProviderUnion>();
111 116
112 /// Create default implementations of applets if one is not provided. 117 /// Create default implementations of applets if one is not provided.
113 if (profile_selector == nullptr) 118 applet_manager.SetDefaultAppletsIfMissing();
114 profile_selector = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
115 if (software_keyboard == nullptr)
116 software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
117 if (web_browser == nullptr)
118 web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
119 119
120 telemetry_session = std::make_unique<Core::TelemetrySession>(); 120 telemetry_session = std::make_unique<Core::TelemetrySession>();
121 service_manager = std::make_shared<Service::SM::ServiceManager>(); 121 service_manager = std::make_shared<Service::SM::ServiceManager>();
@@ -223,9 +223,7 @@ struct System::Impl {
223 app_loader.reset(); 223 app_loader.reset();
224 224
225 // Clear all applets 225 // Clear all applets
226 profile_selector.reset(); 226 applet_manager.ClearAll();
227 software_keyboard.reset();
228 web_browser.reset();
229 227
230 LOG_DEBUG(Core, "Shutdown OK"); 228 LOG_DEBUG(Core, "Shutdown OK");
231 } 229 }
@@ -264,9 +262,7 @@ struct System::Impl {
264 std::unique_ptr<FileSys::CheatEngine> cheat_engine; 262 std::unique_ptr<FileSys::CheatEngine> cheat_engine;
265 263
266 /// Frontend applets 264 /// Frontend applets
267 std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_selector; 265 Service::AM::Applets::AppletManager applet_manager;
268 std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
269 std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
270 266
271 /// Service manager 267 /// Service manager
272 std::shared_ptr<Service::SM::ServiceManager> service_manager; 268 std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -476,20 +472,20 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
476 return impl->virtual_filesystem; 472 return impl->virtual_filesystem;
477} 473}
478 474
479void System::SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet) { 475void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
480 impl->profile_selector = std::move(applet); 476 impl->applet_manager.SetAppletFrontendSet(std::move(set));
481} 477}
482 478
483const Frontend::ProfileSelectApplet& System::GetProfileSelector() const { 479void System::SetDefaultAppletFrontendSet() {
484 return *impl->profile_selector; 480 impl->applet_manager.SetDefaultAppletFrontendSet();
485} 481}
486 482
487void System::SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet) { 483Service::AM::Applets::AppletManager& System::GetAppletManager() {
488 impl->software_keyboard = std::move(applet); 484 return impl->applet_manager;
489} 485}
490 486
491const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const { 487const Service::AM::Applets::AppletManager& System::GetAppletManager() const {
492 return *impl->software_keyboard; 488 return impl->applet_manager;
493} 489}
494 490
495void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) { 491void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
@@ -513,18 +509,6 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
513 impl->content_provider->ClearSlot(slot); 509 impl->content_provider->ClearSlot(slot);
514} 510}
515 511
516void System::SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet) {
517 impl->web_browser = std::move(applet);
518}
519
520Frontend::WebBrowserApplet& System::GetWebBrowser() {
521 return *impl->web_browser;
522}
523
524const Frontend::WebBrowserApplet& System::GetWebBrowser() const {
525 return *impl->web_browser;
526}
527
528System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { 512System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
529 return impl->Init(*this, emu_window); 513 return impl->Init(*this, emu_window);
530} 514}
diff --git a/src/core/core.h b/src/core/core.h
index 82b2e087e..a9a756a4c 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -14,9 +14,6 @@
14 14
15namespace Core::Frontend { 15namespace Core::Frontend {
16class EmuWindow; 16class EmuWindow;
17class ProfileSelectApplet;
18class SoftwareKeyboardApplet;
19class WebBrowserApplet;
20} // namespace Core::Frontend 17} // namespace Core::Frontend
21 18
22namespace FileSys { 19namespace FileSys {
@@ -38,9 +35,18 @@ class AppLoader;
38enum class ResultStatus : u16; 35enum class ResultStatus : u16;
39} // namespace Loader 36} // namespace Loader
40 37
41namespace Service::SM { 38namespace Service {
39
40namespace AM::Applets {
41struct AppletFrontendSet;
42class AppletManager;
43} // namespace AM::Applets
44
45namespace SM {
42class ServiceManager; 46class ServiceManager;
43} // namespace Service::SM 47} // namespace SM
48
49} // namespace Service
44 50
45namespace Tegra { 51namespace Tegra {
46class DebugContext; 52class DebugContext;
@@ -260,18 +266,13 @@ public:
260 void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id, 266 void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id,
261 VAddr code_region_start, VAddr code_region_end); 267 VAddr code_region_start, VAddr code_region_end);
262 268
263 void SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet); 269 void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
264
265 const Frontend::ProfileSelectApplet& GetProfileSelector() const;
266
267 void SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet);
268 270
269 const Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const; 271 void SetDefaultAppletFrontendSet();
270 272
271 void SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet); 273 Service::AM::Applets::AppletManager& GetAppletManager();
272 274
273 Frontend::WebBrowserApplet& GetWebBrowser(); 275 const Service::AM::Applets::AppletManager& GetAppletManager() const;
274 const Frontend::WebBrowserApplet& GetWebBrowser() const;
275 276
276 void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider); 277 void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
277 278
diff --git a/src/core/frontend/applets/error.cpp b/src/core/frontend/applets/error.cpp
new file mode 100644
index 000000000..4002a9211
--- /dev/null
+++ b/src/core/frontend/applets/error.cpp
@@ -0,0 +1,34 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/frontend/applets/error.h"
6
7namespace Core::Frontend {
8
9ErrorApplet::~ErrorApplet() = default;
10
11void DefaultErrorApplet::ShowError(ResultCode error, std::function<void()> finished) const {
12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
13 static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
14}
15
16void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
17 std::function<void()> finished) const {
18 LOG_CRITICAL(
19 Service_Fatal,
20 "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}",
21 static_cast<u32>(error.module.Value()), error.description.Value(), error.raw, time.count());
22}
23
24void DefaultErrorApplet::ShowCustomErrorText(ResultCode error, std::string main_text,
25 std::string detail_text,
26 std::function<void()> finished) const {
27 LOG_CRITICAL(Service_Fatal,
28 "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})",
29 static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
30 LOG_CRITICAL(Service_Fatal, " Main Text: {}", main_text);
31 LOG_CRITICAL(Service_Fatal, " Detail Text: {}", detail_text);
32}
33
34} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/error.h b/src/core/frontend/applets/error.h
new file mode 100644
index 000000000..699df940d
--- /dev/null
+++ b/src/core/frontend/applets/error.h
@@ -0,0 +1,37 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <chrono>
8#include <functional>
9
10#include "core/hle/result.h"
11
12namespace Core::Frontend {
13
14class ErrorApplet {
15public:
16 virtual ~ErrorApplet();
17
18 virtual void ShowError(ResultCode error, std::function<void()> finished) const = 0;
19
20 virtual void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
21 std::function<void()> finished) const = 0;
22
23 virtual void ShowCustomErrorText(ResultCode error, std::string dialog_text,
24 std::string fullscreen_text,
25 std::function<void()> finished) const = 0;
26};
27
28class DefaultErrorApplet final : public ErrorApplet {
29public:
30 void ShowError(ResultCode error, std::function<void()> finished) const override;
31 void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
32 std::function<void()> finished) const override;
33 void ShowCustomErrorText(ResultCode error, std::string main_text, std::string detail_text,
34 std::function<void()> finished) const override;
35};
36
37} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general_frontend.cpp
new file mode 100644
index 000000000..b974f2289
--- /dev/null
+++ b/src/core/frontend/applets/general_frontend.cpp
@@ -0,0 +1,27 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/frontend/applets/general_frontend.h"
7
8namespace Core::Frontend {
9
10PhotoViewerApplet::~PhotoViewerApplet() = default;
11
12DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() {}
13
14void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id,
15 std::function<void()> finished) const {
16 LOG_INFO(Service_AM,
17 "Application requested frontend to display stored photos for title_id={:016X}",
18 title_id);
19 finished();
20}
21
22void DefaultPhotoViewerApplet::ShowAllPhotos(std::function<void()> finished) const {
23 LOG_INFO(Service_AM, "Application requested frontend to display all stored photos.");
24 finished();
25}
26
27} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/general_frontend.h b/src/core/frontend/applets/general_frontend.h
new file mode 100644
index 000000000..d4506c999
--- /dev/null
+++ b/src/core/frontend/applets/general_frontend.h
@@ -0,0 +1,28 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <functional>
8#include "common/common_types.h"
9
10namespace Core::Frontend {
11
12class PhotoViewerApplet {
13public:
14 virtual ~PhotoViewerApplet();
15
16 virtual void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const = 0;
17 virtual void ShowAllPhotos(std::function<void()> finished) const = 0;
18};
19
20class DefaultPhotoViewerApplet final : public PhotoViewerApplet {
21public:
22 ~DefaultPhotoViewerApplet() override;
23
24 void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const override;
25 void ShowAllPhotos(std::function<void()> finished) const override;
26};
27
28} // namespace Core::Frontend
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 1aa4ce1ac..26a665bfd 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -22,7 +22,6 @@
22#include "core/hle/service/am/applets/applets.h" 22#include "core/hle/service/am/applets/applets.h"
23#include "core/hle/service/am/applets/profile_select.h" 23#include "core/hle/service/am/applets/profile_select.h"
24#include "core/hle/service/am/applets/software_keyboard.h" 24#include "core/hle/service/am/applets/software_keyboard.h"
25#include "core/hle/service/am/applets/stub_applet.h"
26#include "core/hle/service/am/applets/web_browser.h" 25#include "core/hle/service/am/applets/web_browser.h"
27#include "core/hle/service/am/idle.h" 26#include "core/hle/service/am/idle.h"
28#include "core/hle/service/am/omm.h" 27#include "core/hle/service/am/omm.h"
@@ -42,12 +41,6 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
42constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3}; 41constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
43constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; 42constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
44 43
45enum class AppletId : u32 {
46 ProfileSelect = 0x10,
47 SoftwareKeyboard = 0x11,
48 LibAppletOff = 0x17,
49};
50
51constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; 44constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
52 45
53struct LaunchParameters { 46struct LaunchParameters {
@@ -886,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
886 879
887ILibraryAppletCreator::~ILibraryAppletCreator() = default; 880ILibraryAppletCreator::~ILibraryAppletCreator() = default;
888 881
889static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
890 switch (id) {
891 case AppletId::ProfileSelect:
892 return std::make_shared<Applets::ProfileSelect>();
893 case AppletId::SoftwareKeyboard:
894 return std::make_shared<Applets::SoftwareKeyboard>();
895 case AppletId::LibAppletOff:
896 return std::make_shared<Applets::WebBrowser>();
897 default:
898 LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!",
899 static_cast<u32>(id));
900 return std::make_shared<Applets::StubApplet>();
901 }
902}
903
904void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { 882void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
905 IPC::RequestParser rp{ctx}; 883 IPC::RequestParser rp{ctx};
906 const auto applet_id = rp.PopRaw<AppletId>(); 884 const auto applet_id = rp.PopRaw<Applets::AppletId>();
907 const auto applet_mode = rp.PopRaw<u32>(); 885 const auto applet_mode = rp.PopRaw<u32>();
908 886
909 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", 887 LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
910 static_cast<u32>(applet_id), applet_mode); 888 static_cast<u32>(applet_id), applet_mode);
911 889
912 const auto applet = GetAppletFromId(applet_id); 890 const auto& applet_manager{Core::System::GetInstance().GetAppletManager()};
891 const auto applet = applet_manager.GetApplet(applet_id);
913 892
914 if (applet == nullptr) { 893 if (applet == nullptr) {
915 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id)); 894 LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index a6064c63f..7f70b10df 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -5,11 +5,21 @@
5#include <cstring> 5#include <cstring>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/frontend/applets/error.h"
9#include "core/frontend/applets/general_frontend.h"
10#include "core/frontend/applets/profile_select.h"
11#include "core/frontend/applets/software_keyboard.h"
12#include "core/frontend/applets/web_browser.h"
8#include "core/hle/kernel/readable_event.h" 13#include "core/hle/kernel/readable_event.h"
9#include "core/hle/kernel/server_session.h" 14#include "core/hle/kernel/server_session.h"
10#include "core/hle/kernel/writable_event.h" 15#include "core/hle/kernel/writable_event.h"
11#include "core/hle/service/am/am.h" 16#include "core/hle/service/am/am.h"
12#include "core/hle/service/am/applets/applets.h" 17#include "core/hle/service/am/applets/applets.h"
18#include "core/hle/service/am/applets/error.h"
19#include "core/hle/service/am/applets/general_backend.h"
20#include "core/hle/service/am/applets/profile_select.h"
21#include "core/hle/service/am/applets/software_keyboard.h"
22#include "core/hle/service/am/applets/web_browser.h"
13 23
14namespace Service::AM::Applets { 24namespace Service::AM::Applets {
15 25
@@ -111,4 +121,76 @@ void Applet::Initialize() {
111 initialized = true; 121 initialized = true;
112} 122}
113 123
124AppletManager::AppletManager() = default;
125
126AppletManager::~AppletManager() = default;
127
128void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
129 if (set.error != nullptr)
130 frontend.error = std::move(set.error);
131 if (set.photo_viewer != nullptr)
132 frontend.photo_viewer = std::move(set.photo_viewer);
133 if (set.profile_select != nullptr)
134 frontend.profile_select = std::move(set.profile_select);
135 if (set.software_keyboard != nullptr)
136 frontend.software_keyboard = std::move(set.software_keyboard);
137 if (set.web_browser != nullptr)
138 frontend.web_browser = std::move(set.web_browser);
139}
140
141void AppletManager::SetDefaultAppletFrontendSet() {
142 frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
143 frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
144 frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
145 frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
146 frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
147}
148
149void AppletManager::SetDefaultAppletsIfMissing() {
150 if (frontend.error == nullptr) {
151 frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
152 }
153
154 if (frontend.photo_viewer == nullptr) {
155 frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
156 }
157
158 if (frontend.profile_select == nullptr) {
159 frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
160 }
161
162 if (frontend.software_keyboard == nullptr) {
163 frontend.software_keyboard =
164 std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
165 }
166
167 if (frontend.web_browser == nullptr) {
168 frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
169 }
170}
171
172void AppletManager::ClearAll() {
173 frontend = {};
174}
175
176std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
177 switch (id) {
178 case AppletId::Error:
179 return std::make_shared<Error>(*frontend.error);
180 case AppletId::ProfileSelect:
181 return std::make_shared<ProfileSelect>(*frontend.profile_select);
182 case AppletId::SoftwareKeyboard:
183 return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard);
184 case AppletId::PhotoViewer:
185 return std::make_shared<PhotoViewer>(*frontend.photo_viewer);
186 case AppletId::LibAppletOff:
187 return std::make_shared<WebBrowser>(*frontend.web_browser);
188 default:
189 UNIMPLEMENTED_MSG(
190 "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
191 static_cast<u8>(id));
192 return std::make_shared<StubApplet>();
193 }
194}
195
114} // namespace Service::AM::Applets 196} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 37424c379..7f932672c 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -12,12 +12,43 @@
12 12
13union ResultCode; 13union ResultCode;
14 14
15namespace Core::Frontend {
16class ErrorApplet;
17class PhotoViewerApplet;
18class ProfileSelectApplet;
19class SoftwareKeyboardApplet;
20class WebBrowserApplet;
21} // namespace Core::Frontend
22
15namespace Service::AM { 23namespace Service::AM {
16 24
17class IStorage; 25class IStorage;
18 26
19namespace Applets { 27namespace Applets {
20 28
29enum class AppletId : u32 {
30 OverlayDisplay = 0x02,
31 QLaunch = 0x03,
32 Starter = 0x04,
33 Auth = 0x0A,
34 Cabinet = 0x0B,
35 Controller = 0x0C,
36 DataErase = 0x0D,
37 Error = 0x0E,
38 NetConnect = 0x0F,
39 ProfileSelect = 0x10,
40 SoftwareKeyboard = 0x11,
41 MiiEdit = 0x12,
42 LibAppletWeb = 0x13,
43 LibAppletShop = 0x14,
44 PhotoViewer = 0x15,
45 Settings = 0x16,
46 LibAppletOff = 0x17,
47 LibAppletWhitelisted = 0x18,
48 LibAppletAuth = 0x19,
49 MyPage = 0x1A,
50};
51
21class AppletDataBroker final { 52class AppletDataBroker final {
22public: 53public:
23 AppletDataBroker(); 54 AppletDataBroker();
@@ -105,5 +136,29 @@ protected:
105 bool initialized = false; 136 bool initialized = false;
106}; 137};
107 138
139struct AppletFrontendSet {
140 std::unique_ptr<Core::Frontend::ErrorApplet> error;
141 std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer;
142 std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select;
143 std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
144 std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
145};
146
147class AppletManager {
148public:
149 AppletManager();
150 ~AppletManager();
151
152 void SetAppletFrontendSet(AppletFrontendSet set);
153 void SetDefaultAppletFrontendSet();
154 void SetDefaultAppletsIfMissing();
155 void ClearAll();
156
157 std::shared_ptr<Applet> GetApplet(AppletId id) const;
158
159private:
160 AppletFrontendSet frontend;
161};
162
108} // namespace Applets 163} // namespace Applets
109} // namespace Service::AM 164} // namespace Service::AM
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
new file mode 100644
index 000000000..04774bedc
--- /dev/null
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -0,0 +1,182 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <cstring>
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "common/string_util.h"
10#include "core/core.h"
11#include "core/frontend/applets/error.h"
12#include "core/hle/service/am/am.h"
13#include "core/hle/service/am/applets/error.h"
14
15namespace Service::AM::Applets {
16
17#pragma pack(push, 4)
18struct ShowError {
19 u8 mode;
20 bool jump;
21 INSERT_PADDING_BYTES(4);
22 bool use_64bit_error_code;
23 INSERT_PADDING_BYTES(1);
24 u64 error_code_64;
25 u32 error_code_32;
26};
27static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
28#pragma pack(pop)
29
30struct ShowErrorRecord {
31 u8 mode;
32 bool jump;
33 INSERT_PADDING_BYTES(6);
34 u64 error_code_64;
35 u64 posix_time;
36};
37static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect size.");
38
39struct SystemErrorArg {
40 u8 mode;
41 bool jump;
42 INSERT_PADDING_BYTES(6);
43 u64 error_code_64;
44 std::array<char, 8> language_code;
45 std::array<char, 0x800> main_text;
46 std::array<char, 0x800> detail_text;
47};
48static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size.");
49
50struct ApplicationErrorArg {
51 u8 mode;
52 bool jump;
53 INSERT_PADDING_BYTES(6);
54 u32 error_code;
55 std::array<char, 8> language_code;
56 std::array<char, 0x800> main_text;
57 std::array<char, 0x800> detail_text;
58};
59static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size.");
60
61union Error::ErrorArguments {
62 ShowError error;
63 ShowErrorRecord error_record;
64 SystemErrorArg system_error;
65 ApplicationErrorArg application_error;
66};
67
68namespace {
69template <typename T>
70void CopyArgumentData(const std::vector<u8>& data, T& variable) {
71 ASSERT(data.size() >= sizeof(T));
72 std::memcpy(&variable, data.data(), sizeof(T));
73}
74
75ResultCode Decode64BitError(u64 error) {
76 const auto description = (error >> 32) & 0x1FFF;
77 auto module = error & 0x3FF;
78 if (module >= 2000)
79 module -= 2000;
80 module &= 0x1FF;
81 return {static_cast<ErrorModule>(module), static_cast<u32>(description)};
82}
83
84} // Anonymous namespace
85
86Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {}
87
88Error::~Error() = default;
89
90void Error::Initialize() {
91 Applet::Initialize();
92 args = std::make_unique<ErrorArguments>();
93 complete = false;
94
95 const auto storage = broker.PopNormalDataToApplet();
96 ASSERT(storage != nullptr);
97 const auto data = storage->GetData();
98
99 ASSERT(!data.empty());
100 std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode));
101
102 switch (mode) {
103 case ErrorAppletMode::ShowError:
104 CopyArgumentData(data, args->error);
105 if (args->error.use_64bit_error_code) {
106 error_code = Decode64BitError(args->error.error_code_64);
107 } else {
108 error_code = ResultCode(args->error.error_code_32);
109 }
110 break;
111 case ErrorAppletMode::ShowSystemError:
112 CopyArgumentData(data, args->system_error);
113 error_code = ResultCode(Decode64BitError(args->system_error.error_code_64));
114 break;
115 case ErrorAppletMode::ShowApplicationError:
116 CopyArgumentData(data, args->application_error);
117 error_code = ResultCode(args->application_error.error_code);
118 break;
119 case ErrorAppletMode::ShowErrorRecord:
120 CopyArgumentData(data, args->error_record);
121 error_code = Decode64BitError(args->error_record.error_code_64);
122 break;
123 default:
124 UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
125 }
126}
127
128bool Error::TransactionComplete() const {
129 return complete;
130}
131
132ResultCode Error::GetStatus() const {
133 return RESULT_SUCCESS;
134}
135
136void Error::ExecuteInteractive() {
137 UNREACHABLE_MSG("Unexpected interactive applet data!");
138}
139
140void Error::Execute() {
141 if (complete) {
142 return;
143 }
144
145 const auto callback = [this] { DisplayCompleted(); };
146
147 switch (mode) {
148 case ErrorAppletMode::ShowError:
149 frontend.ShowError(error_code, callback);
150 break;
151 case ErrorAppletMode::ShowSystemError:
152 case ErrorAppletMode::ShowApplicationError: {
153 const auto system = mode == ErrorAppletMode::ShowSystemError;
154 const auto& main_text =
155 system ? args->system_error.main_text : args->application_error.main_text;
156 const auto& detail_text =
157 system ? args->system_error.detail_text : args->application_error.detail_text;
158
159 frontend.ShowCustomErrorText(
160 error_code,
161 Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()),
162 Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()),
163 callback);
164 break;
165 }
166 case ErrorAppletMode::ShowErrorRecord:
167 frontend.ShowErrorWithTimestamp(
168 error_code, std::chrono::seconds{args->error_record.posix_time}, callback);
169 break;
170 default:
171 UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
172 DisplayCompleted();
173 }
174}
175
176void Error::DisplayCompleted() {
177 complete = true;
178 broker.PushNormalDataFromApplet(IStorage{{}});
179 broker.SignalStateChanged();
180}
181
182} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h
new file mode 100644
index 000000000..a3590d181
--- /dev/null
+++ b/src/core/hle/service/am/applets/error.h
@@ -0,0 +1,47 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/result.h"
8#include "core/hle/service/am/applets/applets.h"
9
10namespace Service::AM::Applets {
11
12enum class ErrorAppletMode : u8 {
13 ShowError = 0,
14 ShowSystemError = 1,
15 ShowApplicationError = 2,
16 ShowEula = 3,
17 ShowErrorPctl = 4,
18 ShowErrorRecord = 5,
19 ShowUpdateEula = 8,
20};
21
22class Error final : public Applet {
23public:
24 explicit Error(const Core::Frontend::ErrorApplet& frontend);
25 ~Error() override;
26
27 void Initialize() override;
28
29 bool TransactionComplete() const override;
30 ResultCode GetStatus() const override;
31 void ExecuteInteractive() override;
32 void Execute() override;
33
34 void DisplayCompleted();
35
36private:
37 union ErrorArguments;
38
39 const Core::Frontend::ErrorApplet& frontend;
40 ResultCode error_code = RESULT_SUCCESS;
41 ErrorAppletMode mode = ErrorAppletMode::ShowError;
42 std::unique_ptr<ErrorArguments> args;
43
44 bool complete = false;
45};
46
47} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/stub_applet.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index ed166b87d..c591b9ac2 100644
--- a/src/core/hle/service/am/applets/stub_applet.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -4,11 +4,15 @@
4 4
5#include <string> 5#include <string>
6 6
7#include "common/assert.h"
7#include "common/hex_util.h" 8#include "common/hex_util.h"
8#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h"
11#include "core/frontend/applets/general_frontend.h"
12#include "core/hle/kernel/process.h"
9#include "core/hle/result.h" 13#include "core/hle/result.h"
10#include "core/hle/service/am/am.h" 14#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/applets/stub_applet.h" 15#include "core/hle/service/am/applets/general_backend.h"
12 16
13namespace Service::AM::Applets { 17namespace Service::AM::Applets {
14 18
@@ -30,6 +34,55 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) {
30 } 34 }
31} 35}
32 36
37PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {}
38
39PhotoViewer::~PhotoViewer() = default;
40
41void PhotoViewer::Initialize() {
42 Applet::Initialize();
43 complete = false;
44
45 const auto storage = broker.PopNormalDataToApplet();
46 ASSERT(storage != nullptr);
47 const auto data = storage->GetData();
48 ASSERT(!data.empty());
49 mode = static_cast<PhotoViewerAppletMode>(data[0]);
50}
51
52bool PhotoViewer::TransactionComplete() const {
53 return complete;
54}
55
56ResultCode PhotoViewer::GetStatus() const {
57 return RESULT_SUCCESS;
58}
59
60void PhotoViewer::ExecuteInteractive() {
61 UNREACHABLE_MSG("Unexpected interactive applet data.");
62}
63
64void PhotoViewer::Execute() {
65 if (complete)
66 return;
67
68 const auto callback = [this] { ViewFinished(); };
69 switch (mode) {
70 case PhotoViewerAppletMode::CurrentApp:
71 frontend.ShowPhotosForApplication(Core::CurrentProcess()->GetTitleID(), callback);
72 break;
73 case PhotoViewerAppletMode::AllApps:
74 frontend.ShowAllPhotos(callback);
75 break;
76 default:
77 UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast<u8>(mode));
78 }
79}
80
81void PhotoViewer::ViewFinished() {
82 broker.PushNormalDataFromApplet(IStorage{{}});
83 broker.SignalStateChanged();
84}
85
33StubApplet::StubApplet() = default; 86StubApplet::StubApplet() = default;
34 87
35StubApplet::~StubApplet() = default; 88StubApplet::~StubApplet() = default;
@@ -67,4 +120,5 @@ void StubApplet::Execute() {
67 broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); 120 broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
68 broker.SignalStateChanged(); 121 broker.SignalStateChanged();
69} 122}
123
70} // namespace Service::AM::Applets 124} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h
new file mode 100644
index 000000000..2dd255d7c
--- /dev/null
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -0,0 +1,48 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/am/applets/applets.h"
8
9namespace Service::AM::Applets {
10
11enum class PhotoViewerAppletMode : u8 {
12 CurrentApp = 0,
13 AllApps = 1,
14};
15
16class PhotoViewer final : public Applet {
17public:
18 explicit PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend);
19 ~PhotoViewer() override;
20
21 void Initialize() override;
22 bool TransactionComplete() const override;
23 ResultCode GetStatus() const override;
24 void ExecuteInteractive() override;
25 void Execute() override;
26
27 void ViewFinished();
28
29private:
30 const Core::Frontend::PhotoViewerApplet& frontend;
31 bool complete = false;
32 PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
33};
34
35class StubApplet final : public Applet {
36public:
37 StubApplet();
38 ~StubApplet() override;
39
40 void Initialize() override;
41
42 bool TransactionComplete() const override;
43 ResultCode GetStatus() const override;
44 void ExecuteInteractive() override;
45 void Execute() override;
46};
47
48} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 14e2a1fee..d113bd2eb 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -15,7 +15,9 @@ namespace Service::AM::Applets {
15 15
16constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; 16constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
17 17
18ProfileSelect::ProfileSelect() = default; 18ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend)
19 : frontend(frontend) {}
20
19ProfileSelect::~ProfileSelect() = default; 21ProfileSelect::~ProfileSelect() = default;
20 22
21void ProfileSelect::Initialize() { 23void ProfileSelect::Initialize() {
@@ -51,8 +53,6 @@ void ProfileSelect::Execute() {
51 return; 53 return;
52 } 54 }
53 55
54 const auto& frontend{Core::System::GetInstance().GetProfileSelector()};
55
56 frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); }); 56 frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
57} 57}
58 58
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
index 787485f22..a2ac6cf50 100644
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
28 28
29class ProfileSelect final : public Applet { 29class ProfileSelect final : public Applet {
30public: 30public:
31 ProfileSelect(); 31 explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend);
32 ~ProfileSelect() override; 32 ~ProfileSelect() override;
33 33
34 void Initialize() override; 34 void Initialize() override;
@@ -41,6 +41,8 @@ public:
41 void SelectionComplete(std::optional<Account::UUID> uuid); 41 void SelectionComplete(std::optional<Account::UUID> uuid);
42 42
43private: 43private:
44 const Core::Frontend::ProfileSelectApplet& frontend;
45
44 UserSelectionConfig config; 46 UserSelectionConfig config;
45 bool complete = false; 47 bool complete = false;
46 ResultCode status = RESULT_SUCCESS; 48 ResultCode status = RESULT_SUCCESS;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 8c5bd6059..e197990f7 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -39,7 +39,8 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
39 return params; 39 return params;
40} 40}
41 41
42SoftwareKeyboard::SoftwareKeyboard() = default; 42SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend)
43 : frontend(frontend) {}
43 44
44SoftwareKeyboard::~SoftwareKeyboard() = default; 45SoftwareKeyboard::~SoftwareKeyboard() = default;
45 46
@@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() {
90 if (status == INTERACTIVE_STATUS_OK) { 91 if (status == INTERACTIVE_STATUS_OK) {
91 complete = true; 92 complete = true;
92 } else { 93 } else {
93 const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
94
95 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string; 94 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
96 std::memcpy(string.data(), data.data() + 4, string.size() * 2); 95 std::memcpy(string.data(), data.data() + 4, string.size() * 2);
97 frontend.SendTextCheckDialog( 96 frontend.SendTextCheckDialog(
@@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() {
106 return; 105 return;
107 } 106 }
108 107
109 const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
110
111 const auto parameters = ConvertToFrontendParameters(config, initial_text); 108 const auto parameters = ConvertToFrontendParameters(config, initial_text);
112 109
113 frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); }, 110 frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); },
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index b93a30d28..0fbc43e51 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
55 55
56class SoftwareKeyboard final : public Applet { 56class SoftwareKeyboard final : public Applet {
57public: 57public:
58 SoftwareKeyboard(); 58 explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend);
59 ~SoftwareKeyboard() override; 59 ~SoftwareKeyboard() override;
60 60
61 void Initialize() override; 61 void Initialize() override;
@@ -68,6 +68,8 @@ public:
68 void WriteText(std::optional<std::u16string> text); 68 void WriteText(std::optional<std::u16string> text);
69 69
70private: 70private:
71 const Core::Frontend::SoftwareKeyboardApplet& frontend;
72
71 KeyboardConfig config; 73 KeyboardConfig config;
72 std::u16string initial_text; 74 std::u16string initial_text;
73 bool complete = false; 75 bool complete = false;
diff --git a/src/core/hle/service/am/applets/stub_applet.h b/src/core/hle/service/am/applets/stub_applet.h
deleted file mode 100644
index 7d8dc968d..000000000
--- a/src/core/hle/service/am/applets/stub_applet.h
+++ /dev/null
@@ -1,24 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/am/applets/applets.h"
8
9namespace Service::AM::Applets {
10
11class StubApplet final : public Applet {
12public:
13 StubApplet();
14 ~StubApplet() override;
15
16 void Initialize() override;
17
18 bool TransactionComplete() const override;
19 ResultCode GetStatus() const override;
20 void ExecuteInteractive() override;
21 void Execute() override;
22};
23
24} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 7e17df98a..7878f5136 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -95,7 +95,7 @@ static FileSys::VirtualFile GetManualRomFS() {
95 return nullptr; 95 return nullptr;
96} 96}
97 97
98WebBrowser::WebBrowser() = default; 98WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {}
99 99
100WebBrowser::~WebBrowser() = default; 100WebBrowser::~WebBrowser() = default;
101 101
@@ -152,8 +152,6 @@ void WebBrowser::Execute() {
152 return; 152 return;
153 } 153 }
154 154
155 auto& frontend{Core::System::GetInstance().GetWebBrowser()};
156
157 frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); 155 frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
158} 156}
159 157
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index b9e228fac..7e0f34c7d 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -12,7 +12,7 @@ namespace Service::AM::Applets {
12 12
13class WebBrowser final : public Applet { 13class WebBrowser final : public Applet {
14public: 14public:
15 WebBrowser(); 15 WebBrowser(Core::Frontend::WebBrowserApplet& frontend);
16 ~WebBrowser() override; 16 ~WebBrowser() override;
17 17
18 void Initialize() override; 18 void Initialize() override;
@@ -32,6 +32,8 @@ public:
32 void Finalize(); 32 void Finalize();
33 33
34private: 34private:
35 Core::Frontend::WebBrowserApplet& frontend;
36
35 bool complete = false; 37 bool complete = false;
36 bool unpacked = false; 38 bool unpacked = false;
37 ResultCode status = RESULT_SUCCESS; 39 ResultCode status = RESULT_SUCCESS;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 31b65c04c..5138bd9a3 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -7,6 +7,8 @@ add_executable(yuzu
7 Info.plist 7 Info.plist
8 about_dialog.cpp 8 about_dialog.cpp
9 about_dialog.h 9 about_dialog.h
10 applets/error.cpp
11 applets/error.h
10 applets/profile_select.cpp 12 applets/profile_select.cpp
11 applets/profile_select.h 13 applets/profile_select.h
12 applets/software_keyboard.cpp 14 applets/software_keyboard.cpp
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp
new file mode 100644
index 000000000..1fb2fe277
--- /dev/null
+++ b/src/yuzu/applets/error.cpp
@@ -0,0 +1,59 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QDateTime>
6#include "core/hle/lock.h"
7#include "yuzu/applets/error.h"
8#include "yuzu/main.h"
9
10QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
11 connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent,
12 &GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection);
13 connect(&parent, &GMainWindow::ErrorDisplayFinished, this,
14 &QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection);
15}
16
17QtErrorDisplay::~QtErrorDisplay() = default;
18
19void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const {
20 this->callback = std::move(finished);
21 emit MainWindowDisplayError(
22 tr("An error has occured.\nPlease try again or contact the developer of the "
23 "software.\n\nError Code: %1-%2 (0x%3)")
24 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
25 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
26 .arg(error.raw, 8, 16, QChar::fromLatin1('0')));
27}
28
29void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
30 std::function<void()> finished) const {
31 this->callback = std::move(finished);
32 emit MainWindowDisplayError(
33 tr("An error occured on %1 at %2.\nPlease try again or contact the "
34 "developer of the software.\n\nError Code: %3-%4 (0x%5)")
35 .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("dddd, MMMM d, yyyy"))
36 .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("h:mm:ss A"))
37 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
38 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
39 .arg(error.raw, 8, 16, QChar::fromLatin1('0')));
40}
41
42void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text,
43 std::string fullscreen_text,
44 std::function<void()> finished) const {
45 this->callback = std::move(finished);
46 emit MainWindowDisplayError(
47 tr("An error has occured.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5")
48 .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))
49 .arg(error.description, 4, 10, QChar::fromLatin1('0'))
50 .arg(error.raw, 8, 16, QChar::fromLatin1('0'))
51 .arg(QString::fromStdString(dialog_text))
52 .arg(QString::fromStdString(fullscreen_text)));
53}
54
55void QtErrorDisplay::MainWindowFinishedError() {
56 // Acquire the HLE mutex
57 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
58 callback();
59}
diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/error.h
new file mode 100644
index 000000000..b0932d895
--- /dev/null
+++ b/src/yuzu/applets/error.h
@@ -0,0 +1,33 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <QObject>
8
9#include "core/frontend/applets/error.h"
10
11class GMainWindow;
12
13class QtErrorDisplay final : public QObject, public Core::Frontend::ErrorApplet {
14 Q_OBJECT
15
16public:
17 explicit QtErrorDisplay(GMainWindow& parent);
18 ~QtErrorDisplay() override;
19
20 void ShowError(ResultCode error, std::function<void()> finished) const override;
21 void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
22 std::function<void()> finished) const override;
23 void ShowCustomErrorText(ResultCode error, std::string dialog_text, std::string fullscreen_text,
24 std::function<void()> finished) const override;
25
26signals:
27 void MainWindowDisplayError(QString error) const;
28
29private:
30 void MainWindowFinishedError();
31
32 mutable std::function<void()> callback;
33};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index bdee44b04..e33e3aaaf 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -8,6 +8,7 @@
8#include <thread> 8#include <thread>
9 9
10// VFS includes must be before glad as they will conflict with Windows file api, which uses defines. 10// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
11#include "applets/error.h"
11#include "applets/profile_select.h" 12#include "applets/profile_select.h"
12#include "applets/software_keyboard.h" 13#include "applets/software_keyboard.h"
13#include "applets/web_browser.h" 14#include "applets/web_browser.h"
@@ -15,6 +16,7 @@
15#include "configuration/configure_per_general.h" 16#include "configuration/configure_per_general.h"
16#include "core/file_sys/vfs.h" 17#include "core/file_sys/vfs.h"
17#include "core/file_sys/vfs_real.h" 18#include "core/file_sys/vfs_real.h"
19#include "core/frontend/applets/general_frontend.h"
18#include "core/frontend/scope_acquire_window_context.h" 20#include "core/frontend/scope_acquire_window_context.h"
19#include "core/hle/service/acc/profile_manager.h" 21#include "core/hle/service/acc/profile_manager.h"
20#include "core/hle/service/am/applets/applets.h" 22#include "core/hle/service/am/applets/applets.h"
@@ -795,9 +797,13 @@ bool GMainWindow::LoadROM(const QString& filename) {
795 797
796 system.SetGPUDebugContext(debug_context); 798 system.SetGPUDebugContext(debug_context);
797 799
798 system.SetProfileSelector(std::make_unique<QtProfileSelector>(*this)); 800 system.SetAppletFrontendSet({
799 system.SetSoftwareKeyboard(std::make_unique<QtSoftwareKeyboard>(*this)); 801 std::make_unique<QtErrorDisplay>(*this),
800 system.SetWebBrowser(std::make_unique<QtWebBrowser>(*this)); 802 nullptr,
803 std::make_unique<QtProfileSelector>(*this),
804 std::make_unique<QtSoftwareKeyboard>(*this),
805 std::make_unique<QtWebBrowser>(*this),
806 });
801 807
802 const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; 808 const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
803 809
@@ -1583,6 +1589,11 @@ void GMainWindow::OnLoadComplete() {
1583 loading_screen->OnLoadComplete(); 1589 loading_screen->OnLoadComplete();
1584} 1590}
1585 1591
1592void GMainWindow::ErrorDisplayDisplayError(QString body) {
1593 QMessageBox::critical(this, tr("Error Display"), body);
1594 emit ErrorDisplayFinished();
1595}
1596
1586void GMainWindow::OnMenuReportCompatibility() { 1597void GMainWindow::OnMenuReportCompatibility() {
1587 if (!Settings::values.yuzu_token.empty() && !Settings::values.yuzu_username.empty()) { 1598 if (!Settings::values.yuzu_token.empty() && !Settings::values.yuzu_username.empty()) {
1588 CompatDB compatdb{this}; 1599 CompatDB compatdb{this};
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index ce5045819..fb2a193cb 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -102,6 +102,8 @@ signals:
102 // Signal that tells widgets to update icons to use the current theme 102 // Signal that tells widgets to update icons to use the current theme
103 void UpdateThemedIcons(); 103 void UpdateThemedIcons();
104 104
105 void ErrorDisplayFinished();
106
105 void ProfileSelectorFinishedSelection(std::optional<Service::Account::UUID> uuid); 107 void ProfileSelectorFinishedSelection(std::optional<Service::Account::UUID> uuid);
106 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text); 108 void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
107 void SoftwareKeyboardFinishedCheckDialog(); 109 void SoftwareKeyboardFinishedCheckDialog();
@@ -111,6 +113,7 @@ signals:
111 113
112public slots: 114public slots:
113 void OnLoadComplete(); 115 void OnLoadComplete();
116 void ErrorDisplayDisplayError(QString body);
114 void ProfileSelectorSelectProfile(); 117 void ProfileSelectorSelectProfile();
115 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); 118 void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
116 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); 119 void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);