// User-facing error handling #include "n64dd.h" #include "z_locale.h" u8 B_801E0F80[0x600]; u8 B_801E1580[0x2800]; u8 B_801E3D80[0x1400]; /** * Converts a number in decimal to a hexadecimal number with the same digits, e.g. 1234 -> 0x1234. * * Will only work on nonnegative numbers. * * @param decNumber Number in decimal to convert, e.g. 1234 * @return s32 Hexadecimal number with the same digits as decNumber, e.g. 0x1234 */ s32 func_801C9B70(s32 decNumber) { s32 currPlaceValue; s32 currExponent = 0; s32 accumulatedHexDigits = 0; s32 remainingDecDigits; // Nothing to do if only one digit. if (decNumber < 10) { return decNumber; } // Find the place value / exponent of the most significant digit in decNumber. for (currPlaceValue = 1; 10 * currPlaceValue <= decNumber; currPlaceValue *= 10) { currExponent++; } remainingDecDigits = decNumber; // Transfer the digits to hex one at a time. while (currExponent--) { // Place the most significant remaining digit at the end of the hex output. accumulatedHexDigits |= remainingDecDigits / currPlaceValue; accumulatedHexDigits *= 0x10; // Shift left one hex digit. remainingDecDigits %= currPlaceValue; // Remove most significant of the remaining digits. currPlaceValue /= 10; } accumulatedHexDigits += remainingDecDigits; // Only one digit left in the remainingDecDigits. return accumulatedHexDigits; } // n64ddError_GetLanguage s32 func_801C9C48(void) { return (gCurrentRegion == 1) ? 0 : 1; } // n64ddError_Memset void func_801C9C74(u8* dest, u8 value, u32 count) { while (count--) { *dest++ = value; } } // n64ddError_GetErrorHeader const char* func_801C9CA4(void) { return gN64DDLocalizedErrorNumberHeaders[func_801C9C48()]; } // n64ddError_WriteNumberJP // Writes a 2-digit number to the char buffer provided // Character indices for numbers in the error code (EUC-JP) void func_801C9CD4(u8* buf, s32 number) { s32 temp_v0 = func_801C9B70(number); u16 character; if (number >= 10) { character = ((temp_v0 >> 4) + 0xA3B0); // '0' } else { character = 0xA1A1; // ' ' } func_801C94F8(buf, character); buf += 2; func_801C94F8(buf, ((temp_v0 & 0xF) + 0xA3B0)); // '0' } // n64ddError_WriteNumberEN // Writes a 2-digit number to the char buffer provided // Character indices for numbers in the error code (ASCII) void func_801C9D54(u8* buf, s32 number) { s32 temp_v0 = func_801C9B70(number); if (number >= 10) { *buf = (temp_v0 >> 4) + '0'; } else { *buf = ' '; } buf++; *buf = (temp_v0 & 0xF) + '0'; } void func_801C9DB8(u8* arg0, s32 errorNum) { u8* errorHeader = (u8*)func_801C9CA4(); //! @bug: both of these functions will write to the pointer target, but errorHeader points to a string literal, //! which is meant to be const. if (gCurrentRegion == 1) { func_801C9CD4(&errorHeader[12], errorNum); } else { func_801C9D54(&errorHeader[13], errorNum); } func_801C9A10(arg0, 192, errorHeader); } u8* func_801C9E28(s32 errorNum) { func_801C9EC0(); if (errorNum == 41) { return (u8*)gN64DDError41Texs[func_801C9C48()]; } // 31,32, 37,38,39,40 if (((errorNum >= 37) && (errorNum < 41)) || (errorNum == 31) || (errorNum == 32)) { return B_801E0F80; } else { func_801C9DB8(B_801E0F80, errorNum); return B_801E0F80; } } // Clear something u8* func_801C9EC0(void) { func_801C9C74(B_801E0F80, 0, 0x600); return B_801E0F80; } // Prints the error message body (?) void func_801C9EF4(u8* arg0, s32 errorNum, s32 lineCount) { s32 i; for (i = 0; i < lineCount; i++, arg0 += 0xA00) { u8* line = (u8*)D_801D2EE0[func_801C9C48()][errorNum][i]; if (1) {} func_801C9A10(arg0, 320, line); } } u8* func_801C9F90(s32 errorNum) { func_801C9FFC(); if (errorNum == 3) { return (u8*)gN64DDPleaseReadManualTexs[func_801C9C48()]; } func_801C9EF4(B_801E1580, errorNum, 4); return B_801E1580; } // Clear something u8* func_801C9FFC(void) { func_801C9C74(B_801E1580, 0, 0x2800); return B_801E1580; } u8* func_801CA030(s32 errorNum) { func_801CA070(); func_801C9EF4(B_801E3D80, errorNum, 2); return B_801E3D80; } // Clear something u8* func_801CA070(void) { func_801C9C74(B_801E3D80, 0, 0x1400); return B_801E3D80; }