diff options
| author | Zach Hilman <zachhilman@gmail.com> | 2019-03-11 19:36:36 -0400 | 
|---|---|---|
| committer | Zach Hilman <zachhilman@gmail.com> | 2019-04-17 11:35:24 -0400 | 
| commit | de3cfb1d37462a4843b8cd4e27ac400e1d479748 (patch) | |
| tree | e880724ae0657a34c601b83e5323d4ba865a5496 | |
| parent | d273bec68fd867f047944ab9d28ac5c5c6617571 (diff) | |
applets: Add Error applet
Responsible for displaying error codes and messages
| -rw-r--r-- | src/core/hle/service/am/applets/error.cpp | 177 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/error.h | 47 | ||||
| -rw-r--r-- | src/core/hle/service/am/applets/stub_applet.h | 24 | 
3 files changed, 224 insertions, 24 deletions
| 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<char, 8> language_code; +    std::array<char, 0x800> main_text; +    std::array<char, 0x800> 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<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 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)}; +} + +} // 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)); +    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 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<ErrorArguments> 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 | 
