diff --git a/source/exceptions.c b/source/exceptions.c index 81c2586..f827ed2 100644 --- a/source/exceptions.c +++ b/source/exceptions.c @@ -188,10 +188,10 @@ void detectAndProcessExceptionDumps(void) drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump); } - char folderPath[36], + char folderPath[12], path[36], - fileName[] = "crash_dump_00010000.dmp"; - + fileName[24]; + sprintf(folderPath, "dumps/arm%u", dumpHeader->processor); findDumpFile(folderPath, fileName); sprintf(path, "%s/%s", folderPath, fileName); diff --git a/source/fmt.c b/source/fmt.c index 288d590..7fdc9ef 100644 --- a/source/fmt.c +++ b/source/fmt.c @@ -1,9 +1,3 @@ -// TuxSH's changes: add support for 64-bit numbers, remove floating-point code -// TODO! fix left-padding handling with > 10 characters. - -#include "fmt.h" -#include "strings.h" - /* File : barebones/ee_printf.c This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code. @@ -37,375 +31,245 @@ This code is based on a file that contains the following: */ -//#include -//#include +/* TuxSH's changes: add support for 64-bit numbers, remove floating-point code + TODO! fix left-padding handling with > 10 characters. */ -#define ZEROPAD (1<<0) /* Pad with zero */ -#define SIGN (1<<1) /* Unsigned/signed long */ -#define PLUS (1<<2) /* Show plus */ -#define SPACE (1<<3) /* Spacer */ -#define LEFT (1<<4) /* Left justified */ -#define HEX_PREP (1<<5) /* 0x */ -#define UPPERCASE (1<<6) /* 'ABCDEF' */ +#include "fmt.h" +#include "strings.h" -#define is_digit(c) ((c) >= '0' && (c) <= '9') +#define ZEROPAD (1<<0) //Pad with zero +#define SIGN (1<<1) //Unsigned/signed long +#define PLUS (1<<2) //Show plus +#define SPACE (1<<3) //Spacer +#define LEFT (1<<4) //Left justified +#define HEX_PREP (1<<5) //0x +#define UPPERCASE (1<<6) //'ABCDEF' -static char *lower_digits = "0123456789abcdefghijklmnopqrstuvwxyz"; -static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') -/* -static size_t strnlen(const char *s, size_t count); - -static size_t strnlen(const char *s, size_t count) +static u32 skipAtoi(const char **s) { - const char *sc; - for (sc = s; *sc != '\0' && count--; ++sc); - return sc - s; -} -*/ - -static int ee_skip_atoi(const char **s) -{ - int i = 0; - while (is_digit(**s)) i = i*10 + *((*s)++) - '0'; - return i; + u32 i = 0; + while(IS_DIGIT(**s)) i = i * 10 + *((*s)++) - '0'; + return i; } -static char *ee_number(char *str, long long num, int base, int size, int precision, int type) +static char *processNumber(char *str, s64 num, bool isHex, s32 size, s32 precision, u32 type) { - char c, sign, tmp[66]; - char *dig = lower_digits; - int i; + if(type & LEFT) type &= ~ZEROPAD; - if (type & UPPERCASE) dig = upper_digits; - if (type & LEFT) type &= ~ZEROPAD; - if (base < 2 || base > 36) return 0; + char sign = 0; - c = (type & ZEROPAD) ? '0' : ' '; - sign = 0; - if (type & SIGN) - { - if (num < 0) + if(type & SIGN) { - sign = '-'; - num = -num; - size--; - } - else if (type & PLUS) - { - sign = '+'; - size--; - } - else if (type & SPACE) - { - sign = ' '; - size--; - } - } - - if (type & HEX_PREP) - { - if (base == 16) - size -= 2; - else if (base == 8) - size--; - } - - i = 0; - - if (num == 0) - tmp[i++] = '0'; - else - { - while (num != 0) - { - tmp[i++] = dig[(unsigned long long)num % (unsigned long long)base]; - num = (long long)((unsigned long long)num / (unsigned long long) base); - } - } - - if (i > precision) precision = i; - size -= precision; - if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' '; - if (sign) *str++ = sign; - - if (type & HEX_PREP) - { - if (base == 8) - *str++ = '0'; - else if (base == 16) - { - *str++ = '0'; - *str++ = lower_digits[33]; - } - } - - if (!(type & LEFT)) while (size-- > 0) *str++ = c; - while (i < precision--) *str++ = '0'; - while (i-- > 0) *str++ = tmp[i]; - while (size-- > 0) *str++ = ' '; - - return str; -} - -static char *eaddr(char *str, unsigned char *addr, int size, int precision __attribute__((unused)), int type) -{ - char tmp[24]; - char *dig = lower_digits; - int i, len; - - if (type & UPPERCASE) dig = upper_digits; - len = 0; - for (i = 0; i < 6; i++) - { - if (i != 0) tmp[len++] = ':'; - tmp[len++] = dig[addr[i] >> 4]; - tmp[len++] = dig[addr[i] & 0x0F]; - } - - if (!(type & LEFT)) while (len < size--) *str++ = ' '; - for (i = 0; i < len; ++i) *str++ = tmp[i]; - while (len < size--) *str++ = ' '; - - return str; -} - -static char *iaddr(char *str, unsigned char *addr, int size, int precision __attribute__((unused)), int type) -{ - char tmp[24]; - int i, n, len; - - len = 0; - for (i = 0; i < 4; i++) - { - if (i != 0) tmp[len++] = '.'; - n = addr[i]; - - if (n == 0) - tmp[len++] = lower_digits[0]; - else - { - if (n >= 100) - { - tmp[len++] = lower_digits[n / 100]; - n = n % 100; - tmp[len++] = lower_digits[n / 10]; - n = n % 10; - } - else if (n >= 10) - { - tmp[len++] = lower_digits[n / 10]; - n = n % 10; - } - - tmp[len++] = lower_digits[n]; - } - } - - if (!(type & LEFT)) while (len < size--) *str++ = ' '; - for (i = 0; i < len; ++i) *str++ = tmp[i]; - while (len < size--) *str++ = ' '; - - return str; -} - -static int ee_vsprintf(char *buf, const char *fmt, va_list args) -{ - int len; - long long num; - int i, base; - char *str; - char *s; - int flags; // Flags to number() - - int field_width; // Width of output field - int precision; // Min. # of digits for integers; max number of chars for from string - int qualifier; // 'h', 'l', or 'L' for integer fields - int qualifier2; - - for (str = buf; *fmt; fmt++) - { - if (*fmt != '%') - { - *str++ = *fmt; - continue; - } - - // Process flags - flags = 0; -repeat: - fmt++; // This also skips first '%' - switch (*fmt) - { - case '-': flags |= LEFT; goto repeat; - case '+': flags |= PLUS; goto repeat; - case ' ': flags |= SPACE; goto repeat; - case '#': flags |= HEX_PREP; goto repeat; - case '0': flags |= ZEROPAD; goto repeat; - } - - // Get field width - field_width = -1; - if (is_digit(*fmt)) - field_width = ee_skip_atoi(&fmt); - else if (*fmt == '*') - { - fmt++; - field_width = va_arg(args, int); - if (field_width < 0) - { - field_width = -field_width; - flags |= LEFT; - } - } - - // Get the precision - precision = -1; - if (*fmt == '.') - { - ++fmt; - if (is_digit(*fmt)) - precision = ee_skip_atoi(&fmt); - else if (*fmt == '*') - { - ++fmt; - precision = va_arg(args, int); - } - if (precision < 0) precision = 0; - } - - // Get the conversion qualifier - qualifier = qualifier2 = -1; - if(*fmt == 'L') - qualifier = *fmt++; - else if (*fmt == 'l') - { - qualifier = *fmt++; - if(*fmt == 'l') qualifier2 = *fmt++; - } - else if (*fmt == 'h') - { - qualifier = *fmt++; - if(*fmt == 'h') qualifier2 = *fmt++; - } - - // Default base - base = 10; - - switch (*fmt) - { - case 'c': - if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' '; - *str++ = (unsigned char) va_arg(args, int); - while (--field_width > 0) *str++ = ' '; - continue; - - case 's': - s = va_arg(args, char *); - if (!s) s = ""; - if(precision != -1) - len = strnlen(s, precision); - else - len = strlen(s); - if (!(flags & LEFT)) while (len < field_width--) *str++ = ' '; - for (i = 0; i < len; ++i) *str++ = *s++; - while (len < field_width--) *str++ = ' '; - continue; - - case 'p': - if (field_width == -1) + if(num < 0) { - field_width = 2 * sizeof(void *); - flags |= ZEROPAD; + sign = '-'; + num = -num; + size--; + } + else if(type & PLUS) + { + sign = '+'; + size--; + } + else if(type & SPACE) + { + sign = ' '; + size--; } - str = ee_number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags); - continue; - - case 'A': - flags |= UPPERCASE; - - case 'a': - if (qualifier == 'l') - str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); - else - str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags); - continue; - - // Integer number formats - set up the flags and "break" - case 'o': - base = 8; - break; - - case 'X': - flags |= UPPERCASE; - - case 'x': - base = 16; - break; - - case 'd': - case 'i': - flags |= SIGN; - - case 'u': - break; - - default: - if (*fmt != '%') *str++ = '%'; - if (*fmt) - *str++ = *fmt; - else - --fmt; - continue; } - // bugfixes here: + if(type & HEX_PREP && isHex) size -= 2; - if(flags & SIGN) - { - if (qualifier == 'l' && qualifier2 == 'l') - num = va_arg(args, long long int); - else if(qualifier == 'l') - num = va_arg(args, long int); -/* else if(qualifier == 'h' && qualifier == 'h') - num = va_arg(args, signed char); - else if(qualifier == 'h') - num = va_arg(args, short);*/ - else - num = va_arg(args, int); - } + static const char *lowerDigits = "0123456789abcdef", + *upperDigits = "0123456789ABCDEF"; + + s32 i = 0; + char tmp[66], + c = (type & ZEROPAD) ? '0' : ' '; + const char *dig = (type & UPPERCASE) ? upperDigits : lowerDigits; + + if(num == 0) tmp[i++] = '0'; else { - if (qualifier == 'l' && qualifier2 == 'l') - num = va_arg(args, unsigned long long int); - else if(qualifier == 'l') - num = va_arg(args, unsigned long int); -/* else if(qualifier == 'h' && qualifier == 'h') - num = va_arg(args, unsigned char); - else if(qualifier == 'h') - num = va_arg(args, unsigned short);*/ - else - num = va_arg(args, unsigned int); + while (num != 0) + { + u64 base = isHex ? 16ULL : 10ULL; + tmp[i++] = dig[(u64)num % base]; + num = (s64)((u64)num / base); + } } - str = ee_number(str, num, base, field_width, precision, flags); - } + if(i > precision) precision = i; + size -= precision; + if(!(type & (ZEROPAD | LEFT))) while(size-- > 0) *str++ = ' '; + if(sign) *str++ = sign; - *str = '\0'; - return str - buf; + if(type & HEX_PREP && isHex) + { + *str++ = '0'; + *str++ = 'x'; + } + + if(!(type & LEFT)) while(size-- > 0) *str++ = c; + while(i < precision--) *str++ = '0'; + while(i-- > 0) *str++ = tmp[i]; + while(size-- > 0) *str++ = ' '; + + return str; } -int vsprintf(char *buf, const char *fmt, va_list args) +u32 vsprintf(char *buf, const char *fmt, va_list args) { - return ee_vsprintf(buf, fmt, args); + char *str; + + for(str = buf; *fmt; fmt++) + { + if(*fmt != '%') + { + *str++ = *fmt; + continue; + } + + //Process flags + u32 flags = 0; //Flags to number() + bool loop = false; + + while(!loop) + { + switch(*++fmt) + { + case '-': flags |= LEFT; break; + case '+': flags |= PLUS; break; + case ' ': flags |= SPACE; break; + case '#': flags |= HEX_PREP; break; + case '0': flags |= ZEROPAD; break; + default: loop = true; break; + } + } + + //Get field width + s32 fieldWidth = -1; //Width of output field + if(IS_DIGIT(*fmt)) fieldWidth = skipAtoi(&fmt); + else if(*fmt == '*') + { + fmt++; + + fieldWidth = va_arg(args, s32); + + if(fieldWidth < 0) + { + fieldWidth = -fieldWidth; + flags |= LEFT; + } + } + + //Get the precision + s32 precision = -1; //Min. # of digits for integers; max number of chars for from string + if(*fmt == '.') + { + fmt++; + + if(IS_DIGIT(*fmt)) precision = skipAtoi(&fmt); + else if(*fmt == '*') + { + fmt++; + precision = va_arg(args, s32); + } + + if(precision < 0) precision = 0; + } + + //Get the conversion qualifier + bool isLongLong = false; + if(*fmt == 'l') + { + if(*++fmt == 'l') + { + fmt++; + isLongLong = true; + } + } + + //Default base + bool isHex = false; + + switch(*fmt) + { + case 'c': + if(!(flags & LEFT)) while(--fieldWidth > 0) *str++ = ' '; + *str++ = (u8)va_arg(args, s32); + while(--fieldWidth > 0) *str++ = ' '; + continue; + + case 's': + { + char *s = va_arg(args, char *); + if(!s) s = ""; + u32 len = (precision != -1) ? strnlen(s, precision) : strlen(s); + if(!(flags & LEFT)) while((s32)len < fieldWidth--) *str++ = ' '; + for(u32 i = 0; i < len; i++) *str++ = *s++; + while((s32)len < fieldWidth--) *str++ = ' '; + continue; + } + + case 'p': + if(fieldWidth == -1) + { + fieldWidth = 8; + flags |= ZEROPAD; + } + str = processNumber(str, (s64)va_arg(args, u32), true, fieldWidth, precision, flags); + continue; + + //Integer number formats - set up the flags and "break" + case 'X': + flags |= UPPERCASE; + + case 'x': + isHex = true; + break; + + case 'd': + case 'i': + flags |= SIGN; + + case 'u': + break; + + default: + if(*fmt != '%') *str++ = '%'; + if(*fmt) *str++ = *fmt; + else fmt--; + continue; + } + + s64 num; + + if(flags & SIGN) + { + if(isLongLong) num = va_arg(args, s64); + else num = va_arg(args, s32); + } + else + { + if(isLongLong) num = va_arg(args, u64); + else num = va_arg(args, u32); + } + + str = processNumber(str, num, isHex, fieldWidth, precision, flags); + } + + *str = 0; + return str - buf; } -int sprintf(char *buf, const char *fmt, ...) +u32 sprintf(char *buf, const char *fmt, ...) { - int n = 0; va_list args; va_start(args, fmt); - n = ee_vsprintf(buf, fmt, args); + u32 res = vsprintf(buf, fmt, args); va_end(args); - return n; + return res; } diff --git a/source/fmt.h b/source/fmt.h index f5867d7..94ed5bf 100644 --- a/source/fmt.h +++ b/source/fmt.h @@ -2,5 +2,5 @@ #include "memory.h" #include -int vsprintf(char *buf, const char *fmt, va_list args); -int sprintf(char *buf, const char *fmt, ...); +u32 vsprintf(char *buf, const char *fmt, va_list args); +u32 sprintf(char *buf, const char *fmt, ...); diff --git a/source/types.h b/source/types.h index 38d6b65..afbcba5 100644 --- a/source/types.h +++ b/source/types.h @@ -35,6 +35,14 @@ typedef volatile u8 vu8; typedef volatile u16 vu16; typedef volatile u32 vu32; typedef volatile u64 vu64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef volatile s8 vs8; +typedef volatile s16 vs16; +typedef volatile s32 vs32; +typedef volatile s64 vs64; #include "3dsheaders.h"