Merge pull request #2228 from DarkLordZach/applet-manager-p1
applets: Add AppletManager and implement PhotoViewer and Error applets
This commit is contained in:
		@@ -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<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) {
 | 
			
		||||
    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>();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
 | 
			
		||||
              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) {
 | 
			
		||||
        LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,21 @@
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#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<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
 | 
			
		||||
 
 | 
			
		||||
@@ -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<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 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 "common/assert.h"
 | 
			
		||||
#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 +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;
 | 
			
		||||
@@ -67,4 +120,5 @@ void StubApplet::Execute() {
 | 
			
		||||
    broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
 | 
			
		||||
    broker.SignalStateChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // 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};
 | 
			
		||||
 | 
			
		||||
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<Account::UUID> uuid) { SelectionComplete(uuid); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
 | 
			
		||||
 | 
			
		||||
class ProfileSelect final : public Applet {
 | 
			
		||||
public:
 | 
			
		||||
    ProfileSelect();
 | 
			
		||||
    explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend);
 | 
			
		||||
    ~ProfileSelect() override;
 | 
			
		||||
 | 
			
		||||
    void Initialize() override;
 | 
			
		||||
@@ -41,6 +41,8 @@ public:
 | 
			
		||||
    void SelectionComplete(std::optional<Account::UUID> uuid);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const Core::Frontend::ProfileSelectApplet& frontend;
 | 
			
		||||
 | 
			
		||||
    UserSelectionConfig config;
 | 
			
		||||
    bool complete = false;
 | 
			
		||||
    ResultCode status = RESULT_SUCCESS;
 | 
			
		||||
 
 | 
			
		||||
@@ -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<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> 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<std::u16string> text) { WriteText(text); },
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
 | 
			
		||||
 | 
			
		||||
class SoftwareKeyboard final : public Applet {
 | 
			
		||||
public:
 | 
			
		||||
    SoftwareKeyboard();
 | 
			
		||||
    explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend);
 | 
			
		||||
    ~SoftwareKeyboard() override;
 | 
			
		||||
 | 
			
		||||
    void Initialize() override;
 | 
			
		||||
@@ -68,6 +68,8 @@ public:
 | 
			
		||||
    void WriteText(std::optional<std::u16string> text);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    const Core::Frontend::SoftwareKeyboardApplet& frontend;
 | 
			
		||||
 | 
			
		||||
    KeyboardConfig config;
 | 
			
		||||
    std::u16string initial_text;
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WebBrowser::WebBrowser() = default;
 | 
			
		||||
WebBrowser::WebBrowser(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(); });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ namespace Service::AM::Applets {
 | 
			
		||||
 | 
			
		||||
class WebBrowser final : public Applet {
 | 
			
		||||
public:
 | 
			
		||||
    WebBrowser();
 | 
			
		||||
    WebBrowser(Core::Frontend::WebBrowserApplet& frontend);
 | 
			
		||||
    ~WebBrowser() override;
 | 
			
		||||
 | 
			
		||||
    void Initialize() override;
 | 
			
		||||
@@ -32,6 +32,8 @@ public:
 | 
			
		||||
    void Finalize();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Core::Frontend::WebBrowserApplet& frontend;
 | 
			
		||||
 | 
			
		||||
    bool complete = false;
 | 
			
		||||
    bool unpacked = false;
 | 
			
		||||
    ResultCode status = RESULT_SUCCESS;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user