forked from suyu/suyu
Merge pull request #2228 from DarkLordZach/applet-manager-p1
applets: Add AppletManager and implement PhotoViewer and Error applets
This commit is contained in:
commit
53f746fa9a
26 changed files with 764 additions and 115 deletions
|
@ -88,6 +88,10 @@ add_library(core STATIC
|
||||||
file_sys/vfs_vector.h
|
file_sys/vfs_vector.h
|
||||||
file_sys/xts_archive.cpp
|
file_sys/xts_archive.cpp
|
||||||
file_sys/xts_archive.h
|
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.cpp
|
||||||
frontend/applets/profile_select.h
|
frontend/applets/profile_select.h
|
||||||
frontend/applets/software_keyboard.cpp
|
frontend/applets/software_keyboard.cpp
|
||||||
|
@ -177,12 +181,14 @@ add_library(core STATIC
|
||||||
hle/service/am/applet_oe.h
|
hle/service/am/applet_oe.h
|
||||||
hle/service/am/applets/applets.cpp
|
hle/service/am/applets/applets.cpp
|
||||||
hle/service/am/applets/applets.h
|
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.cpp
|
||||||
hle/service/am/applets/profile_select.h
|
hle/service/am/applets/profile_select.h
|
||||||
hle/service/am/applets/software_keyboard.cpp
|
hle/service/am/applets/software_keyboard.cpp
|
||||||
hle/service/am/applets/software_keyboard.h
|
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.cpp
|
||||||
hle/service/am/applets/web_browser.h
|
hle/service/am/applets/web_browser.h
|
||||||
hle/service/am/idle.cpp
|
hle/service/am/idle.cpp
|
||||||
|
|
|
@ -18,13 +18,18 @@
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "core/file_sys/registered_cache.h"
|
||||||
#include "core/file_sys/vfs_concat.h"
|
#include "core/file_sys/vfs_concat.h"
|
||||||
#include "core/file_sys/vfs_real.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/gdbstub/gdbstub.h"
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
#include "core/hle/kernel/thread.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/service.h"
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
|
@ -110,12 +115,7 @@ struct System::Impl {
|
||||||
content_provider = std::make_unique<FileSys::ContentProviderUnion>();
|
content_provider = std::make_unique<FileSys::ContentProviderUnion>();
|
||||||
|
|
||||||
/// Create default implementations of applets if one is not provided.
|
/// Create default implementations of applets if one is not provided.
|
||||||
if (profile_selector == nullptr)
|
applet_manager.SetDefaultAppletsIfMissing();
|
||||||
profile_selector = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
|
|
||||||
if (software_keyboard == nullptr)
|
|
||||||
software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
|
|
||||||
if (web_browser == nullptr)
|
|
||||||
web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
|
|
||||||
|
|
||||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||||
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
service_manager = std::make_shared<Service::SM::ServiceManager>();
|
||||||
|
@ -223,9 +223,7 @@ struct System::Impl {
|
||||||
app_loader.reset();
|
app_loader.reset();
|
||||||
|
|
||||||
// Clear all applets
|
// Clear all applets
|
||||||
profile_selector.reset();
|
applet_manager.ClearAll();
|
||||||
software_keyboard.reset();
|
|
||||||
web_browser.reset();
|
|
||||||
|
|
||||||
LOG_DEBUG(Core, "Shutdown OK");
|
LOG_DEBUG(Core, "Shutdown OK");
|
||||||
}
|
}
|
||||||
|
@ -264,9 +262,7 @@ struct System::Impl {
|
||||||
std::unique_ptr<FileSys::CheatEngine> cheat_engine;
|
std::unique_ptr<FileSys::CheatEngine> cheat_engine;
|
||||||
|
|
||||||
/// Frontend applets
|
/// Frontend applets
|
||||||
std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_selector;
|
Service::AM::Applets::AppletManager applet_manager;
|
||||||
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
|
|
||||||
std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
|
|
||||||
|
|
||||||
/// Service manager
|
/// Service manager
|
||||||
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
std::shared_ptr<Service::SM::ServiceManager> service_manager;
|
||||||
|
@ -476,20 +472,20 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
|
||||||
return impl->virtual_filesystem;
|
return impl->virtual_filesystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet) {
|
void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
|
||||||
impl->profile_selector = std::move(applet);
|
impl->applet_manager.SetAppletFrontendSet(std::move(set));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Frontend::ProfileSelectApplet& System::GetProfileSelector() const {
|
void System::SetDefaultAppletFrontendSet() {
|
||||||
return *impl->profile_selector;
|
impl->applet_manager.SetDefaultAppletFrontendSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet) {
|
Service::AM::Applets::AppletManager& System::GetAppletManager() {
|
||||||
impl->software_keyboard = std::move(applet);
|
return impl->applet_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const {
|
const Service::AM::Applets::AppletManager& System::GetAppletManager() const {
|
||||||
return *impl->software_keyboard;
|
return impl->applet_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
|
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
|
||||||
|
@ -513,18 +509,6 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
|
||||||
impl->content_provider->ClearSlot(slot);
|
impl->content_provider->ClearSlot(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> 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) {
|
System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
|
||||||
return impl->Init(*this, emu_window);
|
return impl->Init(*this, emu_window);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
|
|
||||||
namespace Core::Frontend {
|
namespace Core::Frontend {
|
||||||
class EmuWindow;
|
class EmuWindow;
|
||||||
class ProfileSelectApplet;
|
|
||||||
class SoftwareKeyboardApplet;
|
|
||||||
class WebBrowserApplet;
|
|
||||||
} // namespace Core::Frontend
|
} // namespace Core::Frontend
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
@ -38,9 +35,18 @@ class AppLoader;
|
||||||
enum class ResultStatus : u16;
|
enum class ResultStatus : u16;
|
||||||
} // namespace Loader
|
} // namespace Loader
|
||||||
|
|
||||||
namespace Service::SM {
|
namespace Service {
|
||||||
|
|
||||||
|
namespace AM::Applets {
|
||||||
|
struct AppletFrontendSet;
|
||||||
|
class AppletManager;
|
||||||
|
} // namespace AM::Applets
|
||||||
|
|
||||||
|
namespace SM {
|
||||||
class ServiceManager;
|
class ServiceManager;
|
||||||
} // namespace Service::SM
|
} // namespace SM
|
||||||
|
|
||||||
|
} // namespace Service
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class DebugContext;
|
class DebugContext;
|
||||||
|
@ -260,18 +266,13 @@ public:
|
||||||
void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id,
|
void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id,
|
||||||
VAddr code_region_start, VAddr code_region_end);
|
VAddr code_region_start, VAddr code_region_end);
|
||||||
|
|
||||||
void SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet);
|
void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
|
||||||
|
|
||||||
const Frontend::ProfileSelectApplet& GetProfileSelector() const;
|
void SetDefaultAppletFrontendSet();
|
||||||
|
|
||||||
void SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet);
|
Service::AM::Applets::AppletManager& GetAppletManager();
|
||||||
|
|
||||||
const Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
|
const Service::AM::Applets::AppletManager& GetAppletManager() const;
|
||||||
|
|
||||||
void SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet);
|
|
||||||
|
|
||||||
Frontend::WebBrowserApplet& GetWebBrowser();
|
|
||||||
const Frontend::WebBrowserApplet& GetWebBrowser() const;
|
|
||||||
|
|
||||||
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
||||||
|
|
||||||
|
|
34
src/core/frontend/applets/error.cpp
Normal file
34
src/core/frontend/applets/error.cpp
Normal file
|
@ -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<void()> finished) const {
|
||||||
|
LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
|
||||||
|
static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
|
||||||
|
std::function<void()> finished) const {
|
||||||
|
LOG_CRITICAL(
|
||||||
|
Service_Fatal,
|
||||||
|
"Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}",
|
||||||
|
static_cast<u32>(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<void()> finished) const {
|
||||||
|
LOG_CRITICAL(Service_Fatal,
|
||||||
|
"Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})",
|
||||||
|
static_cast<u32>(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
|
37
src/core/frontend/applets/error.h
Normal file
37
src/core/frontend/applets/error.h
Normal file
|
@ -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 <chrono>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
|
namespace Core::Frontend {
|
||||||
|
|
||||||
|
class ErrorApplet {
|
||||||
|
public:
|
||||||
|
virtual ~ErrorApplet();
|
||||||
|
|
||||||
|
virtual void ShowError(ResultCode error, std::function<void()> finished) const = 0;
|
||||||
|
|
||||||
|
virtual void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
|
||||||
|
std::function<void()> finished) const = 0;
|
||||||
|
|
||||||
|
virtual void ShowCustomErrorText(ResultCode error, std::string dialog_text,
|
||||||
|
std::string fullscreen_text,
|
||||||
|
std::function<void()> finished) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DefaultErrorApplet final : public ErrorApplet {
|
||||||
|
public:
|
||||||
|
void ShowError(ResultCode error, std::function<void()> finished) const override;
|
||||||
|
void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
|
||||||
|
std::function<void()> finished) const override;
|
||||||
|
void ShowCustomErrorText(ResultCode error, std::string main_text, std::string detail_text,
|
||||||
|
std::function<void()> finished) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Frontend
|
27
src/core/frontend/applets/general_frontend.cpp
Normal file
27
src/core/frontend/applets/general_frontend.cpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// Copyright 2019 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<void()> 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<void()> finished) const {
|
||||||
|
LOG_INFO(Service_AM, "Application requested frontend to display all stored photos.");
|
||||||
|
finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Frontend
|
28
src/core/frontend/applets/general_frontend.h
Normal file
28
src/core/frontend/applets/general_frontend.h
Normal file
|
@ -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 <functional>
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Core::Frontend {
|
||||||
|
|
||||||
|
class PhotoViewerApplet {
|
||||||
|
public:
|
||||||
|
virtual ~PhotoViewerApplet();
|
||||||
|
|
||||||
|
virtual void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const = 0;
|
||||||
|
virtual void ShowAllPhotos(std::function<void()> finished) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DefaultPhotoViewerApplet final : public PhotoViewerApplet {
|
||||||
|
public:
|
||||||
|
~DefaultPhotoViewerApplet() override;
|
||||||
|
|
||||||
|
void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const override;
|
||||||
|
void ShowAllPhotos(std::function<void()> finished) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Frontend
|
|
@ -22,7 +22,6 @@
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/applets/applets.h"
|
||||||
#include "core/hle/service/am/applets/profile_select.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/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/applets/web_browser.h"
|
||||||
#include "core/hle/service/am/idle.h"
|
#include "core/hle/service/am/idle.h"
|
||||||
#include "core/hle/service/am/omm.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_NO_MESSAGES{ErrorModule::AM, 0x3};
|
||||||
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
|
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;
|
constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
|
||||||
|
|
||||||
struct LaunchParameters {
|
struct LaunchParameters {
|
||||||
|
@ -886,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
|
||||||
|
|
||||||
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
|
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
|
||||||
|
|
||||||
static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
|
|
||||||
switch (id) {
|
|
||||||
case AppletId::ProfileSelect:
|
|
||||||
return std::make_shared<Applets::ProfileSelect>();
|
|
||||||
case AppletId::SoftwareKeyboard:
|
|
||||||
return std::make_shared<Applets::SoftwareKeyboard>();
|
|
||||||
case AppletId::LibAppletOff:
|
|
||||||
return std::make_shared<Applets::WebBrowser>();
|
|
||||||
default:
|
|
||||||
LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!",
|
|
||||||
static_cast<u32>(id));
|
|
||||||
return std::make_shared<Applets::StubApplet>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
|
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto applet_id = rp.PopRaw<AppletId>();
|
const auto applet_id = rp.PopRaw<Applets::AppletId>();
|
||||||
const auto applet_mode = rp.PopRaw<u32>();
|
const auto applet_mode = rp.PopRaw<u32>();
|
||||||
|
|
||||||
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
|
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
|
||||||
static_cast<u32>(applet_id), applet_mode);
|
static_cast<u32>(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) {
|
if (applet == nullptr) {
|
||||||
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
|
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
|
||||||
|
|
|
@ -5,11 +5,21 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/core.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/readable_event.h"
|
||||||
#include "core/hle/kernel/server_session.h"
|
#include "core/hle/kernel/server_session.h"
|
||||||
#include "core/hle/kernel/writable_event.h"
|
#include "core/hle/kernel/writable_event.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/applets.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 {
|
namespace Service::AM::Applets {
|
||||||
|
|
||||||
|
@ -111,4 +121,76 @@ void Applet::Initialize() {
|
||||||
initialized = true;
|
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<Core::Frontend::DefaultErrorApplet>();
|
||||||
|
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
|
||||||
|
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
|
||||||
|
frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
|
||||||
|
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::SetDefaultAppletsIfMissing() {
|
||||||
|
if (frontend.error == nullptr) {
|
||||||
|
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.photo_viewer == nullptr) {
|
||||||
|
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.profile_select == nullptr) {
|
||||||
|
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.software_keyboard == nullptr) {
|
||||||
|
frontend.software_keyboard =
|
||||||
|
std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontend.web_browser == nullptr) {
|
||||||
|
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppletManager::ClearAll() {
|
||||||
|
frontend = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
|
||||||
|
switch (id) {
|
||||||
|
case AppletId::Error:
|
||||||
|
return std::make_shared<Error>(*frontend.error);
|
||||||
|
case AppletId::ProfileSelect:
|
||||||
|
return std::make_shared<ProfileSelect>(*frontend.profile_select);
|
||||||
|
case AppletId::SoftwareKeyboard:
|
||||||
|
return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard);
|
||||||
|
case AppletId::PhotoViewer:
|
||||||
|
return std::make_shared<PhotoViewer>(*frontend.photo_viewer);
|
||||||
|
case AppletId::LibAppletOff:
|
||||||
|
return std::make_shared<WebBrowser>(*frontend.web_browser);
|
||||||
|
default:
|
||||||
|
UNIMPLEMENTED_MSG(
|
||||||
|
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
|
||||||
|
static_cast<u8>(id));
|
||||||
|
return std::make_shared<StubApplet>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Applets
|
||||||
|
|
|
@ -12,12 +12,43 @@
|
||||||
|
|
||||||
union ResultCode;
|
union ResultCode;
|
||||||
|
|
||||||
|
namespace Core::Frontend {
|
||||||
|
class ErrorApplet;
|
||||||
|
class PhotoViewerApplet;
|
||||||
|
class ProfileSelectApplet;
|
||||||
|
class SoftwareKeyboardApplet;
|
||||||
|
class WebBrowserApplet;
|
||||||
|
} // namespace Core::Frontend
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
class IStorage;
|
class IStorage;
|
||||||
|
|
||||||
namespace Applets {
|
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 {
|
class AppletDataBroker final {
|
||||||
public:
|
public:
|
||||||
AppletDataBroker();
|
AppletDataBroker();
|
||||||
|
@ -105,5 +136,29 @@ protected:
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AppletFrontendSet {
|
||||||
|
std::unique_ptr<Core::Frontend::ErrorApplet> error;
|
||||||
|
std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer;
|
||||||
|
std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select;
|
||||||
|
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
|
||||||
|
std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AppletManager {
|
||||||
|
public:
|
||||||
|
AppletManager();
|
||||||
|
~AppletManager();
|
||||||
|
|
||||||
|
void SetAppletFrontendSet(AppletFrontendSet set);
|
||||||
|
void SetDefaultAppletFrontendSet();
|
||||||
|
void SetDefaultAppletsIfMissing();
|
||||||
|
void ClearAll();
|
||||||
|
|
||||||
|
std::shared_ptr<Applet> GetApplet(AppletId id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppletFrontendSet frontend;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Applets
|
} // namespace Applets
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
182
src/core/hle/service/am/applets/error.cpp
Normal file
182
src/core/hle/service/am/applets/error.cpp
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
// Copyright 2019 yuzu emulator team
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstring>
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#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<char, 8> language_code;
|
||||||
|
std::array<char, 0x800> main_text;
|
||||||
|
std::array<char, 0x800> detail_text;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size.");
|
||||||
|
|
||||||
|
struct ApplicationErrorArg {
|
||||||
|
u8 mode;
|
||||||
|
bool jump;
|
||||||
|
INSERT_PADDING_BYTES(6);
|
||||||
|
u32 error_code;
|
||||||
|
std::array<char, 8> language_code;
|
||||||
|
std::array<char, 0x800> main_text;
|
||||||
|
std::array<char, 0x800> detail_text;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size.");
|
||||||
|
|
||||||
|
union Error::ErrorArguments {
|
||||||
|
ShowError error;
|
||||||
|
ShowErrorRecord error_record;
|
||||||
|
SystemErrorArg system_error;
|
||||||
|
ApplicationErrorArg application_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
template <typename T>
|
||||||
|
void CopyArgumentData(const std::vector<u8>& 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<ErrorModule>(module), static_cast<u32>(description)};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {}
|
||||||
|
|
||||||
|
Error::~Error() = default;
|
||||||
|
|
||||||
|
void Error::Initialize() {
|
||||||
|
Applet::Initialize();
|
||||||
|
args = std::make_unique<ErrorArguments>();
|
||||||
|
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));
|
||||||
|
break;
|
||||||
|
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<u8>(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<u8>(mode));
|
||||||
|
DisplayCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Error::DisplayCompleted() {
|
||||||
|
complete = true;
|
||||||
|
broker.PushNormalDataFromApplet(IStorage{{}});
|
||||||
|
broker.SignalStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::AM::Applets
|
47
src/core/hle/service/am/applets/error.h
Normal file
47
src/core/hle/service/am/applets/error.h
Normal file
|
@ -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 {
|
||||||
|
|
||||||
|
enum class ErrorAppletMode : u8 {
|
||||||
|
ShowError = 0,
|
||||||
|
ShowSystemError = 1,
|
||||||
|
ShowApplicationError = 2,
|
||||||
|
ShowEula = 3,
|
||||||
|
ShowErrorPctl = 4,
|
||||||
|
ShowErrorRecord = 5,
|
||||||
|
ShowUpdateEula = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Error final : public Applet {
|
||||||
|
public:
|
||||||
|
explicit 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:
|
||||||
|
union ErrorArguments;
|
||||||
|
|
||||||
|
const Core::Frontend::ErrorApplet& frontend;
|
||||||
|
ResultCode error_code = RESULT_SUCCESS;
|
||||||
|
ErrorAppletMode mode = ErrorAppletMode::ShowError;
|
||||||
|
std::unique_ptr<ErrorArguments> args;
|
||||||
|
|
||||||
|
bool complete = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::AM::Applets
|
|
@ -4,11 +4,15 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging/log.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/result.h"
|
||||||
#include "core/hle/service/am/am.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 {
|
namespace Service::AM::Applets {
|
||||||
|
|
||||||
|
@ -30,6 +34,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<PhotoViewerAppletMode>(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<u8>(mode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoViewer::ViewFinished() {
|
||||||
|
broker.PushNormalDataFromApplet(IStorage{{}});
|
||||||
|
broker.SignalStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
StubApplet::StubApplet() = default;
|
StubApplet::StubApplet() = default;
|
||||||
|
|
||||||
StubApplet::~StubApplet() = default;
|
StubApplet::~StubApplet() = default;
|
||||||
|
@ -67,4 +120,5 @@ void StubApplet::Execute() {
|
||||||
broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
|
broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
|
||||||
broker.SignalStateChanged();
|
broker.SignalStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM::Applets
|
} // namespace Service::AM::Applets
|
48
src/core/hle/service/am/applets/general_backend.h
Normal file
48
src/core/hle/service/am/applets/general_backend.h
Normal file
|
@ -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:
|
||||||
|
explicit 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 = false;
|
||||||
|
PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
|
@ -15,7 +15,9 @@ namespace Service::AM::Applets {
|
||||||
|
|
||||||
constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
|
constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
|
||||||
|
|
||||||
ProfileSelect::ProfileSelect() = default;
|
ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend)
|
||||||
|
: frontend(frontend) {}
|
||||||
|
|
||||||
ProfileSelect::~ProfileSelect() = default;
|
ProfileSelect::~ProfileSelect() = default;
|
||||||
|
|
||||||
void ProfileSelect::Initialize() {
|
void ProfileSelect::Initialize() {
|
||||||
|
@ -51,8 +53,6 @@ void ProfileSelect::Execute() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& frontend{Core::System::GetInstance().GetProfileSelector()};
|
|
||||||
|
|
||||||
frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
|
frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
|
||||||
|
|
||||||
class ProfileSelect final : public Applet {
|
class ProfileSelect final : public Applet {
|
||||||
public:
|
public:
|
||||||
ProfileSelect();
|
explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend);
|
||||||
~ProfileSelect() override;
|
~ProfileSelect() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
@ -41,6 +41,8 @@ public:
|
||||||
void SelectionComplete(std::optional<Account::UUID> uuid);
|
void SelectionComplete(std::optional<Account::UUID> uuid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const Core::Frontend::ProfileSelectApplet& frontend;
|
||||||
|
|
||||||
UserSelectionConfig config;
|
UserSelectionConfig config;
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
ResultCode status = RESULT_SUCCESS;
|
ResultCode status = RESULT_SUCCESS;
|
||||||
|
|
|
@ -39,7 +39,8 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoftwareKeyboard::SoftwareKeyboard() = default;
|
SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend)
|
||||||
|
: frontend(frontend) {}
|
||||||
|
|
||||||
SoftwareKeyboard::~SoftwareKeyboard() = default;
|
SoftwareKeyboard::~SoftwareKeyboard() = default;
|
||||||
|
|
||||||
|
@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() {
|
||||||
if (status == INTERACTIVE_STATUS_OK) {
|
if (status == INTERACTIVE_STATUS_OK) {
|
||||||
complete = true;
|
complete = true;
|
||||||
} else {
|
} else {
|
||||||
const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
|
|
||||||
|
|
||||||
std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
|
std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
|
||||||
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
|
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
|
||||||
frontend.SendTextCheckDialog(
|
frontend.SendTextCheckDialog(
|
||||||
|
@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
|
|
||||||
|
|
||||||
const auto parameters = ConvertToFrontendParameters(config, initial_text);
|
const auto parameters = ConvertToFrontendParameters(config, initial_text);
|
||||||
|
|
||||||
frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); },
|
frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); },
|
||||||
|
|
|
@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
|
||||||
|
|
||||||
class SoftwareKeyboard final : public Applet {
|
class SoftwareKeyboard final : public Applet {
|
||||||
public:
|
public:
|
||||||
SoftwareKeyboard();
|
explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend);
|
||||||
~SoftwareKeyboard() override;
|
~SoftwareKeyboard() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
@ -68,6 +68,8 @@ public:
|
||||||
void WriteText(std::optional<std::u16string> text);
|
void WriteText(std::optional<std::u16string> text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const Core::Frontend::SoftwareKeyboardApplet& frontend;
|
||||||
|
|
||||||
KeyboardConfig config;
|
KeyboardConfig config;
|
||||||
std::u16string initial_text;
|
std::u16string initial_text;
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
|
|
|
@ -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
|
|
|
@ -95,7 +95,7 @@ static FileSys::VirtualFile GetManualRomFS() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebBrowser::WebBrowser() = default;
|
WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {}
|
||||||
|
|
||||||
WebBrowser::~WebBrowser() = default;
|
WebBrowser::~WebBrowser() = default;
|
||||||
|
|
||||||
|
@ -152,8 +152,6 @@ void WebBrowser::Execute() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& frontend{Core::System::GetInstance().GetWebBrowser()};
|
|
||||||
|
|
||||||
frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
|
frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Service::AM::Applets {
|
||||||
|
|
||||||
class WebBrowser final : public Applet {
|
class WebBrowser final : public Applet {
|
||||||
public:
|
public:
|
||||||
WebBrowser();
|
WebBrowser(Core::Frontend::WebBrowserApplet& frontend);
|
||||||
~WebBrowser() override;
|
~WebBrowser() override;
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
|
@ -32,6 +32,8 @@ public:
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Core::Frontend::WebBrowserApplet& frontend;
|
||||||
|
|
||||||
bool complete = false;
|
bool complete = false;
|
||||||
bool unpacked = false;
|
bool unpacked = false;
|
||||||
ResultCode status = RESULT_SUCCESS;
|
ResultCode status = RESULT_SUCCESS;
|
||||||
|
|
|
@ -7,6 +7,8 @@ add_executable(yuzu
|
||||||
Info.plist
|
Info.plist
|
||||||
about_dialog.cpp
|
about_dialog.cpp
|
||||||
about_dialog.h
|
about_dialog.h
|
||||||
|
applets/error.cpp
|
||||||
|
applets/error.h
|
||||||
applets/profile_select.cpp
|
applets/profile_select.cpp
|
||||||
applets/profile_select.h
|
applets/profile_select.h
|
||||||
applets/software_keyboard.cpp
|
applets/software_keyboard.cpp
|
||||||
|
|
59
src/yuzu/applets/error.cpp
Normal file
59
src/yuzu/applets/error.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright 2019 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#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<void()> finished) const {
|
||||||
|
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)")
|
||||||
|
.arg(static_cast<u32>(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<void()> finished) const {
|
||||||
|
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)")
|
||||||
|
.arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("dddd, MMMM d, yyyy"))
|
||||||
|
.arg(QDateTime::fromSecsSinceEpoch(time.count()).toString("h:mm:ss A"))
|
||||||
|
.arg(static_cast<u32>(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<void()> finished) const {
|
||||||
|
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<u32>(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<std::recursive_mutex> lock(HLE::g_hle_lock);
|
||||||
|
callback();
|
||||||
|
}
|
33
src/yuzu/applets/error.h
Normal file
33
src/yuzu/applets/error.h
Normal file
|
@ -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 <QObject>
|
||||||
|
|
||||||
|
#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<void()> finished) const override;
|
||||||
|
void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
|
||||||
|
std::function<void()> finished) const override;
|
||||||
|
void ShowCustomErrorText(ResultCode error, std::string dialog_text, std::string fullscreen_text,
|
||||||
|
std::function<void()> finished) const override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void MainWindowDisplayError(QString error) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MainWindowFinishedError();
|
||||||
|
|
||||||
|
mutable std::function<void()> callback;
|
||||||
|
};
|
|
@ -8,6 +8,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
|
// 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/profile_select.h"
|
||||||
#include "applets/software_keyboard.h"
|
#include "applets/software_keyboard.h"
|
||||||
#include "applets/web_browser.h"
|
#include "applets/web_browser.h"
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
#include "configuration/configure_per_general.h"
|
#include "configuration/configure_per_general.h"
|
||||||
#include "core/file_sys/vfs.h"
|
#include "core/file_sys/vfs.h"
|
||||||
#include "core/file_sys/vfs_real.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/frontend/scope_acquire_window_context.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/hle/service/am/applets/applets.h"
|
#include "core/hle/service/am/applets/applets.h"
|
||||||
|
@ -795,9 +797,13 @@ bool GMainWindow::LoadROM(const QString& filename) {
|
||||||
|
|
||||||
system.SetGPUDebugContext(debug_context);
|
system.SetGPUDebugContext(debug_context);
|
||||||
|
|
||||||
system.SetProfileSelector(std::make_unique<QtProfileSelector>(*this));
|
system.SetAppletFrontendSet({
|
||||||
system.SetSoftwareKeyboard(std::make_unique<QtSoftwareKeyboard>(*this));
|
std::make_unique<QtErrorDisplay>(*this),
|
||||||
system.SetWebBrowser(std::make_unique<QtWebBrowser>(*this));
|
nullptr,
|
||||||
|
std::make_unique<QtProfileSelector>(*this),
|
||||||
|
std::make_unique<QtSoftwareKeyboard>(*this),
|
||||||
|
std::make_unique<QtWebBrowser>(*this),
|
||||||
|
});
|
||||||
|
|
||||||
const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
|
const Core::System::ResultStatus result{system.Load(*render_window, filename.toStdString())};
|
||||||
|
|
||||||
|
@ -1583,6 +1589,11 @@ void GMainWindow::OnLoadComplete() {
|
||||||
loading_screen->OnLoadComplete();
|
loading_screen->OnLoadComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::ErrorDisplayDisplayError(QString body) {
|
||||||
|
QMessageBox::critical(this, tr("Error Display"), body);
|
||||||
|
emit ErrorDisplayFinished();
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::OnMenuReportCompatibility() {
|
void GMainWindow::OnMenuReportCompatibility() {
|
||||||
if (!Settings::values.yuzu_token.empty() && !Settings::values.yuzu_username.empty()) {
|
if (!Settings::values.yuzu_token.empty() && !Settings::values.yuzu_username.empty()) {
|
||||||
CompatDB compatdb{this};
|
CompatDB compatdb{this};
|
||||||
|
|
|
@ -102,6 +102,8 @@ signals:
|
||||||
// Signal that tells widgets to update icons to use the current theme
|
// Signal that tells widgets to update icons to use the current theme
|
||||||
void UpdateThemedIcons();
|
void UpdateThemedIcons();
|
||||||
|
|
||||||
|
void ErrorDisplayFinished();
|
||||||
|
|
||||||
void ProfileSelectorFinishedSelection(std::optional<Service::Account::UUID> uuid);
|
void ProfileSelectorFinishedSelection(std::optional<Service::Account::UUID> uuid);
|
||||||
void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
|
void SoftwareKeyboardFinishedText(std::optional<std::u16string> text);
|
||||||
void SoftwareKeyboardFinishedCheckDialog();
|
void SoftwareKeyboardFinishedCheckDialog();
|
||||||
|
@ -111,6 +113,7 @@ signals:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void OnLoadComplete();
|
void OnLoadComplete();
|
||||||
|
void ErrorDisplayDisplayError(QString body);
|
||||||
void ProfileSelectorSelectProfile();
|
void ProfileSelectorSelectProfile();
|
||||||
void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
|
void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
|
||||||
void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
|
void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
|
||||||
|
|
Loading…
Reference in a new issue