diff --git a/nx/include/switch/applets/error.h b/nx/include/switch/applets/error.h index aaa706eb..1b3f3a8c 100644 --- a/nx/include/switch/applets/error.h +++ b/nx/include/switch/applets/error.h @@ -8,74 +8,91 @@ #include "../types.h" #include "../services/applet.h" -/// Error configuration struct (SystemErrorArg) -typedef struct { - u8 custom_text; ///< Whether to show a custom error message. If this is false, a default message will be shown. - u8 unk[7]; - u32 module; ///< Module code. - u32 description; ///< Description code. - u64 languageCode; - char short_description[0x800]; ///< Short description. - char detailed_description[0x800]; ///< Detailed description (displayed when the user clicks, on "Details"). -} ErrorConfig; - typedef struct { u8 unk_x0[0x200]; } ErrorContext; -/** - * @brief Creates an ErrorConfg struct. - * @param c ErrorConfg struct. - * @note Sets the following fields: majorCode = 2000, minorCode = 0, customText = false, shortDescription = "", detailedDescription = "". - * @warning This applet creates an error report that is logged in the system. Proceed at your own risk! - */ -void errorCreate(ErrorConfig* c); +/// Common header for the start of the arg storage. +typedef struct { + u8 type; + u8 unk_x1; + u8 unk_x2[3]; + u8 contextFlag; + u8 resultFlag; ///< \ref ErrorCommonArg: When clear, errorCode is used, otherwise the applet generates the error-code from res. + u8 unk_x7; +} ErrorCommonHeader; + +/// Error arg data for non-{System/Application}. +typedef struct { + ErrorCommonHeader hdr; + u64 errorCode; + Result res; +} ErrorCommonArg; + +/// SystemErrorArg +typedef struct { + ErrorCommonHeader hdr; + u64 errorCode; + u64 languageCode; + char dialogMessage[0x800]; ///< UTF-8 Dialog message. + char fullscreenMessage[0x800]; ///< UTF-8 Fullscreen message (displayed when the user clicks on "Details"). +} ErrorSystemArg; + +typedef struct { + ErrorSystemArg arg; + ErrorContext ctx; +} ErrorSystemConfig; /** - * @brief Closes an ErrorConfig struct. - * @param c ErrorConfig struct. + * @brief Creates an ErrorSystemConfig struct. + * @param c ErrorSystemConfig struct. + * @param dialog_message UTF-8 dialog message. + * @param fullscreen_message UTF-8 fullscreen message, displayed when the user clicks on "Details". + * @note Sets the following fields: type=1 and {strings}. The rest are cleared. + * @note On pre-5.0.0 this will initialize languageCode by using: setInitialize(), setMakeLanguageCode(SetLanguage_ENUS, ...), and setExit(). This is needed since an empty languageCode wasn't supported until [5.0.0+] (which would also use SetLanguage_ENUS). + * @warning This applet creates an error report that is logged in the system. Proceed at your own risk! */ -void errorClose(ErrorConfig* c); +Result errorSystemCreate(ErrorSystemConfig* c, const char* dialog_message, const char* fullscreen_message); + +/** + * @brief Closes an ErrorSystemConfig struct. + * @param c ErrorSystemConfig struct. + */ +void errorSystemClose(ErrorSystemConfig* c); /** * @brief Launches with the specified config. - * @param c ErrorConfig struct. + * @param c ErrorSystemConfig struct. */ -Result errorShow(ErrorConfig* c); +Result errorSystemShow(ErrorSystemConfig* c); /** - * @brief Sets the error module. - * @param c ErrorConfig struct. - * @param code Code. + * @brief Sets the error code. + * @param c ErrorSystemConfig struct. + * @param low The module portion of the error, normally this should be set to module + 2000. + * @param desc The error description. */ -void errorConfigSetModule(ErrorConfig* c, u32 code); +void errorSystemSetCode(ErrorSystemConfig* c, u32 low, u32 desc); /** - * @brief Sets the error description. - * @param c ErrorConfig struct. - * @param code Code. + * @brief Sets the error code, using the input Result. Wrapper for \ref errorSystemSetCode. + * @param c ErrorSystemConfig struct. + * @param res The Result to set. */ -void errorConfigSetDescription(ErrorConfig* c, u32 code); +void errorSystemSetResult(ErrorSystemConfig* c, Result res); /** - * @brief Sets whether to use a custom error message. - * @param c ErrorConfig struct. - * @param custom_text Whether to use a custom message. + * @brief Sets the LanguageCode. + * @param c ErrorSystemConfig struct. + * @param LanguageCode LanguageCode, see set.h. */ -void errorConfigSetCustomText(ErrorConfig* c, bool custom_text); +void errorSystemSetLanguageCode(ErrorSystemConfig* c, u64 LanguageCode); /** - * @brief Sets the short description. - * @param c ErrorConfig struct. - * @param str Description. + * @brief Sets the ErrorContext. + * @note Only available on [4.0.0+], on older versions \ref errorSystemShow will skip pushing the storage for this. + * @param c ErrorSystemConfig struct. + * @param ctx ErrorContext, NULL to clear it. */ -void errorConfigSetShortDescription(ErrorConfig* c, const char* str); +void errorSystemSetContext(ErrorSystemConfig* c, ErrorContext* ctx); -/** - * @brief Sets the detailed description. - * @param c ErrorConfig struct. - * @param str Description. - * - * This gets displayed when the user clicks on "Details". - */ -void errorConfigSetDetailedDescription(ErrorConfig* c, const char* str); diff --git a/nx/source/applets/error.c b/nx/source/applets/error.c index f72c48e7..1336134d 100644 --- a/nx/source/applets/error.c +++ b/nx/source/applets/error.c @@ -1,10 +1,11 @@ -#include #include #include "types.h" #include "result.h" #include "services/applet.h" +#include "services/set.h" #include "applets/libapplet.h" #include "applets/error.h" +#include "runtime/hosversion.h" static Result _errorAppletCreate(AppletHolder* holder, const void* indata, size_t insize, const void* indata2, size_t insize2) { Result rc=0; @@ -64,36 +65,58 @@ static Result _errorShow(const void* indata, size_t insize, const void* indata2, return rc; } -void errorCreate(ErrorConfig* c) { - memset(c, 0, sizeof(ErrorConfig)); - c->custom_text = false; - c->module = 2000; +static Result _errorShowContext(const void* indata, size_t insize, ErrorContext* ctx) { + void* ctx_ptr = NULL; + size_t ctx_size = 0; + if (hosversionAtLeast(4,0,0)) { + ctx_ptr = ctx; + if (ctx_ptr) ctx_size = sizeof(ErrorContext); + } + + return _errorShow(indata, insize, ctx_ptr, ctx_size); } -void errorClose(ErrorConfig* c) { - memset(c, 0, sizeof(ErrorConfig)); +Result errorSystemCreate(ErrorSystemConfig* c, const char* dialog_message, const char* fullscreen_message) { + Result rc=0; + + memset(c, 0, sizeof(ErrorSystemConfig)); + c->arg.hdr.type = 1; + + strncpy(c->arg.dialogMessage, dialog_message, sizeof(c->arg.dialogMessage)-1); + strncpy(c->arg.fullscreenMessage, fullscreen_message, sizeof(c->arg.fullscreenMessage)-1); + + if (hosversionBefore(5,0,0)) { + rc = setInitialize(); + if (R_SUCCEEDED(rc)) rc = setMakeLanguageCode(SetLanguage_ENUS, &c->arg.languageCode); + setExit(); + } + + return rc; } -Result errorShow(ErrorConfig* c) { - return _errorShow(c, sizeof(ErrorConfig), NULL, 0); +void errorSystemClose(ErrorSystemConfig* c) { + memset(c, 0, sizeof(ErrorSystemConfig)); } -void errorConfigSetModule(ErrorConfig* c, u32 code) { - c->module = code; +Result errorSystemShow(ErrorSystemConfig* c) { + return _errorShowContext(&c->arg, sizeof(c->arg), c->arg.hdr.contextFlag!=0 ? &c->ctx : NULL); } -void errorConfigSetDescription(ErrorConfig* c, u32 code) { - c->description = code; +void errorSystemSetCode(ErrorSystemConfig* c, u32 low, u32 desc) { + c->arg.errorCode = (u64)low | ((u64)desc<<32); } -void errorConfigSetCustomText(ErrorConfig* c, bool custom_text) { - c->custom_text = custom_text; +void errorSystemSetResult(ErrorSystemConfig* c, Result res) { + errorSystemSetCode(c, 2000 + R_MODULE(res), R_DESCRIPTION(res)); } -void errorConfigSetShortDescription(ErrorConfig* c, const char* str) { - strncpy(c->short_description, str, sizeof(c->short_description) - 1); +void errorSystemSetLanguageCode(ErrorSystemConfig* c, u64 LanguageCode) { + c->arg.languageCode = LanguageCode; } -void errorConfigSetDetailedDescription(ErrorConfig* c, const char* str) { - strncpy(c->detailed_description, str, sizeof(c->detailed_description) - 1); +void errorSystemSetContext(ErrorSystemConfig* c, ErrorContext* ctx) { + c->arg.hdr.contextFlag = ctx!=0; + memset(&c->ctx, 0, sizeof(ErrorContext)); + if (ctx) memcpy(&c->ctx, ctx, sizeof(ErrorContext)); } +