From dfb9fa0144ca79e596f6f2b1bc960b1a44745aa6 Mon Sep 17 00:00:00 2001 From: Liam Date: Sun, 31 Dec 2023 09:40:32 -0500 Subject: am: re-namespace frontend applets to frontend directory --- src/core/hle/service/am/frontend/applet_error.cpp | 223 ++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 src/core/hle/service/am/frontend/applet_error.cpp (limited to 'src/core/hle/service/am/frontend/applet_error.cpp') diff --git a/src/core/hle/service/am/frontend/applet_error.cpp b/src/core/hle/service/am/frontend/applet_error.cpp new file mode 100644 index 000000000..48be77da2 --- /dev/null +++ b/src/core/hle/service/am/frontend/applet_error.cpp @@ -0,0 +1,223 @@ +// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include "common/assert.h" +#include "common/logging/log.h" +#include "common/string_util.h" +#include "core/core.h" +#include "core/frontend/applets/error.h" +#include "core/hle/service/am/am.h" +#include "core/hle/service/am/frontend/applet_error.h" +#include "core/hle/service/am/storage.h" +#include "core/reporter.h" + +namespace Service::AM::Frontend { + +struct ErrorCode { + u32 error_category{}; + u32 error_number{}; + + static constexpr ErrorCode FromU64(u64 error_code) { + return { + .error_category{static_cast(error_code >> 32)}, + .error_number{static_cast(error_code & 0xFFFFFFFF)}, + }; + } + + static constexpr ErrorCode FromResult(Result result) { + return { + .error_category{2000 + static_cast(result.GetModule())}, + .error_number{result.GetDescription()}, + }; + } + + constexpr Result ToResult() const { + return Result{static_cast(error_category - 2000), error_number}; + } +}; +static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size."); + +#pragma pack(push, 4) +struct ShowError { + u8 mode; + bool jump; + INSERT_PADDING_BYTES_NOINIT(4); + bool use_64bit_error_code; + INSERT_PADDING_BYTES_NOINIT(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_NOINIT(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_NOINIT(6); + u64 error_code_64; + std::array language_code; + std::array main_text; + std::array detail_text; +}; +static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size."); + +struct ApplicationErrorArg { + u8 mode; + bool jump; + INSERT_PADDING_BYTES_NOINIT(6); + u32 error_code; + std::array language_code; + std::array main_text; + std::array detail_text; +}; +static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size."); + +union Error::ErrorArguments { + ShowError error; + ShowErrorRecord error_record; + SystemErrorArg system_error; + ApplicationErrorArg application_error; + std::array raw{}; +}; + +namespace { +template +void CopyArgumentData(const std::vector& data, T& variable) { + ASSERT(data.size() >= sizeof(T)); + std::memcpy(&variable, data.data(), sizeof(T)); +} + +Result Decode64BitError(u64 error) { + return ErrorCode::FromU64(error).ToResult(); +} + +} // Anonymous namespace + +Error::Error(Core::System& system_, LibraryAppletMode applet_mode_, + const Core::Frontend::ErrorApplet& frontend_) + : FrontendApplet{system_, applet_mode_}, frontend{frontend_}, system{system_} {} + +Error::~Error() = default; + +void Error::Initialize() { + FrontendApplet::Initialize(); + args = std::make_unique(); + complete = false; + + const auto storage = broker.PopNormalDataToApplet(); + ASSERT(storage != nullptr); + const auto data = storage->GetData(); + + ASSERT(!data.empty()); + std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode)); + + switch (mode) { + case ErrorAppletMode::ShowError: + CopyArgumentData(data, args->error); + if (args->error.use_64bit_error_code) { + error_code = Decode64BitError(args->error.error_code_64); + } else { + error_code = Result(args->error.error_code_32); + } + break; + case ErrorAppletMode::ShowSystemError: + CopyArgumentData(data, args->system_error); + error_code = Result(Decode64BitError(args->system_error.error_code_64)); + break; + case ErrorAppletMode::ShowApplicationError: + CopyArgumentData(data, args->application_error); + error_code = Result(args->application_error.error_code); + break; + case ErrorAppletMode::ShowErrorPctl: + CopyArgumentData(data, args->error_record); + error_code = Decode64BitError(args->error_record.error_code_64); + 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}!", mode); + break; + } +} + +bool Error::TransactionComplete() const { + return complete; +} + +Result Error::GetStatus() const { + return ResultSuccess; +} + +void Error::ExecuteInteractive() { + ASSERT_MSG(false, "Unexpected interactive applet data!"); +} + +void Error::Execute() { + if (complete) { + return; + } + + const auto callback = [this] { DisplayCompleted(); }; + const auto title_id = system.GetApplicationProcessProgramID(); + const auto& reporter{system.GetReporter()}; + + switch (mode) { + case ErrorAppletMode::ShowError: + reporter.SaveErrorReport(title_id, error_code); + frontend.ShowError(error_code, callback); + break; + case ErrorAppletMode::ShowSystemError: + case ErrorAppletMode::ShowApplicationError: { + const auto is_system = mode == ErrorAppletMode::ShowSystemError; + const auto& main_text = + is_system ? args->system_error.main_text : args->application_error.main_text; + const auto& detail_text = + is_system ? args->system_error.detail_text : args->application_error.detail_text; + + const auto main_text_string = + Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()); + const auto detail_text_string = + Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()); + + reporter.SaveErrorReport(title_id, error_code, main_text_string, detail_text_string); + frontend.ShowCustomErrorText(error_code, main_text_string, detail_text_string, callback); + break; + } + case ErrorAppletMode::ShowErrorPctl: + case ErrorAppletMode::ShowErrorRecord: + reporter.SaveErrorReport(title_id, error_code, + fmt::format("{:016X}", args->error_record.posix_time)); + frontend.ShowErrorWithTimestamp( + error_code, std::chrono::seconds{args->error_record.posix_time}, callback); + break; + default: + UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", mode); + DisplayCompleted(); + } +} + +void Error::DisplayCompleted() { + complete = true; + broker.PushNormalDataFromApplet(std::make_shared(system, std::vector{})); + broker.SignalStateChanged(); +} + +Result Error::RequestExit() { + frontend.Close(); + R_SUCCEED(); +} + +} // namespace Service::AM::Frontend -- cgit v1.2.3