mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 23:49:01 -05:00 
			
		
		
		
	applets: Add Error applet
Responsible for displaying error codes and messages
This commit is contained in:
		
							
								
								
									
										177
									
								
								src/core/hle/service/am/applets/error.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								src/core/hle/service/am/applets/error.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										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 { | ||||
|  | ||||
| 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 | ||||
| @@ -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 | ||||
		Reference in New Issue
	
	Block a user
	 Zach Hilman
					Zach Hilman