From e51d33f0cee74f9fbd58439b411e6d3fef57576d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:32:59 -0400 Subject: [PATCH 01/13] applets: Add AppletManager class to control lifetime --- src/core/hle/service/am/applets/applets.cpp | 82 +++++++++++++++++++++ src/core/hle/service/am/applets/applets.h | 55 ++++++++++++++ 2 files changed, 137 insertions(+) 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 @@ #include #include "common/assert.h" #include "core/core.h" +#include "core/frontend/applets/error.h" +#include "core/frontend/applets/general_frontend.h" +#include "core/frontend/applets/profile_select.h" +#include "core/frontend/applets/software_keyboard.h" +#include "core/frontend/applets/web_browser.h" #include "core/hle/kernel/readable_event.h" #include "core/hle/kernel/server_session.h" #include "core/hle/kernel/writable_event.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/applets.h" +#include "core/hle/service/am/applets/error.h" +#include "core/hle/service/am/applets/general_backend.h" +#include "core/hle/service/am/applets/profile_select.h" +#include "core/hle/service/am/applets/software_keyboard.h" +#include "core/hle/service/am/applets/web_browser.h" namespace Service::AM::Applets { @@ -111,4 +121,76 @@ void Applet::Initialize() { initialized = true; } +AppletManager::AppletManager() = default; + +AppletManager::~AppletManager() = default; + +void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { + if (set.error != nullptr) + frontend.error = std::move(set.error); + if (set.photo_viewer != nullptr) + frontend.photo_viewer = std::move(set.photo_viewer); + if (set.profile_select != nullptr) + frontend.profile_select = std::move(set.profile_select); + if (set.software_keyboard != nullptr) + frontend.software_keyboard = std::move(set.software_keyboard); + if (set.web_browser != nullptr) + frontend.web_browser = std::move(set.web_browser); +} + +void AppletManager::SetDefaultAppletFrontendSet() { + frontend.error = std::make_unique(); + frontend.photo_viewer = std::make_unique(); + frontend.profile_select = std::make_unique(); + frontend.software_keyboard = std::make_unique(); + frontend.web_browser = std::make_unique(); +} + +void AppletManager::SetDefaultAppletsIfMissing() { + if (frontend.error == nullptr) { + frontend.error = std::make_unique(); + } + + if (frontend.photo_viewer == nullptr) { + frontend.photo_viewer = std::make_unique(); + } + + if (frontend.profile_select == nullptr) { + frontend.profile_select = std::make_unique(); + } + + if (frontend.software_keyboard == nullptr) { + frontend.software_keyboard = + std::make_unique(); + } + + if (frontend.web_browser == nullptr) { + frontend.web_browser = std::make_unique(); + } +} + +void AppletManager::ClearAll() { + frontend = {}; +} + +std::shared_ptr AppletManager::GetApplet(AppletId id) const { + switch (id) { + case AppletId::Error: + return std::make_shared(*frontend.error); + case AppletId::ProfileSelect: + return std::make_shared(*frontend.profile_select); + case AppletId::SoftwareKeyboard: + return std::make_shared(*frontend.software_keyboard); + case AppletId::PhotoViewer: + return std::make_shared(*frontend.photo_viewer); + case AppletId::LibAppletOff: + return std::make_shared(*frontend.web_browser); + default: + UNIMPLEMENTED_MSG( + "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", + static_cast(id)); + return std::make_shared(); + } +} + } // 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 @@ union ResultCode; +namespace Core::Frontend { +class ErrorApplet; +class PhotoViewerApplet; +class ProfileSelectApplet; +class SoftwareKeyboardApplet; +class WebBrowserApplet; +} // namespace Core::Frontend + namespace Service::AM { class IStorage; namespace Applets { +enum class AppletId : u32 { + OverlayDisplay = 0x02, + QLaunch = 0x03, + Starter = 0x04, + Auth = 0x0A, + Cabinet = 0x0B, + Controller = 0x0C, + DataErase = 0x0D, + Error = 0x0E, + NetConnect = 0x0F, + ProfileSelect = 0x10, + SoftwareKeyboard = 0x11, + MiiEdit = 0x12, + LibAppletWeb = 0x13, + LibAppletShop = 0x14, + PhotoViewer = 0x15, + Settings = 0x16, + LibAppletOff = 0x17, + LibAppletWhitelisted = 0x18, + LibAppletAuth = 0x19, + MyPage = 0x1A, +}; + class AppletDataBroker final { public: AppletDataBroker(); @@ -105,5 +136,29 @@ protected: bool initialized = false; }; +struct AppletFrontendSet { + std::unique_ptr error; + std::unique_ptr photo_viewer; + std::unique_ptr profile_select; + std::unique_ptr software_keyboard; + std::unique_ptr web_browser; +}; + +class AppletManager { +public: + AppletManager(); + ~AppletManager(); + + void SetAppletFrontendSet(AppletFrontendSet set); + void SetDefaultAppletFrontendSet(); + void SetDefaultAppletsIfMissing(); + void ClearAll(); + + std::shared_ptr GetApplet(AppletId id) const; + +private: + AppletFrontendSet frontend; +}; + } // namespace Applets } // namespace Service::AM From 6cea62b756fd32f54fca62a945e79f2ce44752bc Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:33:18 -0400 Subject: [PATCH 02/13] am: Delegate applet creation to AppletManager --- src/core/hle/service/am/am.cpp | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) 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 @@ #include "core/hle/service/am/applets/applets.h" #include "core/hle/service/am/applets/profile_select.h" #include "core/hle/service/am/applets/software_keyboard.h" -#include "core/hle/service/am/applets/stub_applet.h" #include "core/hle/service/am/applets/web_browser.h" #include "core/hle/service/am/idle.h" #include "core/hle/service/am/omm.h" @@ -42,12 +41,6 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2}; constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3}; constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7}; -enum class AppletId : u32 { - ProfileSelect = 0x10, - SoftwareKeyboard = 0x11, - LibAppletOff = 0x17, -}; - constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA; struct LaunchParameters { @@ -886,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple ILibraryAppletCreator::~ILibraryAppletCreator() = default; -static std::shared_ptr GetAppletFromId(AppletId id) { - switch (id) { - case AppletId::ProfileSelect: - return std::make_shared(); - case AppletId::SoftwareKeyboard: - return std::make_shared(); - case AppletId::LibAppletOff: - return std::make_shared(); - default: - LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!", - static_cast(id)); - return std::make_shared(); - } -} - void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto applet_id = rp.PopRaw(); + const auto applet_id = rp.PopRaw(); const auto applet_mode = rp.PopRaw(); LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", static_cast(applet_id), applet_mode); - const auto applet = GetAppletFromId(applet_id); + const auto& applet_manager{Core::System::GetInstance().GetAppletManager()}; + const auto applet = applet_manager.GetApplet(applet_id); if (applet == nullptr) { LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast(applet_id)); From ec0bc3061e674c70958f97b1fad3dbeb8145d3f6 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:33:49 -0400 Subject: [PATCH 03/13] core: Remove specific applets in favor of AppletManager --- src/core/core.cpp | 50 ++++++++++++++++------------------------------- src/core/core.h | 29 ++++++++++++++------------- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index bc9e887b6..aa578a589 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -20,13 +20,18 @@ #include "core/file_sys/registered_cache.h" #include "core/file_sys/vfs_concat.h" #include "core/file_sys/vfs_real.h" +#include "core/frontend/applets/error.h" +#include "core/frontend/applets/general_frontend.h" +#include "core/frontend/applets/profile_select.h" +#include "core/frontend/applets/software_keyboard.h" +#include "core/frontend/applets/web_browser.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" -#include "core/hle/service/am/applets/software_keyboard.h" +#include "core/hle/service/am/applets/applets.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" #include "core/loader/loader.h" @@ -113,12 +118,7 @@ struct System::Impl { content_provider = std::make_unique(); /// Create default implementations of applets if one is not provided. - if (profile_selector == nullptr) - profile_selector = std::make_unique(); - if (software_keyboard == nullptr) - software_keyboard = std::make_unique(); - if (web_browser == nullptr) - web_browser = std::make_unique(); + applet_manager.SetDefaultAppletsIfMissing(); auto main_process = Kernel::Process::Create(system, "main"); kernel.MakeCurrentProcess(main_process.get()); @@ -224,9 +224,7 @@ struct System::Impl { app_loader.reset(); // Clear all applets - profile_selector.reset(); - software_keyboard.reset(); - web_browser.reset(); + applet_manager.ClearAll(); LOG_DEBUG(Core, "Shutdown OK"); } @@ -265,9 +263,7 @@ struct System::Impl { std::unique_ptr cheat_engine; /// Frontend applets - std::unique_ptr profile_selector; - std::unique_ptr software_keyboard; - std::unique_ptr web_browser; + Service::AM::Applets::AppletManager applet_manager; /// Service manager std::shared_ptr service_manager; @@ -477,20 +473,20 @@ std::shared_ptr System::GetFilesystem() const { return impl->virtual_filesystem; } -void System::SetProfileSelector(std::unique_ptr applet) { - impl->profile_selector = std::move(applet); +void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) { + impl->applet_manager.SetAppletFrontendSet(std::move(set)); } -const Frontend::ProfileSelectApplet& System::GetProfileSelector() const { - return *impl->profile_selector; +void System::SetDefaultAppletFrontendSet() { + impl->applet_manager.SetDefaultAppletFrontendSet(); } -void System::SetSoftwareKeyboard(std::unique_ptr applet) { - impl->software_keyboard = std::move(applet); +Service::AM::Applets::AppletManager& System::GetAppletManager() { + return impl->applet_manager; } -const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const { - return *impl->software_keyboard; +const Service::AM::Applets::AppletManager& System::GetAppletManager() const { + return impl->applet_manager; } void System::SetContentProvider(std::unique_ptr provider) { @@ -514,18 +510,6 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) { impl->content_provider->ClearSlot(slot); } -void System::SetWebBrowser(std::unique_ptr applet) { - impl->web_browser = std::move(applet); -} - -Frontend::WebBrowserApplet& System::GetWebBrowser() { - return *impl->web_browser; -} - -const Frontend::WebBrowserApplet& System::GetWebBrowser() const { - return *impl->web_browser; -} - System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) { return impl->Init(*this, emu_window); } 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 @@ namespace Core::Frontend { class EmuWindow; -class ProfileSelectApplet; -class SoftwareKeyboardApplet; -class WebBrowserApplet; } // namespace Core::Frontend namespace FileSys { @@ -38,9 +35,18 @@ class AppLoader; enum class ResultStatus : u16; } // namespace Loader -namespace Service::SM { +namespace Service { + +namespace AM::Applets { +struct AppletFrontendSet; +class AppletManager; +} // namespace AM::Applets + +namespace SM { class ServiceManager; -} // namespace Service::SM +} // namespace SM + +} // namespace Service namespace Tegra { class DebugContext; @@ -260,18 +266,13 @@ public: void RegisterCheatList(const std::vector& list, const std::string& build_id, VAddr code_region_start, VAddr code_region_end); - void SetProfileSelector(std::unique_ptr applet); + void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set); - const Frontend::ProfileSelectApplet& GetProfileSelector() const; + void SetDefaultAppletFrontendSet(); - void SetSoftwareKeyboard(std::unique_ptr applet); + Service::AM::Applets::AppletManager& GetAppletManager(); - const Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const; - - void SetWebBrowser(std::unique_ptr applet); - - Frontend::WebBrowserApplet& GetWebBrowser(); - const Frontend::WebBrowserApplet& GetWebBrowser() const; + const Service::AM::Applets::AppletManager& GetAppletManager() const; void SetContentProvider(std::unique_ptr provider); From f7540157e41f7ebcf06baed66947567a3a46019f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:34:23 -0400 Subject: [PATCH 04/13] web_browser: Make OpenPage const --- src/core/frontend/applets/web_browser.cpp | 2 +- src/core/frontend/applets/web_browser.h | 4 ++-- src/yuzu/applets/web_browser.cpp | 2 +- src/yuzu/applets/web_browser.h | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp index 3a3d3d0bf..6a36b4b8f 100644 --- a/src/core/frontend/applets/web_browser.cpp +++ b/src/core/frontend/applets/web_browser.cpp @@ -13,7 +13,7 @@ DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; void DefaultWebBrowserApplet::OpenPage(std::string_view filename, std::function unpack_romfs_callback, - std::function finished_callback) { + std::function finished_callback) const { LOG_INFO(Service_AM, "(STUBBED) called - No suitable web browser implementation found to open website page " "at '{}'!", diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h index f952856af..41d272d26 100644 --- a/src/core/frontend/applets/web_browser.h +++ b/src/core/frontend/applets/web_browser.h @@ -14,7 +14,7 @@ public: virtual ~WebBrowserApplet(); virtual void OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) = 0; + std::function finished_callback) const = 0; }; class DefaultWebBrowserApplet final : public WebBrowserApplet { @@ -22,7 +22,7 @@ public: ~DefaultWebBrowserApplet() override; void OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) override; + std::function finished_callback) const override; }; } // namespace Core::Frontend diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp index ac80b2fa2..5b7b73518 100644 --- a/src/yuzu/applets/web_browser.cpp +++ b/src/yuzu/applets/web_browser.cpp @@ -88,7 +88,7 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { QtWebBrowser::~QtWebBrowser() = default; void QtWebBrowser::OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) { + std::function finished_callback) const { this->unpack_romfs_callback = std::move(unpack_romfs_callback); this->finished_callback = std::move(finished_callback); diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h index 1a3d67353..983886586 100644 --- a/src/yuzu/applets/web_browser.h +++ b/src/yuzu/applets/web_browser.h @@ -38,7 +38,7 @@ public: ~QtWebBrowser() override; void OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) override; + std::function finished_callback) const override; signals: void MainWindowOpenPage(std::string_view filename, std::string_view additional_args) const; @@ -47,6 +47,6 @@ private: void MainWindowUnpackRomFS(); void MainWindowFinishedBrowsing(); - std::function unpack_romfs_callback; - std::function finished_callback; + mutable std::function unpack_romfs_callback; + mutable std::function finished_callback; }; From d273bec68fd867f047944ab9d28ac5c5c6617571 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:35:01 -0400 Subject: [PATCH 05/13] applets: Port current applets to take frontend in constructor As opposed to using Core::System::GetInstance() --- src/core/hle/service/am/applets/profile_select.cpp | 6 +++--- src/core/hle/service/am/applets/profile_select.h | 5 ++++- src/core/hle/service/am/applets/software_keyboard.cpp | 7 ++----- src/core/hle/service/am/applets/software_keyboard.h | 4 +++- src/core/hle/service/am/applets/web_browser.cpp | 4 +--- src/core/hle/service/am/applets/web_browser.h | 4 +++- 6 files changed, 16 insertions(+), 14 deletions(-) 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 { constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; -ProfileSelect::ProfileSelect() = default; +ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend) + : frontend(frontend) {} + ProfileSelect::~ProfileSelect() = default; void ProfileSelect::Initialize() { @@ -51,8 +53,6 @@ void ProfileSelect::Execute() { return; } - const auto& frontend{Core::System::GetInstance().GetProfileSelector()}; - frontend.SelectProfile([this](std::optional uuid) { SelectionComplete(uuid); }); } diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h index 787485f22..cb281dd52 100644 --- a/src/core/hle/service/am/applets/profile_select.h +++ b/src/core/hle/service/am/applets/profile_select.h @@ -7,6 +7,7 @@ #include #include "common/common_funcs.h" +#include "core/frontend/applets/software_keyboard.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applets/applets.h" @@ -28,7 +29,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco class ProfileSelect final : public Applet { public: - ProfileSelect(); + ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend); ~ProfileSelect() override; void Initialize() override; @@ -41,6 +42,8 @@ public: void SelectionComplete(std::optional uuid); private: + const Core::Frontend::ProfileSelectApplet& frontend; + UserSelectionConfig config; bool complete = false; 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( return params; } -SoftwareKeyboard::SoftwareKeyboard() = default; +SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend) + : frontend(frontend) {} SoftwareKeyboard::~SoftwareKeyboard() = default; @@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() { if (status == INTERACTIVE_STATUS_OK) { complete = true; } else { - const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; - std::array string; std::memcpy(string.data(), data.data() + 4, string.size() * 2); frontend.SendTextCheckDialog( @@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() { return; } - const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()}; - const auto parameters = ConvertToFrontendParameters(config, initial_text); frontend.RequestText([this](std::optional 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..e97e1cd5b 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 class SoftwareKeyboard final : public Applet { public: - SoftwareKeyboard(); + SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend); ~SoftwareKeyboard() override; void Initialize() override; @@ -68,6 +68,8 @@ public: void WriteText(std::optional text); private: + const Core::Frontend::SoftwareKeyboardApplet& frontend; + KeyboardConfig config; std::u16string initial_text; bool complete = false; diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 7e17df98a..a66e23fce 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() { return nullptr; } -WebBrowser::WebBrowser() = default; +WebBrowser::WebBrowser(const Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {} WebBrowser::~WebBrowser() = default; @@ -152,8 +152,6 @@ void WebBrowser::Execute() { return; } - auto& frontend{Core::System::GetInstance().GetWebBrowser()}; - frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); }); } diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index b9e228fac..894bdb35a 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 { class WebBrowser final : public Applet { public: - WebBrowser(); + WebBrowser(const Core::Frontend::WebBrowserApplet& frontend); ~WebBrowser() override; void Initialize() override; @@ -32,6 +32,8 @@ public: void Finalize(); private: + const Core::Frontend::WebBrowserApplet& frontend; + bool complete = false; bool unpacked = false; ResultCode status = RESULT_SUCCESS; From de3cfb1d37462a4843b8cd4e27ac400e1d479748 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:36:36 -0400 Subject: [PATCH 06/13] applets: Add Error applet Responsible for displaying error codes and messages --- src/core/hle/service/am/applets/error.cpp | 177 ++++++++++++++++++ src/core/hle/service/am/applets/error.h | 47 +++++ src/core/hle/service/am/applets/stub_applet.h | 24 --- 3 files changed, 224 insertions(+), 24 deletions(-) create mode 100644 src/core/hle/service/am/applets/error.cpp create mode 100644 src/core/hle/service/am/applets/error.h delete mode 100644 src/core/hle/service/am/applets/stub_applet.h 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..df0408edc --- /dev/null +++ b/src/core/hle/service/am/applets/error.cpp @@ -0,0 +1,177 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/string_util.h" +#include "core/core.h" +#include "core/frontend/applets/error.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/applets/error.h" + +namespace Service::AM::Applets { + +#pragma pack(push, 4) +struct ShowError { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(4); + bool use_64bit_error_code; + INSERT_PADDING_BYTES(1); + u64 error_code_64; + u32 error_code_32; +}; +static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size."); +#pragma pack(pop) + +struct ShowErrorRecord { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(6); + u64 error_code_64; + u64 posix_time; +}; +static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect size."); + +struct SystemErrorArg { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(6); + u64 error_code_64; + std::array language_code; + std::array main_text; + std::array detail_text; +}; +static_assert(sizeof(SystemErrorArg) == 0x1018, "ApplicationErrorArg has incorrect size."); + +struct ApplicationErrorArg { + u8 mode; + bool jump; + INSERT_PADDING_BYTES(6); + u32 error_code; + std::array language_code; + std::array main_text; + std::array detail_text; +}; +static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size."); + +union ErrorArguments { + ShowError error; + ShowErrorRecord error_record; + SystemErrorArg system_error; + ApplicationErrorArg application_error; +}; + +namespace { +template +void CopyArgumentData(const std::vector& data, T& variable) { + ASSERT(data.size() >= sizeof(T)); + std::memcpy(&variable, data.data(), sizeof(T)); +} + +ResultCode Decode64BitError(u64 error) { + const auto description = (error >> 32) & 0x1FFF; + auto module = error & 0x3FF; + if (module >= 2000) + module -= 2000; + module &= 0x1FF; + return {static_cast(module), static_cast(description)}; +} + +} // namespace + +Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {} + +Error::~Error() = default; + +void Error::Initialize() { + Applet::Initialize(); + args = std::make_unique(); + complete = false; + + const auto storage = broker.PopNormalDataToApplet(); + ASSERT(storage != nullptr); + const auto data = storage->GetData(); + + ASSERT(!data.empty()); + std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode)); + + switch (mode) { + case ErrorAppletMode::ShowError: + CopyArgumentData(data, args->error); + if (args->error.use_64bit_error_code) { + error_code = Decode64BitError(args->error.error_code_64); + } else { + error_code = ResultCode(args->error.error_code_32); + } + break; + case ErrorAppletMode::ShowSystemError: + CopyArgumentData(data, args->system_error); + error_code = ResultCode(Decode64BitError(args->system_error.error_code_64)); + case ErrorAppletMode::ShowApplicationError: + CopyArgumentData(data, args->application_error); + error_code = ResultCode(args->application_error.error_code); + break; + case ErrorAppletMode::ShowErrorRecord: + CopyArgumentData(data, args->error_record); + error_code = Decode64BitError(args->error_record.error_code_64); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast(mode)); + } +} + +bool Error::TransactionComplete() const { + return complete; +} + +ResultCode Error::GetStatus() const { + return RESULT_SUCCESS; +} + +void Error::ExecuteInteractive() { + UNREACHABLE_MSG("Unexpected interactive applet data!"); +} + +void Error::Execute() { + if (complete) { + return; + } + + const auto callback = [this] { DisplayCompleted(); }; + + switch (mode) { + case ErrorAppletMode::ShowError: + frontend.ShowError(error_code, callback); + break; + case ErrorAppletMode::ShowSystemError: + case ErrorAppletMode::ShowApplicationError: { + const auto system = mode == ErrorAppletMode::ShowSystemError; + const auto& main_text = + system ? args->system_error.main_text : args->application_error.main_text; + const auto& detail_text = + system ? args->system_error.detail_text : args->application_error.detail_text; + + frontend.ShowCustomErrorText( + error_code, + Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()), + Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()), + callback); + break; + } + case ErrorAppletMode::ShowErrorRecord: + frontend.ShowErrorWithTimestamp( + error_code, std::chrono::seconds{args->error_record.posix_time}, callback); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast(mode)); + DisplayCompleted(); + } +} + +void Error::DisplayCompleted() { + complete = true; + broker.PushNormalDataFromApplet(IStorage{{}}); + broker.SignalStateChanged(); +} + +} // 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..fcf9caef2 --- /dev/null +++ b/src/core/hle/service/am/applets/error.h @@ -0,0 +1,47 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" +#include "core/hle/service/am/applets/applets.h" + +namespace Service::AM::Applets { + +union ErrorArguments; + +enum class ErrorAppletMode : u8 { + ShowError = 0, + ShowSystemError = 1, + ShowApplicationError = 2, + ShowEula = 3, + ShowErrorPctl = 4, + ShowErrorRecord = 5, + ShowUpdateEula = 8, +}; + +class Error final : public Applet { +public: + Error(const Core::Frontend::ErrorApplet& frontend); + ~Error() override; + + void Initialize() override; + + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; + + void DisplayCompleted(); + +private: + const Core::Frontend::ErrorApplet& frontend; + ResultCode error_code = RESULT_SUCCESS; + ErrorAppletMode mode; + std::unique_ptr args; + + bool complete; +}; + +} // namespace Service::AM::Applets 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 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "core/hle/service/am/applets/applets.h" - -namespace Service::AM::Applets { - -class StubApplet final : public Applet { -public: - StubApplet(); - ~StubApplet() override; - - void Initialize() override; - - bool TransactionComplete() const override; - ResultCode GetStatus() const override; - void ExecuteInteractive() override; - void Execute() override; -}; - -} // namespace Service::AM::Applets From d9f6715d459630d165537c19e48cc2ddd54b294b Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:37:10 -0400 Subject: [PATCH 07/13] frontend: Add frontend receiver for Error applet --- src/core/CMakeLists.txt | 10 ++++++-- src/core/frontend/applets/error.cpp | 34 ++++++++++++++++++++++++++ src/core/frontend/applets/error.h | 37 +++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/core/frontend/applets/error.cpp create mode 100644 src/core/frontend/applets/error.h 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 file_sys/vfs_vector.h file_sys/xts_archive.cpp file_sys/xts_archive.h + frontend/applets/error.cpp + frontend/applets/error.h + frontend/applets/general_frontend.cpp + frontend/applets/general_frontend.h frontend/applets/profile_select.cpp frontend/applets/profile_select.h frontend/applets/software_keyboard.cpp @@ -177,12 +181,14 @@ add_library(core STATIC hle/service/am/applet_oe.h hle/service/am/applets/applets.cpp hle/service/am/applets/applets.h + hle/service/am/applets/error.cpp + hle/service/am/applets/error.h + hle/service/am/applets/general_backend.cpp + hle/service/am/applets/general_backend.h hle/service/am/applets/profile_select.cpp hle/service/am/applets/profile_select.h hle/service/am/applets/software_keyboard.cpp hle/service/am/applets/software_keyboard.h - hle/service/am/applets/stub_applet.cpp - hle/service/am/applets/stub_applet.h hle/service/am/applets/web_browser.cpp hle/service/am/applets/web_browser.h hle/service/am/idle.cpp 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 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/frontend/applets/error.h" + +namespace Core::Frontend { + +ErrorApplet::~ErrorApplet() = default; + +void DefaultErrorApplet::ShowError(ResultCode error, std::function finished) const { + LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})", + static_cast(error.module.Value()), error.description.Value(), error.raw); +} + +void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, + std::function finished) const { + LOG_CRITICAL( + Service_Fatal, + "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}", + static_cast(error.module.Value()), error.description.Value(), error.raw, time.count()); +} + +void DefaultErrorApplet::ShowCustomErrorText(ResultCode error, std::string main_text, + std::string detail_text, + std::function finished) const { + LOG_CRITICAL(Service_Fatal, + "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})", + static_cast(error.module.Value()), error.description.Value(), error.raw); + LOG_CRITICAL(Service_Fatal, " Main Text: {}", main_text); + LOG_CRITICAL(Service_Fatal, " Detail Text: {}", detail_text); +} + +} // 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 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "core/hle/result.h" + +namespace Core::Frontend { + +class ErrorApplet { +public: + virtual ~ErrorApplet(); + + virtual void ShowError(ResultCode error, std::function finished) const = 0; + + virtual void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, + std::function finished) const = 0; + + virtual void ShowCustomErrorText(ResultCode error, std::string dialog_text, + std::string fullscreen_text, + std::function finished) const = 0; +}; + +class DefaultErrorApplet final : public ErrorApplet { +public: + void ShowError(ResultCode error, std::function finished) const override; + void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, + std::function finished) const override; + void ShowCustomErrorText(ResultCode error, std::string main_text, std::string detail_text, + std::function finished) const override; +}; + +} // namespace Core::Frontend From 80c9e4d3ab7e7b7a4eeda8c3467039d8ca48ff62 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:37:35 -0400 Subject: [PATCH 08/13] general_frontend: Add frontend scaffold for PhotoViewer applet --- .../frontend/applets/general_frontend.cpp | 27 ++++++++++++++++++ src/core/frontend/applets/general_frontend.h | 28 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/core/frontend/applets/general_frontend.cpp create mode 100644 src/core/frontend/applets/general_frontend.h diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general_frontend.cpp new file mode 100644 index 000000000..d2762db96 --- /dev/null +++ b/src/core/frontend/applets/general_frontend.cpp @@ -0,0 +1,27 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/frontend/applets/general_frontend.h" + +namespace Core::Frontend { + +PhotoViewerApplet::~PhotoViewerApplet() = default; + +DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() {} + +void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id, + std::function finished) const { + LOG_INFO(Service_AM, + "Application requested frontend to display stored photos for title_id={:016X}", + title_id); + finished(); +} + +void DefaultPhotoViewerApplet::ShowAllPhotos(std::function finished) const { + LOG_INFO(Service_AM, "Application requested frontend to display all stored photos."); + finished(); +} + +} // 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 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" + +namespace Core::Frontend { + +class PhotoViewerApplet { +public: + virtual ~PhotoViewerApplet(); + + virtual void ShowPhotosForApplication(u64 title_id, std::function finished) const = 0; + virtual void ShowAllPhotos(std::function finished) const = 0; +}; + +class DefaultPhotoViewerApplet final : public PhotoViewerApplet { +public: + ~DefaultPhotoViewerApplet() override; + + void ShowPhotosForApplication(u64 title_id, std::function finished) const override; + void ShowAllPhotos(std::function finished) const override; +}; + +} // namespace Core::Frontend From f6e229505583d37c8320f3a01b3f86018fcde22b Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:38:53 -0400 Subject: [PATCH 09/13] general_backend: Move StubApplet and add backend PhotoViewer --- .../{stub_applet.cpp => general_backend.cpp} | 55 ++++++++++++++++++- .../hle/service/am/applets/general_backend.h | 48 ++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) rename src/core/hle/service/am/applets/{stub_applet.cpp => general_backend.cpp} (60%) create mode 100644 src/core/hle/service/am/applets/general_backend.h diff --git a/src/core/hle/service/am/applets/stub_applet.cpp b/src/core/hle/service/am/applets/general_backend.cpp similarity index 60% rename from src/core/hle/service/am/applets/stub_applet.cpp rename to src/core/hle/service/am/applets/general_backend.cpp index ed166b87d..18ab0718b 100644 --- a/src/core/hle/service/am/applets/stub_applet.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp @@ -6,9 +6,12 @@ #include "common/hex_util.h" #include "common/logging/log.h" +#include "core/core.h" +#include "core/frontend/applets/general_frontend.h" +#include "core/hle/kernel/process.h" #include "core/hle/result.h" #include "core/hle/service/am/am.h" -#include "core/hle/service/am/applets/stub_applet.h" +#include "core/hle/service/am/applets/general_backend.h" namespace Service::AM::Applets { @@ -30,6 +33,55 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) { } } +PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {} + +PhotoViewer::~PhotoViewer() = default; + +void PhotoViewer::Initialize() { + Applet::Initialize(); + complete = false; + + const auto storage = broker.PopNormalDataToApplet(); + ASSERT(storage != nullptr); + const auto data = storage->GetData(); + ASSERT(!data.empty()); + mode = static_cast(data[0]); +} + +bool PhotoViewer::TransactionComplete() const { + return complete; +} + +ResultCode PhotoViewer::GetStatus() const { + return RESULT_SUCCESS; +} + +void PhotoViewer::ExecuteInteractive() { + UNREACHABLE_MSG("Unexpected interactive applet data."); +} + +void PhotoViewer::Execute() { + if (complete) + return; + + const auto callback = [this] { ViewFinished(); }; + switch (mode) { + case PhotoViewerAppletMode::CurrentApp: + frontend.ShowPhotosForApplication(Core::CurrentProcess()->GetTitleID(), callback); + break; + case PhotoViewerAppletMode::AllApps: + frontend.ShowAllPhotos(callback); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast(mode)); + } +} + +void PhotoViewer::ViewFinished() { + broker.PushNormalDataFromApplet(IStorage{{}}); + broker.SignalStateChanged(); +} + StubApplet::StubApplet() = default; StubApplet::~StubApplet() = default; @@ -67,4 +119,5 @@ void StubApplet::Execute() { broker.PushInteractiveDataFromApplet(IStorage{std::vector(0x1000)}); broker.SignalStateChanged(); } + } // 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..d7313e74a --- /dev/null +++ b/src/core/hle/service/am/applets/general_backend.h @@ -0,0 +1,48 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/am/applets/applets.h" + +namespace Service::AM::Applets { + +enum class PhotoViewerAppletMode : u8 { + CurrentApp = 0, + AllApps = 1, +}; + +class PhotoViewer final : public Applet { +public: + PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend); + ~PhotoViewer() override; + + void Initialize() override; + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; + + void ViewFinished(); + +private: + const Core::Frontend::PhotoViewerApplet& frontend; + bool complete; + PhotoViewerAppletMode mode; +}; + +class StubApplet final : public Applet { +public: + StubApplet(); + ~StubApplet() override; + + void Initialize() override; + + bool TransactionComplete() const override; + ResultCode GetStatus() const override; + void ExecuteInteractive() override; + void Execute() override; +}; + +} // namespace Service::AM::Applets From 76452cd5b3bfd71ebc17ec8da4c593cdd5ee6d0e Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:39:20 -0400 Subject: [PATCH 10/13] qt: Add dialog implementation of Error applet --- src/yuzu/CMakeLists.txt | 2 ++ src/yuzu/applets/error.cpp | 59 ++++++++++++++++++++++++++++++++++++++ src/yuzu/applets/error.h | 33 +++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 src/yuzu/applets/error.cpp create mode 100644 src/yuzu/applets/error.h 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 Info.plist about_dialog.cpp about_dialog.h + applets/error.cpp + applets/error.h applets/profile_select.cpp applets/profile_select.h applets/software_keyboard.cpp diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp new file mode 100644 index 000000000..f7535e768 --- /dev/null +++ b/src/yuzu/applets/error.cpp @@ -0,0 +1,59 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "core/hle/lock.h" +#include "yuzu/applets/error.h" +#include "yuzu/main.h" + +QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) { + connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent, + &GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection); + connect(&parent, &GMainWindow::ErrorDisplayFinished, this, + &QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection); +} + +QtErrorDisplay::~QtErrorDisplay() = default; + +void QtErrorDisplay::ShowError(ResultCode error, std::function finished) const { + this->callback = finished; + emit MainWindowDisplayError( + tr("An error has occured.\nPlease try again or contact the developer of the " + "software.\n\nError Code: %1-%2 (0x%3)") + .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) + .arg(error.description, 4, 10, QChar::fromLatin1('0')) + .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); +} + +void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, + std::function finished) const { + this->callback = finished; + emit MainWindowDisplayError( + tr("An error occured on %1 at %2.\nPlease try again or contact the " + "developer of the software.\n\nError Code: %3-%4 (0x%5)") + .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("dddd, MMMM d, yyyy")) + .arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("h:mm:ss A")) + .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) + .arg(error.description, 4, 10, QChar::fromLatin1('0')) + .arg(error.raw, 8, 16, QChar::fromLatin1('0'))); +} + +void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, + std::string fullscreen_text, + std::function finished) const { + this->callback = finished; + emit MainWindowDisplayError( + tr("An error has occured.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5") + .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) + .arg(error.description, 4, 10, QChar::fromLatin1('0')) + .arg(error.raw, 8, 16, QChar::fromLatin1('0')) + .arg(QString::fromStdString(dialog_text)) + .arg(QString::fromStdString(fullscreen_text))); +} + +void QtErrorDisplay::MainWindowFinishedError() { + // Acquire the HLE mutex + std::lock_guard lock(HLE::g_hle_lock); + callback(); +} 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 @@ +// Copyright 2019 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "core/frontend/applets/error.h" + +class GMainWindow; + +class QtErrorDisplay final : public QObject, public Core::Frontend::ErrorApplet { + Q_OBJECT + +public: + explicit QtErrorDisplay(GMainWindow& parent); + ~QtErrorDisplay() override; + + void ShowError(ResultCode error, std::function finished) const override; + void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, + std::function finished) const override; + void ShowCustomErrorText(ResultCode error, std::string dialog_text, std::string fullscreen_text, + std::function finished) const override; + +signals: + void MainWindowDisplayError(QString error) const; + +private: + void MainWindowFinishedError(); + + mutable std::function callback; +}; From a04d36c5a407ba3d182cbc8ee9695bc39f46ca4f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:39:48 -0400 Subject: [PATCH 11/13] main: Switch to AppletManager for frontend --- src/yuzu/main.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index bdee44b04..c73e78a23 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -8,6 +8,7 @@ #include // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. +#include "applets/error.h" #include "applets/profile_select.h" #include "applets/software_keyboard.h" #include "applets/web_browser.h" @@ -15,6 +16,7 @@ #include "configuration/configure_per_general.h" #include "core/file_sys/vfs.h" #include "core/file_sys/vfs_real.h" +#include "core/frontend/applets/general_frontend.h" #include "core/frontend/scope_acquire_window_context.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applets/applets.h" @@ -795,9 +797,13 @@ bool GMainWindow::LoadROM(const QString& filename) { system.SetGPUDebugContext(debug_context); - system.SetProfileSelector(std::make_unique(*this)); - system.SetSoftwareKeyboard(std::make_unique(*this)); - system.SetWebBrowser(std::make_unique(*this)); + system.SetAppletFrontendSet({ + std::make_unique(*this), + nullptr, + std::make_unique(*this), + std::make_unique(*this), + std::make_unique(*this), + }); const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())}; From 8f8049e846f38d548e975243bc42ce1b09a71ae3 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 11 Mar 2019 19:45:22 -0400 Subject: [PATCH 12/13] main: Add GMainWindow hooks for Error display --- src/core/frontend/applets/general_frontend.cpp | 2 +- src/core/hle/service/am/applets/error.cpp | 4 ++-- src/yuzu/main.cpp | 5 +++++ src/yuzu/main.h | 3 +++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/core/frontend/applets/general_frontend.cpp b/src/core/frontend/applets/general_frontend.cpp index d2762db96..b974f2289 100644 --- a/src/core/frontend/applets/general_frontend.cpp +++ b/src/core/frontend/applets/general_frontend.cpp @@ -1,4 +1,4 @@ -// Copyright 2018 yuzu emulator team +// Copyright 2019 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index df0408edc..fec014f3b 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp @@ -41,7 +41,7 @@ struct SystemErrorArg { std::array main_text; std::array detail_text; }; -static_assert(sizeof(SystemErrorArg) == 0x1018, "ApplicationErrorArg has incorrect size."); +static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size."); struct ApplicationErrorArg { u8 mode; @@ -77,7 +77,7 @@ ResultCode Decode64BitError(u64 error) { return {static_cast(module), static_cast(description)}; } -} // namespace +} // Anonymous namespace Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {} diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c73e78a23..e33e3aaaf 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1589,6 +1589,11 @@ void GMainWindow::OnLoadComplete() { loading_screen->OnLoadComplete(); } +void GMainWindow::ErrorDisplayDisplayError(QString body) { + QMessageBox::critical(this, tr("Error Display"), body); + emit ErrorDisplayFinished(); +} + void GMainWindow::OnMenuReportCompatibility() { if (!Settings::values.yuzu_token.empty() && !Settings::values.yuzu_username.empty()) { 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: // Signal that tells widgets to update icons to use the current theme void UpdateThemedIcons(); + void ErrorDisplayFinished(); + void ProfileSelectorFinishedSelection(std::optional uuid); void SoftwareKeyboardFinishedText(std::optional text); void SoftwareKeyboardFinishedCheckDialog(); @@ -111,6 +113,7 @@ signals: public slots: void OnLoadComplete(); + void ErrorDisplayDisplayError(QString body); void ProfileSelectorSelectProfile(); void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters); void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message); From 2adb226b26f7f4b9a2c5cd4ea056479d7b5c1527 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 4 Apr 2019 18:09:42 -0400 Subject: [PATCH 13/13] web_browser: Make OpenPage non-const --- src/core/frontend/applets/web_browser.cpp | 2 +- src/core/frontend/applets/web_browser.h | 4 ++-- src/core/hle/service/am/applets/error.cpp | 7 ++++++- src/core/hle/service/am/applets/error.h | 10 +++++----- src/core/hle/service/am/applets/general_backend.cpp | 1 + src/core/hle/service/am/applets/general_backend.h | 6 +++--- src/core/hle/service/am/applets/profile_select.h | 3 +-- src/core/hle/service/am/applets/software_keyboard.h | 2 +- src/core/hle/service/am/applets/web_browser.cpp | 2 +- src/core/hle/service/am/applets/web_browser.h | 4 ++-- src/yuzu/applets/error.cpp | 6 +++--- src/yuzu/applets/web_browser.cpp | 2 +- src/yuzu/applets/web_browser.h | 6 +++--- 13 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp index 6a36b4b8f..3a3d3d0bf 100644 --- a/src/core/frontend/applets/web_browser.cpp +++ b/src/core/frontend/applets/web_browser.cpp @@ -13,7 +13,7 @@ DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; void DefaultWebBrowserApplet::OpenPage(std::string_view filename, std::function unpack_romfs_callback, - std::function finished_callback) const { + std::function finished_callback) { LOG_INFO(Service_AM, "(STUBBED) called - No suitable web browser implementation found to open website page " "at '{}'!", diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h index 41d272d26..f952856af 100644 --- a/src/core/frontend/applets/web_browser.h +++ b/src/core/frontend/applets/web_browser.h @@ -14,7 +14,7 @@ public: virtual ~WebBrowserApplet(); virtual void OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) const = 0; + std::function finished_callback) = 0; }; class DefaultWebBrowserApplet final : public WebBrowserApplet { @@ -22,7 +22,7 @@ public: ~DefaultWebBrowserApplet() override; void OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) const override; + std::function finished_callback) override; }; } // namespace Core::Frontend diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index fec014f3b..04774bedc 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp @@ -2,6 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include "common/assert.h" +#include "common/logging/log.h" #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/error.h" @@ -54,7 +58,7 @@ struct ApplicationErrorArg { }; static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size."); -union ErrorArguments { +union Error::ErrorArguments { ShowError error; ShowErrorRecord error_record; SystemErrorArg system_error; @@ -107,6 +111,7 @@ void Error::Initialize() { case ErrorAppletMode::ShowSystemError: CopyArgumentData(data, args->system_error); error_code = ResultCode(Decode64BitError(args->system_error.error_code_64)); + break; case ErrorAppletMode::ShowApplicationError: CopyArgumentData(data, args->application_error); error_code = ResultCode(args->application_error.error_code); diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h index fcf9caef2..a3590d181 100644 --- a/src/core/hle/service/am/applets/error.h +++ b/src/core/hle/service/am/applets/error.h @@ -9,8 +9,6 @@ namespace Service::AM::Applets { -union ErrorArguments; - enum class ErrorAppletMode : u8 { ShowError = 0, ShowSystemError = 1, @@ -23,7 +21,7 @@ enum class ErrorAppletMode : u8 { class Error final : public Applet { public: - Error(const Core::Frontend::ErrorApplet& frontend); + explicit Error(const Core::Frontend::ErrorApplet& frontend); ~Error() override; void Initialize() override; @@ -36,12 +34,14 @@ public: void DisplayCompleted(); private: + union ErrorArguments; + const Core::Frontend::ErrorApplet& frontend; ResultCode error_code = RESULT_SUCCESS; - ErrorAppletMode mode; + ErrorAppletMode mode = ErrorAppletMode::ShowError; std::unique_ptr args; - bool complete; + bool complete = false; }; } // namespace Service::AM::Applets diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index 18ab0718b..c591b9ac2 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp @@ -4,6 +4,7 @@ #include +#include "common/assert.h" #include "common/hex_util.h" #include "common/logging/log.h" #include "core/core.h" diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h index d7313e74a..2dd255d7c 100644 --- a/src/core/hle/service/am/applets/general_backend.h +++ b/src/core/hle/service/am/applets/general_backend.h @@ -15,7 +15,7 @@ enum class PhotoViewerAppletMode : u8 { class PhotoViewer final : public Applet { public: - PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend); + explicit PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend); ~PhotoViewer() override; void Initialize() override; @@ -28,8 +28,8 @@ public: private: const Core::Frontend::PhotoViewerApplet& frontend; - bool complete; - PhotoViewerAppletMode mode; + bool complete = false; + PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp; }; class StubApplet final : public Applet { diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h index cb281dd52..a2ac6cf50 100644 --- a/src/core/hle/service/am/applets/profile_select.h +++ b/src/core/hle/service/am/applets/profile_select.h @@ -7,7 +7,6 @@ #include #include "common/common_funcs.h" -#include "core/frontend/applets/software_keyboard.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/am/applets/applets.h" @@ -29,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco class ProfileSelect final : public Applet { public: - ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend); + explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend); ~ProfileSelect() override; void Initialize() override; diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h index e97e1cd5b..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 class SoftwareKeyboard final : public Applet { public: - SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend); + explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend); ~SoftwareKeyboard() override; void Initialize() override; diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index a66e23fce..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() { return nullptr; } -WebBrowser::WebBrowser(const Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {} +WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {} WebBrowser::~WebBrowser() = default; diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h index 894bdb35a..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 { class WebBrowser final : public Applet { public: - WebBrowser(const Core::Frontend::WebBrowserApplet& frontend); + WebBrowser(Core::Frontend::WebBrowserApplet& frontend); ~WebBrowser() override; void Initialize() override; @@ -32,7 +32,7 @@ public: void Finalize(); private: - const Core::Frontend::WebBrowserApplet& frontend; + Core::Frontend::WebBrowserApplet& frontend; bool complete = false; bool unpacked = false; diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp index f7535e768..1fb2fe277 100644 --- a/src/yuzu/applets/error.cpp +++ b/src/yuzu/applets/error.cpp @@ -17,7 +17,7 @@ QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) { QtErrorDisplay::~QtErrorDisplay() = default; void QtErrorDisplay::ShowError(ResultCode error, std::function finished) const { - this->callback = finished; + this->callback = std::move(finished); emit MainWindowDisplayError( tr("An error has occured.\nPlease try again or contact the developer of the " "software.\n\nError Code: %1-%2 (0x%3)") @@ -28,7 +28,7 @@ void QtErrorDisplay::ShowError(ResultCode error, std::function finished) void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, std::function finished) const { - this->callback = finished; + this->callback = std::move(finished); emit MainWindowDisplayError( tr("An error occured on %1 at %2.\nPlease try again or contact the " "developer of the software.\n\nError Code: %3-%4 (0x%5)") @@ -42,7 +42,7 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, std::string fullscreen_text, std::function finished) const { - this->callback = finished; + this->callback = std::move(finished); emit MainWindowDisplayError( tr("An error has occured.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5") .arg(static_cast(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0')) diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp index 5b7b73518..ac80b2fa2 100644 --- a/src/yuzu/applets/web_browser.cpp +++ b/src/yuzu/applets/web_browser.cpp @@ -88,7 +88,7 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { QtWebBrowser::~QtWebBrowser() = default; void QtWebBrowser::OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) const { + std::function finished_callback) { this->unpack_romfs_callback = std::move(unpack_romfs_callback); this->finished_callback = std::move(finished_callback); diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h index 983886586..1a3d67353 100644 --- a/src/yuzu/applets/web_browser.h +++ b/src/yuzu/applets/web_browser.h @@ -38,7 +38,7 @@ public: ~QtWebBrowser() override; void OpenPage(std::string_view url, std::function unpack_romfs_callback, - std::function finished_callback) const override; + std::function finished_callback) override; signals: void MainWindowOpenPage(std::string_view filename, std::string_view additional_args) const; @@ -47,6 +47,6 @@ private: void MainWindowUnpackRomFS(); void MainWindowFinishedBrowsing(); - mutable std::function unpack_romfs_callback; - mutable std::function finished_callback; + std::function unpack_romfs_callback; + std::function finished_callback; };