]> Chaos Git - corbenik/ctrulib.git/commitdiff
Improve err:f documentation and add wrappers to construct errors automatically
authorchaoskagami <chaos.kagami@gmail.com>
Fri, 15 Jul 2016 23:39:38 +0000 (19:39 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Fri, 15 Jul 2016 23:39:38 +0000 (19:39 -0400)
libctru/include/3ds/errf.h
libctru/source/errf.c

index d79de3462690ec3c0cf4a9bf2b59c1917f7ad563..70123a9981d7f7fa223ed6823333ff40254df788 100644 (file)
@@ -14,10 +14,12 @@ typedef struct {
 
 /// Types of errors that can be thrown by err:f.
 typedef enum {
-       ERRF_ERRTYPE_GENERIC    = 0, ///< For generic errors. Shows miscellaneous info.
-       ERRF_ERRTYPE_EXCEPTION  = 3, ///< For exceptions, or more specifically 'crashes'. union data should be exception_data.
-       ERRF_ERRTYPE_FAILURE    = 4, ///< For general failure. Shows a message. union data should have a string set in failure_mesg
-       ERRF_ERRTYPE_LOGGED     = 5  ///< Outputs logs to NAND in some cases.
+       ERRF_ERRTYPE_GENERIC      = 0, ///< For generic errors. Shows miscellaneous info.
+       ERRF_ERRTYPE_MEM_CORRUPT  = 1, ///< Same output as generic, but informs the user that "the System Memory has been damaged".
+       ERRF_ERRTYPE_CARD_REMOVED = 2, ///< Displays the "The Game Card was removed." message.
+       ERRF_ERRTYPE_EXCEPTION    = 3, ///< For exceptions, or more specifically 'crashes'. union data should be exception_data.
+       ERRF_ERRTYPE_FAILURE      = 4, ///< For general failure. Shows a message. union data should have a string set in failure_mesg
+       ERRF_ERRTYPE_LOGGED       = 5  ///< Outputs logs to NAND in some cases.
 } ERRF_ErrType;
 
 /// Types of 'Exceptions' thrown for ERRF_ERRTYPE_EXCEPTION
@@ -59,10 +61,10 @@ typedef struct {
        } data;                                ///< The different types of data for errors.
 } ERRF_FatalErrInfo;
 
-/// Initializes ERR:f.
+/// Initializes ERR:f. Unless you plan to call ERRF_Throw yourself, do not use this.
 Result errfInit(void);
 
-/// Exits ERR:f.
+/// Exits ERR:f. Unless you plan to call ERRF_Throw yourself, do not use this.
 void errfExit(void);
 
 /**
@@ -72,9 +74,45 @@ void errfExit(void);
 Handle *errfGetSessionHandle(void);
 
 /**
- * @brief Throws a system error and possibly results in ErrDisp triggering. After performing this,
- * the system may panic and need to be rebooted. Extra information will be displayed on the
+ * @brief Throws a system error and possibly results in ErrDisp triggering.
+ * @param[in] error Error to throw.
+ *
+ * After performing this, the system may panic and need to be rebooted. Extra information will be displayed on the
  * top screen with a developer console or the proper patches in a CFW applied.
- * @param error Error to throw.
+ *
+ * The error may not be shown and execution aborted until errfExit(void) is called.
+ *
+ * You may wish to use ERRF_ThrowResult() or ERRF_ThrowResultWithMessage() instead of
+ * constructing the ERRF_FatalErrInfo struct yourself.
  */
-Result ERRF_Throw(ERRF_FatalErrInfo *error);
+Result ERRF_Throw(const ERRF_FatalErrInfo* error);
+
+/**
+ * @brief Throws a system error with the given Result code.
+ * @param[in] failure Result code to throw.
+ *
+ * This calls ERRF_Throw() with error type ERRF_ERRTYPE_GENERIC and fills in the required data.
+ *
+ * This function \em does fill in the address where this function was called from.
+ *
+ * See https://3dbrew.org/wiki/ERR:Throw#Generic for expected top screen output
+ * on development units/patched ErrDisp.
+ */
+Result ERRF_ThrowResult(Result failure);
+
+/**
+ * @brief Throws a system error with the given Result code and message.
+ * @param[in] failure Result code to throw.
+ * @param[in] message The message to display.
+ *
+ * This calls ERRF_Throw() with error type ERRF_ERRTYPE_FAILURE and fills in the required data.
+ *
+ * This function does \em not fill in the address where this function was called from because it
+ * would not be displayed.
+ *
+ * The message is only displayed on development units/patched ErrDisp.
+ *
+ * See https://3dbrew.org/wiki/ERR:Throw#Result_Failure for expected top screen output
+ * on development units/patched ErrDisp.
+ */
+Result ERRF_ThrowResultWithMessage(Result failure, const char* message);
index a15a7199b64b5221fb1c19d5403b23839e36c0dd..e9ad6b1f2a7d6e6df2755526e9d4467efa16aae0 100644 (file)
@@ -37,11 +37,11 @@ Handle* errfGetSessionHandle(void)
        return &errfHandle;
 }
 
-Result ERRF_Throw(ERRF_FatalErrInfo *error)
+Result ERRF_Throw(const ERRF_FatalErrInfo* error)
 {
        uint32_t *cmdbuf = getThreadCommandBuffer();
 
-       cmdbuf[0] = 0x10800;
+       cmdbuf[0] = IPC_MakeHeader(0x1,32,0); // 0x10800
        memcpy(&cmdbuf[1], error, sizeof(ERRF_FatalErrInfo));
 
        Result ret = 0;
@@ -50,3 +50,59 @@ Result ERRF_Throw(ERRF_FatalErrInfo *error)
 
        return cmdbuf[1];
 }
+
+static inline void getCommonErrorData(ERRF_FatalErrInfo* error, Result failure)
+{
+       error->resCode = failure;
+       svcGetProcessId(&error->procId, 0xFFFF8001);
+}
+
+Result ERRF_ThrowResult(Result failure)
+{
+       ERRF_FatalErrInfo error;
+       Result ret;
+
+       if (R_FAILED(ret = errfInit()))
+               return ret;
+
+       memset(&error, 0, sizeof(error));
+
+       error.type = ERRF_ERRTYPE_GENERIC;
+
+       // pcAddr is not used by ErrDisp for ERRF_ERRTYPE_FAILURE
+       error.pcAddr = (u32)__builtin_extract_return_addr(__builtin_return_address(0));
+       getCommonErrorData(&error, failure);
+
+       ret = ERRF_Throw(&error);
+
+       errfExit();
+
+       return ret;
+}
+
+Result ERRF_ThrowResultWithMessage(Result failure, const char* message)
+{
+       ERRF_FatalErrInfo error;
+       Result ret;
+       size_t msglen;
+
+       if (R_FAILED(ret = errfInit()))
+               return ret;
+
+       memset(&error, 0, sizeof(error));
+
+       error.type = ERRF_ERRTYPE_FAILURE;
+       getCommonErrorData(&error, failure);
+
+       if ((msglen = strlen(message)) > sizeof(error.data.failure_mesg) - 1)
+               msglen = sizeof(error.data.failure_mesg) - 1;
+
+       memcpy(error.data.failure_mesg, message, msglen);
+       error.data.failure_mesg[msglen] = '\0';
+
+       ret = ERRF_Throw(&error);
+
+       errfExit();
+
+       return ret;
+}