#include #include #include "debug.inc.c" #include #if DVDL u8 sDisplayListState = OK; static u32 variable_to_u64(variableWatchAttributes*); static void round_up_float(u32*, u8); static void u64_to_string(variableWatchAttributes*, u32, u8); static u32 _strlen(const char*); static void _memcpy(char*, const char*, u32); void display_dvdl(void) { u32 variable; u32 i, vNameLen; u32 arraySize = sizeof(gMainVariableWatchList) / sizeof(variableWatchAttributes); s32 text_y_possition = TEXT_Y_POSSITION; u8 base; char *vName, *cBuffer; load_debug_font(); for (i = 0; i < arraySize; i++) { variableWatchAttributes* currentAttribute = &gMainVariableWatchList[i]; currentAttribute->characterBuffer = currentAttribute->buffer; cBuffer = currentAttribute->characterBuffer; vName = currentAttribute->variableName; variable = variable_to_u64(currentAttribute); base = 0; if (currentAttribute->variableFlag & (DISPLAY_FLOAT_AS_TYPE | DISPLAY_FLOAT_WITH_ROUNDING)) { if (currentAttribute->variableFlag & DISPLAY_FLOAT_NUMBER) { sDisplayListState = BAD; } else if (currentAttribute->variableFlag & DISPLAY_FLOAT_WITH_ROUNDING) { round_up_float(&variable, currentAttribute->variableSize); } } switch (currentAttribute->variableFlag & 0x8F) { case DISPLAY_FLOAT_NUMBER: sprintf(cBuffer, "%.3f", *(f32*) &variable); break; case DISPLAY_HEXIDECIMAL_NUMBER: base = HEXIDECIMAL; break; case DISPLAY_DECIMAL_NUMBER: base = DECIMAL; break; case DISPLAY_OCTAL_NUMBER: base = OCTAL; break; case DISPLAY_BINARY_NUMBER: base = BINARY; break; default: sDisplayListState = BAD; } if (base) { u64_to_string(currentAttribute, variable, base); } if (sDisplayListState == BAD) { cBuffer = "NaN"; } sDisplayListState = OK; vNameLen = _strlen(vName); debug_print_str2(TEXT_X_POSSITION, text_y_possition, vName); debug_print_str2(TEXT_X_POSSITION + (vNameLen * 0x8), text_y_possition, cBuffer); text_y_possition += 0x8; } gSPDisplayList(gDisplayListHead++, D_0D007EB8); gSPDisplayList(gDisplayListHead++, D_020076E0); func_80093C98(1); } static u32 variable_to_u64(variableWatchAttributes* attribute) { u32 variable; switch (attribute->variableSize) { case sizeof(u8): variable = *((u8*) attribute->variablePointer); break; case sizeof(u16): variable = *((u16*) attribute->variablePointer); break; case sizeof(u32): case sizeof(u64): variable = *((u32*) attribute->variablePointer); // no floating point rounding break; default: sDisplayListState = BAD; } return variable; } static void round_up_float(u32* variable, u8 variableSize) { switch (variableSize) { case sizeof(u64): case sizeof(u32): *variable = (u32) (*(f32*) &*variable); break; default: sDisplayListState = BAD; } } static void u64_to_string(variableWatchAttributes* attribute, u32 variable, u8 base) { s32 signedVariable; u32 stringDifference, indexesToFillAVariable, stringLengthWithZero; u32 indexesToFillAByte, upperIndex, remainder; u32 stringLength, lowerIndex, i; u8 variableSize; char* bufferedString; char swapRegister; if (sDisplayListState == BAD) { return; } bufferedString = attribute->characterBuffer; variableSize = attribute->variableSize; // converts a minus number into it's unsigned equivalent for proper string conversion if (attribute->variableFlag & DISPLAY_SIGNED_NUMBER) { switch (variableSize) { case sizeof(u8): signedVariable = (s8) variable; if (signedVariable < 0) { signedVariable = -signedVariable; variable = (u8) signedVariable; *bufferedString = '-'; bufferedString++; } break; case sizeof(u16): signedVariable = (s16) variable; if (signedVariable < 0) { signedVariable = -signedVariable; variable = (u16) signedVariable; *bufferedString = '-'; bufferedString++; } break; case sizeof(u32): case sizeof(u64): signedVariable = (s32) variable; if (signedVariable < 0) { signedVariable = -signedVariable; variable = (u32) signedVariable; *bufferedString = '-'; bufferedString++; } break; } } stringLength = 0; // convert u64 into a string but it gets put in reverse if (base != HEXIDECIMAL) { do { stringLength++; *bufferedString = variable % base + '0'; bufferedString++; variable /= base; } while (variable != 0); } else { do { stringLength++; remainder = variable % 16; if ((remainder >= 0) && (remainder <= 9)) { *bufferedString = '0' + remainder; } else { *bufferedString = 'A' + (remainder - 10); } bufferedString++; variable /= 16; } while (variable != 0); } bufferedString -= stringLength; upperIndex = stringLength - 1; // flip string 4321 --> 1234 for (lowerIndex = 0; lowerIndex < stringLength >> 1; lowerIndex++) { swapRegister = bufferedString[lowerIndex]; bufferedString[lowerIndex] = bufferedString[upperIndex]; bufferedString[upperIndex] = swapRegister; upperIndex--; } switch (base) { case BINARY: indexesToFillAByte = 8; break; case OCTAL: indexesToFillAByte = 3; break; case DECIMAL: bufferedString[stringLength] = '\0'; return; case HEXIDECIMAL: indexesToFillAByte = 2; break; } stringLengthWithZero = stringLength - 1; indexesToFillAVariable = indexesToFillAByte * variableSize; stringDifference = indexesToFillAVariable - stringLengthWithZero; // makes space and fills in extra space. u32 FE -> 000000FE for (i = stringLength; i > 0; i--) { bufferedString[stringDifference + i - 2] = bufferedString[i - 1]; } for (i = 0; i < stringDifference - 1; i++) { bufferedString[i] = '0'; } bufferedString[indexesToFillAVariable] = '\0'; } static u32 _strlen(const char* str) { u32 len; len = 0; for (; *str != '\0'; str++) { len++; } return len; } // unused but may be useful static void _memcpy(char* destStr, const char* copyStr, u32 copySize) { u32 i; for (i = 0; i < copySize; i++) { *destStr = *copyStr; destStr++; copyStr++; } } #endif