diff --git a/arm11/link.ld b/arm11/link.ld index c9370d6..14e8e69 100644 --- a/arm11/link.ld +++ b/arm11/link.ld @@ -1,64 +1,64 @@ -OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") -OUTPUT_ARCH(arm) -ENTRY(__boot) - -MEMORY -{ - /* Virtual address where bootrom will be mappped to avoid veneers */ - BOOTROM (RX) : ORIGIN = 0x17000000, LENGTH = 32K - VRAMLOAD (RWX) : ORIGIN = 0x18100000, LENGTH = 1M -} - -SECTIONS -{ - .bootrom (NOLOAD) : ALIGN(4K) - { - *(.bootrom*) - . = ALIGN(4K); - } >BOOTROM - - .text : ALIGN(4K) - { - __text_pa = LOADADDR(.text); - __text_va = ABSOLUTE(.); - *(.text*) - . = ALIGN(4K); - __text_len = . - __text_va; - } >VRAMLOAD - - .data : ALIGN(4K) - { - __data_pa = LOADADDR(.data); - __data_va = ABSOLUTE(.); - *(.data*) - . = ALIGN(4K); - __data_len = . - __data_va; - } >VRAMLOAD - - .rodata : ALIGN(4K) - { - __rodata_pa = LOADADDR(.rodata); - __rodata_va = ABSOLUTE(.); - *(.rodata*) - . = ALIGN(4K); - __rodata_len = . - __rodata_va; - } >VRAMLOAD - - .shared (NOLOAD) : ALIGN(4K) - { - __shared_pa = LOADADDR(.shared); - __shared_va = ABSOLUTE(.); - *(.shared*) - . = ALIGN(4K); - __shared_len = . - __shared_va; - } >VRAMLOAD - - .bss (NOLOAD) : ALIGN(4K) - { - __bss_pa = LOADADDR(.bss); - __bss_va = ABSOLUTE(.); - *(.bss*) - . = ALIGN(4K); - __bss_len = . - __bss_va; - } >VRAMLOAD -} +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(__boot) + +MEMORY +{ + /* Virtual address where bootrom will be mappped to avoid veneers */ + BOOTROM (RX) : ORIGIN = 0x17000000, LENGTH = 32K + VRAMLOAD (RWX) : ORIGIN = 0x18100000, LENGTH = 1M +} + +SECTIONS +{ + .bootrom (NOLOAD) : ALIGN(4K) + { + *(.bootrom*) + . = ALIGN(4K); + } >BOOTROM + + .text : ALIGN(4K) + { + __text_pa = LOADADDR(.text); + __text_va = ABSOLUTE(.); + *(.text*) + . = ALIGN(4K); + __text_len = . - __text_va; + } >VRAMLOAD + + .data : ALIGN(4K) + { + __data_pa = LOADADDR(.data); + __data_va = ABSOLUTE(.); + *(.data*) + . = ALIGN(4K); + __data_len = . - __data_va; + } >VRAMLOAD + + .rodata : ALIGN(4K) + { + __rodata_pa = LOADADDR(.rodata); + __rodata_va = ABSOLUTE(.); + *(.rodata*) + . = ALIGN(4K); + __rodata_len = . - __rodata_va; + } >VRAMLOAD + + .shared (NOLOAD) : ALIGN(4K) + { + __shared_pa = LOADADDR(.shared); + __shared_va = ABSOLUTE(.); + *(.shared*) + . = ALIGN(4K); + __shared_len = . - __shared_va; + } >VRAMLOAD + + .bss (NOLOAD) : ALIGN(4K) + { + __bss_pa = LOADADDR(.bss); + __bss_va = ABSOLUTE(.); + *(.bss*) + . = ALIGN(4K); + __bss_len = . - __bss_va; + } >VRAMLOAD +} diff --git a/arm11/source/arm/exception.c b/arm11/source/arm/exception.c index d0839f3..9902ac7 100644 --- a/arm11/source/arm/exception.c +++ b/arm11/source/arm/exception.c @@ -1,30 +1,30 @@ -#include "exception.h" -#include "ui/debug.h" - -#include -#include -#include - -#include - -void doException(u32 type, u32* regs) { - I2C_writeReg(I2C_DEV_CTR_MCU, 0x29, 4); - - consoleClear(); - debugPrintf("ARM11 ded %ld\n\n", type); - - for (int i = 0; i < 20; i += 2) { - debugPrintf("%02d %08lX %02d %08lX\n", i, regs[i], i+1, regs[i+1]); - } - - debugPrint("\nStack:\n"); - u32* sp = (u32*) regs[13]; - - for (int i = 0; i < 32; i += 4) { - debugPrintf("%08lX %08lX %08lX %08lX\n", sp[i], sp[i+1], sp[i+2], sp[i+3]); - } - - PXI_Send(PXICMD_LEGACY_BOOT); - - while (1); +#include "exception.h" +#include "ui/debug.h" + +#include +#include +#include + +#include + +void doException(u32 type, u32* regs) { + I2C_writeReg(I2C_DEV_CTR_MCU, 0x29, 4); + + consoleClear(); + debugPrintf("ARM11 ded %ld\n\n", type); + + for (int i = 0; i < 20; i += 2) { + debugPrintf("%02d %08lX %02d %08lX\n", i, regs[i], i+1, regs[i+1]); + } + + debugPrint("\nStack:\n"); + u32* sp = (u32*) regs[13]; + + for (int i = 0; i < 32; i += 4) { + debugPrintf("%08lX %08lX %08lX %08lX\n", sp[i], sp[i+1], sp[i+2], sp[i+3]); + } + + PXI_Send(PXICMD_LEGACY_BOOT); + + while (1); } \ No newline at end of file diff --git a/arm11/source/arm/exception.h b/arm11/source/arm/exception.h index 0b7e772..6082e7e 100644 --- a/arm11/source/arm/exception.h +++ b/arm11/source/arm/exception.h @@ -1,5 +1,5 @@ -#pragma once - -#include "common.h" - +#pragma once + +#include "common.h" + void doException(u32 type, u32* regs); \ No newline at end of file diff --git a/arm11/source/pxi/log.c b/arm11/source/pxi/log.c index c2b017f..cc3f134 100644 --- a/arm11/source/pxi/log.c +++ b/arm11/source/pxi/log.c @@ -1,32 +1,32 @@ -#include "log.h" -#include "common.h" - -#include -#include - -static u8 __attribute__((section(".shared"))) sharedBuffer[MAX_LOG_LEN]; - -bool pxiLogWrite(const void* data, unsigned int btw) { - btw = min(btw, MAX_LOG_LEN); - memcpy(sharedBuffer, data, btw); - - PXI_Send((2 << 16) | PXICMD_LOG_DATA); - PXI_Send((u32) sharedBuffer); - PXI_Send(btw); - - //consolePrint("sent pxi log data\n"); - - return PXI_Recv(); -} - -bool pxiLogWriteStr(const char* str) { - strncpy((char*) sharedBuffer, str, MAX_LOG_LEN - 1); - - PXI_Send((1 << 16) | PXICMD_LOG_DATA); - PXI_Send((u32) sharedBuffer); - - //consolePrint("sent pxi log str\n"); - - return PXI_Recv(); -} - +#include "log.h" +#include "common.h" + +#include +#include + +static u8 __attribute__((section(".shared"))) sharedBuffer[MAX_LOG_LEN]; + +bool pxiLogWrite(const void* data, unsigned int btw) { + btw = min(btw, MAX_LOG_LEN); + memcpy(sharedBuffer, data, btw); + + PXI_Send((2 << 16) | PXICMD_LOG_DATA); + PXI_Send((u32) sharedBuffer); + PXI_Send(btw); + + //consolePrint("sent pxi log data\n"); + + return PXI_Recv(); +} + +bool pxiLogWriteStr(const char* str) { + strncpy((char*) sharedBuffer, str, MAX_LOG_LEN - 1); + + PXI_Send((1 << 16) | PXICMD_LOG_DATA); + PXI_Send((u32) sharedBuffer); + + //consolePrint("sent pxi log str\n"); + + return PXI_Recv(); +} + diff --git a/arm11/source/pxi/log.h b/arm11/source/pxi/log.h index 9c386c1..7d875ac 100644 --- a/arm11/source/pxi/log.h +++ b/arm11/source/pxi/log.h @@ -1,8 +1,8 @@ -#pragma once - -#include "common.h" - -#define MAX_LOG_LEN 1024 - -bool pxiLogWrite(const void* data, unsigned int btw); +#pragma once + +#include "common.h" + +#define MAX_LOG_LEN 1024 + +bool pxiLogWrite(const void* data, unsigned int btw); bool pxiLogWriteStr(const char* str); \ No newline at end of file diff --git a/arm11/source/pxi/timer.c b/arm11/source/pxi/timer.c index 27d77a4..23136b6 100644 --- a/arm11/source/pxi/timer.c +++ b/arm11/source/pxi/timer.c @@ -1,11 +1,11 @@ -#include "log.h" -#include "common.h" - -#include -#include - -u64 pxiGetTimerTicks() { - PXI_Send((0 << 16) | PXICMD_GET_TIMER_TICKS); - - return PXI_Recv64(); -} +#include "log.h" +#include "common.h" + +#include +#include + +u64 pxiGetTimerTicks() { + PXI_Send((0 << 16) | PXICMD_GET_TIMER_TICKS); + + return PXI_Recv64(); +} diff --git a/arm11/source/pxi/timer.h b/arm11/source/pxi/timer.h index dc39dc5..bbc59ff 100644 --- a/arm11/source/pxi/timer.h +++ b/arm11/source/pxi/timer.h @@ -1,5 +1,5 @@ -#pragma once - -#include "common.h" - +#pragma once + +#include "common.h" + u64 pxiGetTimerTicks(); \ No newline at end of file diff --git a/arm11/source/ui/debug.c b/arm11/source/ui/debug.c index 06c6b4d..3eb0fad 100644 --- a/arm11/source/ui/debug.c +++ b/arm11/source/ui/debug.c @@ -1,29 +1,29 @@ -#include "debug.h" -#include "pxi/log.h" - -#include -#include -#include - -#include - -#define PREFIX_LEN (sizeof(ARM11_DEBUG_PREFIX) - 1) - -static char strBuf[sizeof(ARM11_DEBUG_PREFIX) + DEBUG_MAX_LEN] = ARM11_DEBUG_PREFIX; - -void logDebugPrintf(bool logOnly, const char* format, ...) { - va_list args; - va_start(args, format); - int n = bfnVsnprintf(strBuf + PREFIX_LEN, DEBUG_MAX_LEN, format, args); - va_end(args); - - if (n == 0) - return; - - if (!logOnly) { - if ((u32) n != consoleNPrint(strBuf + PREFIX_LEN, n)) - ARM_BKPT(); - } - - pxiLogWrite(strBuf, PREFIX_LEN + n); +#include "debug.h" +#include "pxi/log.h" + +#include +#include +#include + +#include + +#define PREFIX_LEN (sizeof(ARM11_DEBUG_PREFIX) - 1) + +static char strBuf[sizeof(ARM11_DEBUG_PREFIX) + DEBUG_MAX_LEN] = ARM11_DEBUG_PREFIX; + +void logDebugPrintf(bool logOnly, const char* format, ...) { + va_list args; + va_start(args, format); + int n = bfnVsnprintf(strBuf + PREFIX_LEN, DEBUG_MAX_LEN, format, args); + va_end(args); + + if (n == 0) + return; + + if (!logOnly) { + if ((u32) n != consoleNPrint(strBuf + PREFIX_LEN, n)) + ARM_BKPT(); + } + + pxiLogWrite(strBuf, PREFIX_LEN + n); } \ No newline at end of file diff --git a/arm11/source/ui/debug.h b/arm11/source/ui/debug.h index e756f5e..34958a8 100644 --- a/arm11/source/ui/debug.h +++ b/arm11/source/ui/debug.h @@ -1,12 +1,12 @@ -#pragma once - -#include "common.h" - -#define ARM11_DEBUG_PREFIX "[ARM11] " -#define DEBUG_MAX_LEN 512 - -#define debugPrint(str) debugPrintf("%s", str) -#define debugPrintf(format, args...) logDebugPrintf(false, format, args) - -// Uses bootrom vsnprintf +#pragma once + +#include "common.h" + +#define ARM11_DEBUG_PREFIX "[ARM11] " +#define DEBUG_MAX_LEN 512 + +#define debugPrint(str) debugPrintf("%s", str) +#define debugPrintf(format, args...) logDebugPrintf(false, format, args) + +// Uses bootrom vsnprintf void PRINTF_ARGS(2) logDebugPrintf(bool logOnly, const char* format, ...); \ No newline at end of file diff --git a/arm11/source/ui/draw.c b/arm11/source/ui/draw.c index 05062aa..23f6111 100644 --- a/arm11/source/ui/draw.c +++ b/arm11/source/ui/draw.c @@ -1,24 +1,24 @@ -#include "draw.h" - -u32 drawStringColor(u16* screen, const char* str, u32 x, u32 y, u16 color) { - u32 count = 0; - - for (; *str != '\0'; x += CHR_WIDTH, str++, count++) { - drawCharacter(screen, *str, x, y, color); - } - - return count; -} - -/*u32 DrawString(u16* screen, const char* str, u32 x, u32 y) { - return DrawStringColor(screen, str, x, y, CON_COLOR_FONT); -}*/ - -u32 drawStringCenteredColor(u16* screen, const char* str, u32 x, u32 y, u16 color) { - return drawStringColor(screen, str, x - (strlen(str) * CHR_WIDTH / 2), y, color); -} - -void drawProgressBar(u16* screen, u32 x, u32 y, u32 width, u32 height, u32 widthFilled, u16 fillColor, u16 unfillColor) { - fillRect(screen, x, y, widthFilled, height, fillColor); - fillRect(screen, x + widthFilled, y, width - widthFilled, height, unfillColor); +#include "draw.h" + +u32 drawStringColor(u16* screen, const char* str, u32 x, u32 y, u16 color) { + u32 count = 0; + + for (; *str != '\0'; x += CHR_WIDTH, str++, count++) { + drawCharacter(screen, *str, x, y, color); + } + + return count; +} + +/*u32 DrawString(u16* screen, const char* str, u32 x, u32 y) { + return DrawStringColor(screen, str, x, y, CON_COLOR_FONT); +}*/ + +u32 drawStringCenteredColor(u16* screen, const char* str, u32 x, u32 y, u16 color) { + return drawStringColor(screen, str, x - (strlen(str) * CHR_WIDTH / 2), y, color); +} + +void drawProgressBar(u16* screen, u32 x, u32 y, u32 width, u32 height, u32 widthFilled, u16 fillColor, u16 unfillColor) { + fillRect(screen, x, y, widthFilled, height, fillColor); + fillRect(screen, x + widthFilled, y, width - widthFilled, height, unfillColor); } \ No newline at end of file diff --git a/arm11/source/ui/draw.h b/arm11/source/ui/draw.h index 75f99e6..af0616c 100644 --- a/arm11/source/ui/draw.h +++ b/arm11/source/ui/draw.h @@ -1,10 +1,10 @@ -#pragma once - -#include - -u32 drawStringColor(u16* screen, const char* str, u32 x, u32 y, u16 color); -//u32 DrawString(u16* screen, const char* str, u32 x, u32 y); - -u32 drawStringCenteredColor(u16* screen, const char* str, u32 x, u32 y, u16 color); - +#pragma once + +#include + +u32 drawStringColor(u16* screen, const char* str, u32 x, u32 y, u16 color); +//u32 DrawString(u16* screen, const char* str, u32 x, u32 y); + +u32 drawStringCenteredColor(u16* screen, const char* str, u32 x, u32 y, u16 color); + void drawProgressBar(u16* screen, u32 x, u32 y, u32 width, u32 height, u32 widthFilled, u16 fillColor, u16 unfillColor); \ No newline at end of file diff --git a/arm11/source/ui/ui.c b/arm11/source/ui/ui.c index 4d68960..79a5eb0 100644 --- a/arm11/source/ui/ui.c +++ b/arm11/source/ui/ui.c @@ -1,18 +1,18 @@ -#include "ui.h" - -#include -#include "ui/debug.h" - -static void drawBorders() { - fillRect(MAIN_SCREEN, 0, 0, BORDER_THICKNESS, SCREEN_HEIGHT, BORDER_COLOR); - fillRect(MAIN_SCREEN, 0, 0, MAIN_SCREEN_WIDTH, BORDER_THICKNESS, BORDER_COLOR); - fillRect(MAIN_SCREEN, MAIN_SCREEN_WIDTH - BORDER_THICKNESS, 0, BORDER_THICKNESS, SCREEN_HEIGHT, BORDER_COLOR); - fillRect(MAIN_SCREEN, 0, SCREEN_HEIGHT - BORDER_THICKNESS, MAIN_SCREEN_WIDTH, BORDER_THICKNESS, BORDER_COLOR); -} - -void initUI() { - drawBorders(); - - drawStringCenteredColor(MAIN_SCREEN, "3ds_hw_test by aspargas2 - commit " COMMIT, MAIN_SCREEN_WIDTH / 2, BORDER_THICKNESS + 2, COLOR_LIGHT_BLUE); - //drawProgressBar(MAIN_SCREEN, 50, 50, 100, 10, 50, COLOR_GREEN, COLOR_GREY); +#include "ui.h" + +#include +#include "ui/debug.h" + +static void drawBorders() { + fillRect(MAIN_SCREEN, 0, 0, BORDER_THICKNESS, SCREEN_HEIGHT, BORDER_COLOR); + fillRect(MAIN_SCREEN, 0, 0, MAIN_SCREEN_WIDTH, BORDER_THICKNESS, BORDER_COLOR); + fillRect(MAIN_SCREEN, MAIN_SCREEN_WIDTH - BORDER_THICKNESS, 0, BORDER_THICKNESS, SCREEN_HEIGHT, BORDER_COLOR); + fillRect(MAIN_SCREEN, 0, SCREEN_HEIGHT - BORDER_THICKNESS, MAIN_SCREEN_WIDTH, BORDER_THICKNESS, BORDER_COLOR); +} + +void initUI() { + drawBorders(); + + drawStringCenteredColor(MAIN_SCREEN, "3ds_hw_test by aspargas2 - commit " COMMIT, MAIN_SCREEN_WIDTH / 2, BORDER_THICKNESS + 2, COLOR_LIGHT_BLUE); + //drawProgressBar(MAIN_SCREEN, 50, 50, 100, 10, 50, COLOR_GREEN, COLOR_GREY); } \ No newline at end of file diff --git a/arm11/source/ui/ui.h b/arm11/source/ui/ui.h index 7d4850b..c03d440 100644 --- a/arm11/source/ui/ui.h +++ b/arm11/source/ui/ui.h @@ -1,8 +1,8 @@ -#pragma once - -#include "draw.h" - -#define BORDER_THICKNESS 2 -#define BORDER_COLOR COLOR_WHITE - +#pragma once + +#include "draw.h" + +#define BORDER_THICKNESS 2 +#define BORDER_COLOR COLOR_WHITE + void initUI(); \ No newline at end of file diff --git a/arm9/source/debug.c b/arm9/source/debug.c index 67fc2ba..f82d3ad 100644 --- a/arm9/source/debug.c +++ b/arm9/source/debug.c @@ -1,126 +1,126 @@ -#include "debug.h" -#include "console.h" -#include "smalllib.h" - -#include - -#ifdef ARM9 -#include -#else -#include -#endif - -#include -#include -#include - -static void debugNPrint(bool logOnly, const char* str, u32 n) { - // Console code returns number of chars printed, so min(n, strlen(str)) - if (n == 0) - return; - n = logOnly ? strnlen(str, n) : - consoleNPrint(str, n); - if (n == 0) - return; - logWrite(str, n); -} - -void debugPrint(const char* str) { - if (*str == '\0') - return; - u32 irqState = ARM_EnterCritical(); - logWrite(ARM9_DEBUG_PREFIX, sizeof(ARM9_DEBUG_PREFIX) - 1); - debugNPrint(false, str, -1); - ARM_LeaveCritical(irqState); -} - -void logDebugPrintf(bool logOnly, const char* format, ...) { - static char strbuf[30]; - u32 i = 0; - - u32 irqState = ARM_EnterCritical(); - va_list args; - va_start(args, format); - - logWrite(ARM9_DEBUG_PREFIX, sizeof(ARM9_DEBUG_PREFIX) - 1); - - for (;;i++) { - char c = format[i]; - - if (c == '\0') { - debugNPrint(logOnly, format, i); - break; - } - - if (c == '%') { - debugNPrint(logOnly, format, i); - format += i; - i = 0; - int lcount = 0; - - codeswitch: - switch (format[1]) { - case '%': - format++; - continue; - case 's': - debugNPrint(logOnly, va_arg(args, const char*), -1); - format += 2; - continue; - case 'd': { - s32 arg; - if (lcount > 1) { - s64 arg64 = va_arg(args, s64); - if ((arg64 < (s64) INT32_MIN) || (arg64 > (s64) INT32_MAX)) - goto default_; - else - arg = (s32) arg64; - } else - arg = va_arg(args, s32); - itoadec(arg, strbuf); - debugNPrint(logOnly, strbuf, 30); - format += 2; - continue; - } - case 'u': { - u32 arg; - if (lcount > 1) { - u64 arg64 = va_arg(args, u64); - if (arg64 > (u64) UINT32_MAX) - goto default_; - else - arg = (u32) arg64; - } else - arg = va_arg(args, u32); - utoadec(arg, strbuf); - debugNPrint(logOnly, strbuf, 30); - format += 2; - continue; - } - case 'x': - if (lcount > 1) { - u64 arg = va_arg(args, u64); - utoahex(arg >> 32, strbuf); - if (*strbuf != '0') - debugNPrint(logOnly, strbuf, 30); - utoahex((u32) arg, strbuf); - } else - utoahex(va_arg(args, u32), strbuf); - debugNPrint(logOnly, strbuf, 30); - format += 2; - continue; - case 'l': - lcount++; - format++; - goto codeswitch; - default_: - default: - format -= lcount; - continue; - } - } - } - - va_end(args); - ARM_LeaveCritical(irqState); +#include "debug.h" +#include "console.h" +#include "smalllib.h" + +#include + +#ifdef ARM9 +#include +#else +#include +#endif + +#include +#include +#include + +static void debugNPrint(bool logOnly, const char* str, u32 n) { + // Console code returns number of chars printed, so min(n, strlen(str)) + if (n == 0) + return; + n = logOnly ? strnlen(str, n) : + consoleNPrint(str, n); + if (n == 0) + return; + logWrite(str, n); +} + +void debugPrint(const char* str) { + if (*str == '\0') + return; + u32 irqState = ARM_EnterCritical(); + logWrite(ARM9_DEBUG_PREFIX, sizeof(ARM9_DEBUG_PREFIX) - 1); + debugNPrint(false, str, -1); + ARM_LeaveCritical(irqState); +} + +void logDebugPrintf(bool logOnly, const char* format, ...) { + static char strbuf[30]; + u32 i = 0; + + u32 irqState = ARM_EnterCritical(); + va_list args; + va_start(args, format); + + logWrite(ARM9_DEBUG_PREFIX, sizeof(ARM9_DEBUG_PREFIX) - 1); + + for (;;i++) { + char c = format[i]; + + if (c == '\0') { + debugNPrint(logOnly, format, i); + break; + } + + if (c == '%') { + debugNPrint(logOnly, format, i); + format += i; + i = 0; + int lcount = 0; + + codeswitch: + switch (format[1]) { + case '%': + format++; + continue; + case 's': + debugNPrint(logOnly, va_arg(args, const char*), -1); + format += 2; + continue; + case 'd': { + s32 arg; + if (lcount > 1) { + s64 arg64 = va_arg(args, s64); + if ((arg64 < (s64) INT32_MIN) || (arg64 > (s64) INT32_MAX)) + goto default_; + else + arg = (s32) arg64; + } else + arg = va_arg(args, s32); + itoadec(arg, strbuf); + debugNPrint(logOnly, strbuf, 30); + format += 2; + continue; + } + case 'u': { + u32 arg; + if (lcount > 1) { + u64 arg64 = va_arg(args, u64); + if (arg64 > (u64) UINT32_MAX) + goto default_; + else + arg = (u32) arg64; + } else + arg = va_arg(args, u32); + utoadec(arg, strbuf); + debugNPrint(logOnly, strbuf, 30); + format += 2; + continue; + } + case 'x': + if (lcount > 1) { + u64 arg = va_arg(args, u64); + utoahex(arg >> 32, strbuf); + if (*strbuf != '0') + debugNPrint(logOnly, strbuf, 30); + utoahex((u32) arg, strbuf); + } else + utoahex(va_arg(args, u32), strbuf); + debugNPrint(logOnly, strbuf, 30); + format += 2; + continue; + case 'l': + lcount++; + format++; + goto codeswitch; + default_: + default: + format -= lcount; + continue; + } + } + } + + va_end(args); + ARM_LeaveCritical(irqState); } \ No newline at end of file diff --git a/arm9/source/debug.h b/arm9/source/debug.h index 81c4d92..a4c6a07 100644 --- a/arm9/source/debug.h +++ b/arm9/source/debug.h @@ -1,12 +1,12 @@ -#pragma once - -#include "common.h" - -#define ARM9_DEBUG_PREFIX "[ARM9] " - -#define debugPrintf(format, args...) logDebugPrintf(false, format, args) - -void debugPrint(const char* str); - -// Hand-rolled minimal printf +#pragma once + +#include "common.h" + +#define ARM9_DEBUG_PREFIX "[ARM9] " + +#define debugPrintf(format, args...) logDebugPrintf(false, format, args) + +void debugPrint(const char* str); + +// Hand-rolled minimal printf void PRINTF_ARGS(2) logDebugPrintf(bool logOnly, const char* format, ...); \ No newline at end of file diff --git a/arm9/source/exception.c b/arm9/source/exception.c index 085b8d4..79ad8f2 100644 --- a/arm9/source/exception.c +++ b/arm9/source/exception.c @@ -1,30 +1,30 @@ -#include "exception.h" - -#include -#include -#include - -#include "log.h" - -void doException(u32 type, u32* regs) { - I2C_writeReg(I2C_DEV_CTR_MCU, 0x29, 4); - - consoleClear(); - debugPrintf("\nARM9 ded %ld\n\n", type); - - for (int i = 0; i < 16; i += 2) { - debugPrintf("%d %lx %d %lx\n", i, regs[i], i + 1, regs[i + 1]); - } - - debugPrintf("CPSR %lx\n\nStack:\n", regs[16]); - - u32* sp = (u32*) regs[13]; - - for (int i = 0; i < 16; i += 4) { - debugPrintf("%lx %lx %lx %lx\n", sp[i], sp[i+1], sp[i+2], sp[i+3]); - } - - deinitLog(); - - while (1); +#include "exception.h" + +#include +#include +#include + +#include "log.h" + +void doException(u32 type, u32* regs) { + I2C_writeReg(I2C_DEV_CTR_MCU, 0x29, 4); + + consoleClear(); + debugPrintf("\nARM9 ded %ld\n\n", type); + + for (int i = 0; i < 16; i += 2) { + debugPrintf("%d %lx %d %lx\n", i, regs[i], i + 1, regs[i + 1]); + } + + debugPrintf("CPSR %lx\n\nStack:\n", regs[16]); + + u32* sp = (u32*) regs[13]; + + for (int i = 0; i < 16; i += 4) { + debugPrintf("%lx %lx %lx %lx\n", sp[i], sp[i+1], sp[i+2], sp[i+3]); + } + + deinitLog(); + + while (1); } \ No newline at end of file diff --git a/arm9/source/exception.h b/arm9/source/exception.h index 0b7e772..6082e7e 100644 --- a/arm9/source/exception.h +++ b/arm9/source/exception.h @@ -1,5 +1,5 @@ -#pragma once - -#include "common.h" - +#pragma once + +#include "common.h" + void doException(u32 type, u32* regs); \ No newline at end of file diff --git a/arm9/source/irq.h b/arm9/source/irq.h index 03f1c11..facd0f9 100644 --- a/arm9/source/irq.h +++ b/arm9/source/irq.h @@ -1,32 +1,32 @@ -#pragma once - -#include "common.h" - -// https://www.3dbrew.org/wiki/IRQ_Registers - -#define IRQ_IE ((vu32*)0x10001000) -#define IRQ_IF ((vu32*)0x10001004) - -static inline void disableAllInterrupts() { - *IRQ_IE = 0; -} - -static inline void enableInterrupt(u32 irqn) { - *IRQ_IE |= BIT(irqn); -} - -static inline void disableInterrupt(u32 irqn) { - *IRQ_IE &= ~BIT(irqn); -} - -static inline void clearAllInterrupts() { - *IRQ_IF = -1; -} - -static inline bool testInterrupt(u32 irqn) { - return *IRQ_IF & BIT(irqn); -} - -static inline void clearInterrupt(u32 irqn) { - *IRQ_IF &= BIT(irqn); +#pragma once + +#include "common.h" + +// https://www.3dbrew.org/wiki/IRQ_Registers + +#define IRQ_IE ((vu32*)0x10001000) +#define IRQ_IF ((vu32*)0x10001004) + +static inline void disableAllInterrupts() { + *IRQ_IE = 0; +} + +static inline void enableInterrupt(u32 irqn) { + *IRQ_IE |= BIT(irqn); +} + +static inline void disableInterrupt(u32 irqn) { + *IRQ_IE &= ~BIT(irqn); +} + +static inline void clearAllInterrupts() { + *IRQ_IF = -1; +} + +static inline bool testInterrupt(u32 irqn) { + return *IRQ_IF & BIT(irqn); +} + +static inline void clearInterrupt(u32 irqn) { + *IRQ_IF &= BIT(irqn); } \ No newline at end of file diff --git a/arm9/source/irqHandlers.c b/arm9/source/irqHandlers.c index 1ccb3be..fb50e6b 100644 --- a/arm9/source/irqHandlers.c +++ b/arm9/source/irqHandlers.c @@ -1,73 +1,73 @@ -#include "irqHandlers.h" - -#include -#include -#include - -#include "irq.h" -#include "log.h" -#include "timer.h" - -#define PXICMD_QUEUE_LEN 64 - -#define CIRC_INC(i) (((i) == (PXICMD_QUEUE_LEN - 1)) ? (0) : ((i) + 1)) -#define CIRC_DEC(i) (((i) == 0) ? (PXICMD_QUEUE_LEN - 1) : ((i) - 1)) - -static u32 pxicmdQueue[PXICMD_QUEUE_LEN]; - -static u32 pxicmdQueueFront = 0; -static u32 pxicmdQueueBack = 0; - -static void enqueuePxicmd(u32 cmd) { - if (pxicmdQueueFront == CIRC_INC(pxicmdQueueBack)) - ARM_BKPT(); - - pxicmdQueue[pxicmdQueueBack = CIRC_INC(pxicmdQueueBack)] = cmd; -} - -u32 dequeuePxicmd() { - if (pxicmdQueueFront == pxicmdQueueBack) - return PXICMD_NONE; - - return pxicmdQueue[pxicmdQueueFront = CIRC_INC(pxicmdQueueFront)]; -} - -void irqHandlerMain(/*u32 lr*/) { - //debugPrintf("Got IRQ; %x\n", lr); - - if(testInterrupt(TIMER_INTERRUPT(0))) - clearInterrupt(TIMER_INTERRUPT(0)); - - if (testInterrupt(PXI_RX_INTERRUPT)) { - clearInterrupt(PXI_RX_INTERRUPT); - - while (!(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY)) { - u32 cmd = PXI_Recv(); - u32 argc = cmd >> 16; - cmd &= 0xFFFF; - - switch (cmd) { - case PXICMD_LOG_DATA: - PXI_Send(logWrite((void*) PXI_Recv(), PXI_Recv())); - break; - - case PXICMD_LOG_STRING: - PXI_Send(logWriteStr((char*) PXI_Recv())); - break; - - case PXICMD_GET_TIMER_TICKS: - PXI_Send64(getFullTimerTicks()); - break; - - // For all other commands, place command ID and args in queue to be dealt with later - default: - enqueuePxicmd(cmd); - for (u32 i = 0; i < argc; i++) - enqueuePxicmd(PXI_Recv()); - break; - } - - //debugPrintf("Handled cmd %d\n", cmd); - } - } +#include "irqHandlers.h" + +#include +#include +#include + +#include "irq.h" +#include "log.h" +#include "timer.h" + +#define PXICMD_QUEUE_LEN 64 + +#define CIRC_INC(i) (((i) == (PXICMD_QUEUE_LEN - 1)) ? (0) : ((i) + 1)) +#define CIRC_DEC(i) (((i) == 0) ? (PXICMD_QUEUE_LEN - 1) : ((i) - 1)) + +static u32 pxicmdQueue[PXICMD_QUEUE_LEN]; + +static u32 pxicmdQueueFront = 0; +static u32 pxicmdQueueBack = 0; + +static void enqueuePxicmd(u32 cmd) { + if (pxicmdQueueFront == CIRC_INC(pxicmdQueueBack)) + ARM_BKPT(); + + pxicmdQueue[pxicmdQueueBack = CIRC_INC(pxicmdQueueBack)] = cmd; +} + +u32 dequeuePxicmd() { + if (pxicmdQueueFront == pxicmdQueueBack) + return PXICMD_NONE; + + return pxicmdQueue[pxicmdQueueFront = CIRC_INC(pxicmdQueueFront)]; +} + +void irqHandlerMain(/*u32 lr*/) { + //debugPrintf("Got IRQ; %x\n", lr); + + if(testInterrupt(TIMER_INTERRUPT(0))) + clearInterrupt(TIMER_INTERRUPT(0)); + + if (testInterrupt(PXI_RX_INTERRUPT)) { + clearInterrupt(PXI_RX_INTERRUPT); + + while (!(*PXI_CNT & PXI_CNT_RECV_FIFO_EMPTY)) { + u32 cmd = PXI_Recv(); + u32 argc = cmd >> 16; + cmd &= 0xFFFF; + + switch (cmd) { + case PXICMD_LOG_DATA: + PXI_Send(logWrite((void*) PXI_Recv(), PXI_Recv())); + break; + + case PXICMD_LOG_STRING: + PXI_Send(logWriteStr((char*) PXI_Recv())); + break; + + case PXICMD_GET_TIMER_TICKS: + PXI_Send64(getFullTimerTicks()); + break; + + // For all other commands, place command ID and args in queue to be dealt with later + default: + enqueuePxicmd(cmd); + for (u32 i = 0; i < argc; i++) + enqueuePxicmd(PXI_Recv()); + break; + } + + //debugPrintf("Handled cmd %d\n", cmd); + } + } } \ No newline at end of file diff --git a/arm9/source/irqHandlers.h b/arm9/source/irqHandlers.h index e7df4e8..1b26fb0 100644 --- a/arm9/source/irqHandlers.h +++ b/arm9/source/irqHandlers.h @@ -1,7 +1,7 @@ -#pragma once - -#include - -u32 dequeuePxicmd(); - +#pragma once + +#include + +u32 dequeuePxicmd(); + void irqHandlerMain(/*u32 lr*/); \ No newline at end of file diff --git a/arm9/source/smalllib.c b/arm9/source/smalllib.c index 4fc4339..ddcbfa3 100644 --- a/arm9/source/smalllib.c +++ b/arm9/source/smalllib.c @@ -1,101 +1,101 @@ -#include "smalllib.h" - -#include - -size_t strlen(const char* str) { - return strnlen(str, INT_MAX); -} - -size_t strnlen(const char* str, size_t maxlen) { - size_t len = 0; - - while (len < maxlen && str[len] != '\0') len++; - - return len; -} - -char* strchr(const char* str, int c) { - for (char ch = *str; ch != '\0'; ch = *(++str)) - if (ch == c) - return (char*) str; - - return NULL; -} - -int memcmp(const void* ptr1, const void* ptr2, size_t num) { - const u8* p1 = ptr1; - const u8* p2 = ptr2; - - for (; num != 0; num--) { - u8 diff = *p1++ - *p2++; - - if (diff != 0) - return diff; - } - - return 0; -} - -void utoahex(u32 x, char* buf) { - bool started = false; - - for (size_t i = 0; i < sizeof(x) * 2; i++) { - const u8 dig = x >> 28; - - if (started || dig != 0) { - *buf++ = ((dig < 10) ? '0' : ('a' - 0xA)) + dig; - started = true; - } - - x <<= 4; - } - - if (!started) - *buf++ = '0'; - - *buf = '\0'; -} - -// Compile for arm so __aeabi_uidiv_whatever can get inlined and optimized -void __attribute__((noinline, target("arm"))) utoadec(u32 x, char* buf) { - bool started = false; - u32 pow_10 = 1000000000UL; - - while (pow_10 != 0) { - char dig = '0'; - - while (true) { - const u32 temp = x - pow_10; - if (temp > x) - break; - x = temp; - dig++; - } - - if (started || dig != '0') { - *buf++ = dig; - started = true; - } - - pow_10 /= 10; - } - - if (!started) - *buf++ = '0'; - - *buf = '\0'; -} - -void itoadec(s32 x, char* buf) { - if (x < 0) { - *buf++ = '-'; - x = -x; - } - - utoadec(x, buf); -} - -int __attribute__((naked, target("arm"))) clz(u32 __attribute__((unused)) x) { - asm("clz r0, r0"); - asm("bx lr"); +#include "smalllib.h" + +#include + +size_t strlen(const char* str) { + return strnlen(str, INT_MAX); +} + +size_t strnlen(const char* str, size_t maxlen) { + size_t len = 0; + + while (len < maxlen && str[len] != '\0') len++; + + return len; +} + +char* strchr(const char* str, int c) { + for (char ch = *str; ch != '\0'; ch = *(++str)) + if (ch == c) + return (char*) str; + + return NULL; +} + +int memcmp(const void* ptr1, const void* ptr2, size_t num) { + const u8* p1 = ptr1; + const u8* p2 = ptr2; + + for (; num != 0; num--) { + u8 diff = *p1++ - *p2++; + + if (diff != 0) + return diff; + } + + return 0; +} + +void utoahex(u32 x, char* buf) { + bool started = false; + + for (size_t i = 0; i < sizeof(x) * 2; i++) { + const u8 dig = x >> 28; + + if (started || dig != 0) { + *buf++ = ((dig < 10) ? '0' : ('a' - 0xA)) + dig; + started = true; + } + + x <<= 4; + } + + if (!started) + *buf++ = '0'; + + *buf = '\0'; +} + +// Compile for arm so __aeabi_uidiv_whatever can get inlined and optimized +void __attribute__((noinline, target("arm"))) utoadec(u32 x, char* buf) { + bool started = false; + u32 pow_10 = 1000000000UL; + + while (pow_10 != 0) { + char dig = '0'; + + while (true) { + const u32 temp = x - pow_10; + if (temp > x) + break; + x = temp; + dig++; + } + + if (started || dig != '0') { + *buf++ = dig; + started = true; + } + + pow_10 /= 10; + } + + if (!started) + *buf++ = '0'; + + *buf = '\0'; +} + +void itoadec(s32 x, char* buf) { + if (x < 0) { + *buf++ = '-'; + x = -x; + } + + utoadec(x, buf); +} + +int __attribute__((naked, target("arm"))) clz(u32 __attribute__((unused)) x) { + asm("clz r0, r0"); + asm("bx lr"); } \ No newline at end of file diff --git a/arm9/source/smalllib.h b/arm9/source/smalllib.h index b9e7380..8e44592 100644 --- a/arm9/source/smalllib.h +++ b/arm9/source/smalllib.h @@ -1,15 +1,15 @@ -#pragma once - -#include "common.h" -#include "bfn.h" - -#include - -#define memset(dest, c, num) ((void) bfnMemset(dest, c, num)) -#define memcpy(dest, src, num) ((void) bfnMemcpy(src, dest, num)) - -int clz(u32 x); - -void utoahex(u32 x, char* buf); -void utoadec(u32 x, char* buf); +#pragma once + +#include "common.h" +#include "bfn.h" + +#include + +#define memset(dest, c, num) ((void) bfnMemset(dest, c, num)) +#define memcpy(dest, src, num) ((void) bfnMemcpy(src, dest, num)) + +int clz(u32 x); + +void utoahex(u32 x, char* buf); +void utoadec(u32 x, char* buf); void itoadec(s32 x, char* buf); \ No newline at end of file diff --git a/arm9/source/timer.c b/arm9/source/timer.c index c002c7e..97b3e1b 100644 --- a/arm9/source/timer.c +++ b/arm9/source/timer.c @@ -1,28 +1,28 @@ -#include "timer.h" - -#include - -void resetAllTimers() { - for (int i = 0; i < N_TIMERS; i++) - resetTimer(i); -} - -void startFullTimerCountup(TimerPrescaler prescaler) { - resetAllTimers(); - - TIMER_CNT(0) = TIMER_ACTIVE | TIMER_ENABLE_IRQ | prescaler; - TIMER_CNT(1) = TIMER_CNT(2) = TIMER_CNT(3) = TIMER_ACTIVE | TIMER_COUNT_UP; -} - -u64 getFullTimerTicks() { - u64 ticks = 0; - u32 irqState = ARM_EnterCritical(); - - for (int i = N_TIMERS - 1; i >= 0; i--) { - ticks <<= 16; - ticks |= (u64) TIMER_VAL(i); - } - - ARM_LeaveCritical(irqState); - return ticks; +#include "timer.h" + +#include + +void resetAllTimers() { + for (int i = 0; i < N_TIMERS; i++) + resetTimer(i); +} + +void startFullTimerCountup(TimerPrescaler prescaler) { + resetAllTimers(); + + TIMER_CNT(0) = TIMER_ACTIVE | TIMER_ENABLE_IRQ | prescaler; + TIMER_CNT(1) = TIMER_CNT(2) = TIMER_CNT(3) = TIMER_ACTIVE | TIMER_COUNT_UP; +} + +u64 getFullTimerTicks() { + u64 ticks = 0; + u32 irqState = ARM_EnterCritical(); + + for (int i = N_TIMERS - 1; i >= 0; i--) { + ticks <<= 16; + ticks |= (u64) TIMER_VAL(i); + } + + ARM_LeaveCritical(irqState); + return ticks; } \ No newline at end of file diff --git a/arm9/source/timer.h b/arm9/source/timer.h index d15ed45..0961412 100644 --- a/arm9/source/timer.h +++ b/arm9/source/timer.h @@ -1,32 +1,32 @@ -#pragma once - -#include "common.h" - -// https://www.3dbrew.org/wiki/TIMER_Registers - -#define N_TIMERS 4 -#define TIMER_FREQ 67027964 - -#define TIMER_VAL(n) (*(vu16*)(0x10003000 + 4*(n))) -#define TIMER_CNT(n) (*(u16*)(0x10003002 + 4*(n))) -#define TIMER_INTERRUPT(n) (8 + n) - -typedef enum { // timer will run at TIMER_FREQ / one of these - FREQ_1, - FREQ_64, - FREQ_256, - FREQ_1024, -} TimerPrescaler; - -#define TIMER_COUNT_UP 0x0004 -#define TIMER_ENABLE_IRQ 0x0040 -#define TIMER_ACTIVE 0x0080 - -static inline void resetTimer(int n) { - TIMER_CNT(n) = 0; - TIMER_VAL(n) = 0; -} - -void resetAllTimers(); -void startFullTimerCountup(TimerPrescaler prescaler); +#pragma once + +#include "common.h" + +// https://www.3dbrew.org/wiki/TIMER_Registers + +#define N_TIMERS 4 +#define TIMER_FREQ 67027964 + +#define TIMER_VAL(n) (*(vu16*)(0x10003000 + 4*(n))) +#define TIMER_CNT(n) (*(u16*)(0x10003002 + 4*(n))) +#define TIMER_INTERRUPT(n) (8 + n) + +typedef enum { // timer will run at TIMER_FREQ / one of these + FREQ_1, + FREQ_64, + FREQ_256, + FREQ_1024, +} TimerPrescaler; + +#define TIMER_COUNT_UP 0x0004 +#define TIMER_ENABLE_IRQ 0x0040 +#define TIMER_ACTIVE 0x0080 + +static inline void resetTimer(int n) { + TIMER_CNT(n) = 0; + TIMER_VAL(n) = 0; +} + +void resetAllTimers(); +void startFullTimerCountup(TimerPrescaler prescaler); u64 getFullTimerTicks(); \ No newline at end of file diff --git a/common/bfn.S b/common/bfn.S index fa8063c..888e817 100644 --- a/common/bfn.S +++ b/common/bfn.S @@ -1,64 +1,64 @@ -#include "common.h" - -.section .bootrom - -#ifdef ARM9 // .bootrom linked at 0xFFFF0000 - -.org 0x0198; asm_func bfnWaitCycles -.org 0x01A4; asm_func bfnWFI -.org 0x03A4; asm_func bfnMemset32 -.org 0x03F0; asm_func bfnMemcpy32 -.org 0x056C; asm_func bfnMemset -.org 0x05E0; asm_func bfnMemcpy -.org 0x06EC; asm_func bfnEnterCriticalSection -.org 0x0700; asm_func bfnLeaveCriticalSection -.org 0x0798; asm_func bfnEnableDCache -.org 0x07B0; asm_func bfnDisableDCache -.org 0x07C8; asm_func bfnSetDCache -.org 0x07F0; asm_func bfnInvalidateDCache -.org 0x07FC; asm_func bfnWritebackDCache -.org 0x0830; asm_func bfnWritebackInvalidateDCache -.org 0x0868; asm_func bfnInvalidateDCacheRange -.org 0x0884; asm_func bfnWritebackDCacheRange -.org 0x08A8; asm_func bfnWritebackInvalidateDCacheRange -.org 0x096C; asm_func bfnDataSynchronizationBarrier -.org 0x0A5C; asm_func bfnEnableICache -.org 0x0A74; asm_func bfnDisableICache -.org 0x0A8C; asm_func bfnSetICache -.org 0x0AB4; asm_func bfnInvalidateICache -.org 0x0AC0; asm_func bfnInvalidateICacheRange -.org 0x0C38; asm_func bfnEnableMPU -.org 0x0C48; asm_func bfnDisableMPU -.org 0x0C58; asm_func bfnResetControlRegisters - -#else // ARM11; .bootrom linked at 0x10000 - -.org 0x1288; asm_func bfnEnableDCache -.org 0x12A0; asm_func bfnDisableDCache -.org 0x12B8; asm_func bfnSetDCache -.org 0x12E0; asm_func bfnInvalidateDCache -.org 0x12EC; asm_func bfnWritebackDCache -.org 0x1320; asm_func bfnWritebackInvalidateDCache -.org 0x1358; asm_func bfnInvalidateDCacheRange -.org 0x1374; asm_func bfnWritebackDCacheRange -.org 0x1398; asm_func bfnWritebackInvalidateDCacheRange -.org 0x13C0; asm_func bfnDataSynchronizationBarrier -.org 0x13E8; asm_func bfnDataMemoryBarrier -.org 0x13F4; asm_func bfnEnableICache -.org 0x140C; asm_func bfnDisableICache -.org 0x1424; asm_func bfnSetICache -.org 0x144C; asm_func bfnInvalidateICache -.org 0x1458; asm_func bfnInvalidateICacheRange -.org 0x1490; asm_func bfnInstructionSynchronizationBarrier -.org 0x14E8; asm_func bfnInvalidateBranchTargetCache -.org 0x14F4; asm_func bfnInvalidateBranchTargetCacheRange -.org 0x16E4; asm_func bfnMemset32 -.org 0x1730; asm_func bfnMemcpy32 -.org 0x18AC; asm_func bfnMemset -.org 0x1920; asm_func bfnMemcpy -.org 0x1A38; asm_func bfnWaitCycles -.org 0x1AC4; asm_func bfnEnterCriticalSection -.org 0x1AD8; asm_func bfnLeaveCriticalSection -.org 0x28F8; .thumb_func; asm_func bfnVsnprintf - +#include "common.h" + +.section .bootrom + +#ifdef ARM9 // .bootrom linked at 0xFFFF0000 + +.org 0x0198; asm_func bfnWaitCycles +.org 0x01A4; asm_func bfnWFI +.org 0x03A4; asm_func bfnMemset32 +.org 0x03F0; asm_func bfnMemcpy32 +.org 0x056C; asm_func bfnMemset +.org 0x05E0; asm_func bfnMemcpy +.org 0x06EC; asm_func bfnEnterCriticalSection +.org 0x0700; asm_func bfnLeaveCriticalSection +.org 0x0798; asm_func bfnEnableDCache +.org 0x07B0; asm_func bfnDisableDCache +.org 0x07C8; asm_func bfnSetDCache +.org 0x07F0; asm_func bfnInvalidateDCache +.org 0x07FC; asm_func bfnWritebackDCache +.org 0x0830; asm_func bfnWritebackInvalidateDCache +.org 0x0868; asm_func bfnInvalidateDCacheRange +.org 0x0884; asm_func bfnWritebackDCacheRange +.org 0x08A8; asm_func bfnWritebackInvalidateDCacheRange +.org 0x096C; asm_func bfnDataSynchronizationBarrier +.org 0x0A5C; asm_func bfnEnableICache +.org 0x0A74; asm_func bfnDisableICache +.org 0x0A8C; asm_func bfnSetICache +.org 0x0AB4; asm_func bfnInvalidateICache +.org 0x0AC0; asm_func bfnInvalidateICacheRange +.org 0x0C38; asm_func bfnEnableMPU +.org 0x0C48; asm_func bfnDisableMPU +.org 0x0C58; asm_func bfnResetControlRegisters + +#else // ARM11; .bootrom linked at 0x10000 + +.org 0x1288; asm_func bfnEnableDCache +.org 0x12A0; asm_func bfnDisableDCache +.org 0x12B8; asm_func bfnSetDCache +.org 0x12E0; asm_func bfnInvalidateDCache +.org 0x12EC; asm_func bfnWritebackDCache +.org 0x1320; asm_func bfnWritebackInvalidateDCache +.org 0x1358; asm_func bfnInvalidateDCacheRange +.org 0x1374; asm_func bfnWritebackDCacheRange +.org 0x1398; asm_func bfnWritebackInvalidateDCacheRange +.org 0x13C0; asm_func bfnDataSynchronizationBarrier +.org 0x13E8; asm_func bfnDataMemoryBarrier +.org 0x13F4; asm_func bfnEnableICache +.org 0x140C; asm_func bfnDisableICache +.org 0x1424; asm_func bfnSetICache +.org 0x144C; asm_func bfnInvalidateICache +.org 0x1458; asm_func bfnInvalidateICacheRange +.org 0x1490; asm_func bfnInstructionSynchronizationBarrier +.org 0x14E8; asm_func bfnInvalidateBranchTargetCache +.org 0x14F4; asm_func bfnInvalidateBranchTargetCacheRange +.org 0x16E4; asm_func bfnMemset32 +.org 0x1730; asm_func bfnMemcpy32 +.org 0x18AC; asm_func bfnMemset +.org 0x1920; asm_func bfnMemcpy +.org 0x1A38; asm_func bfnWaitCycles +.org 0x1AC4; asm_func bfnEnterCriticalSection +.org 0x1AD8; asm_func bfnLeaveCriticalSection +.org 0x28F8; .thumb_func; asm_func bfnVsnprintf + #endif \ No newline at end of file diff --git a/common/font.h b/common/font.h index c3bcb1b..47cf418 100644 --- a/common/font.h +++ b/common/font.h @@ -1,43 +1,43 @@ -#pragma once - +#pragma once + #include "common.h" - -#define CHR_HEIGHT 10 -#define CHR_WIDTH 6 - -// Generated with an ugly python script; each u64 is a character's font data -static const u64 font[] = { - /*0x0, 0x7adce1ce1780, 0x7b3b7fb7f780, 0x873ef94000, 0x873e708000, 0x708db671c000, 0x708fbe708000, 0x31e300000, - 0xffffffce1cfffff, 0xc4a148c000, 0xfffff3b5eb73fff, 0x72289e128f00, 0x21c21c8a2700, 0x18e208a28600, 0xdb6924f24f00, 0x22a73672a200, - 0x8639e386080, 0x830e3ce30800, 0x21ca88a9c200, 0x480492492480, 0xa28a3caaaabc, 0x72242891228489c, 0x7df7c0000000, 0x3e21ca88a9c200, - 0x208208a9c200, 0x21ca88208200, 0x843e408000, 0x813e108000, 0x782082000000, 0x1287f852000, 0xfbe71c208000, 0x20871cfbe000,*/ - 0x0, 0x200208208200, 0x14514, 0x53e514f94000, 0x872aa1c2aa708, 0xcb2108426980, 0xb12a84292300, 0x8208, - 0x10204104104210, 0x4210410410204, 0x22a72a200, 0x823e208000, 0x10830c000000000, 0x3e000000, 0x618000000000, 0x82104208410820, - 0x7229aaca2700, 0xf8820828c200, 0xf84210822700, 0x722818822700, 0x410f92518400, 0x722820782f80, 0x72289e084600, 0x208210820f80, - 0x72289c8a2700, 0x31083c8a2700, 0x618018600000, 0x10830c00c300000, 0x810204210800, 0xf80f80000, 0x108420408100, 0x200210822700, - 0x702eaaea2700, 0x8a2fa2894200, 0x7a491c924780, 0x7220820a2700, 0x7a4924924780, 0xf8209e082f80, 0x8209e082f80, 0x7228ba0a2700, - 0x8a28be8a2880, 0x708208208700, 0x312490410e00, 0x892286292880, 0xf82082082080, 0x8a28aaab6880, 0x8a28b2aa6880, 0x7228a28a2700, - 0x8209e8a2780, 0xb12aa28a2700, 0x89229e8a2780, 0x72281c0a2700, 0x208208208f80, 0x7228a28a2880, 0x2148a28a2880, 0x8b6aaa8a2880, - 0x8a2508522880, 0x2082148a2880, 0xf82108420f80, 0x18208208208218, 0x820410208104082, 0xc20820820820c, 0x894200, 0x3e000000000000, - 0x10204, 0xf22f20700000, 0x6a68a6682080, 0x7220a2700000, 0xb328b2b20800, 0xf02fa2700000, 0x20821c208c00, 0x720b328b2b00000, - 0x8a28a2782080, 0x708208300200, 0x188208208300200, 0x89238a482080, 0x708208208300, 0xaaaaaa580000, 0x8a28a6680000, 0x7228a2700000, - 0x826a68a6680000, 0x820b328b2b00000, 0x820a6680000, 0x7a0702f00000, 0xc08208708200, 0xb328a2880000, 0x2148a2880000, 0x52aaaaa80000, - 0x894214880000, 0x720f228a2880000, 0xf84210f80000, 0x10208204208210, 0x8208200208208, 0x4208210208204, 0x10a84000000, 0xfa2894200000, - /*0x1087220820a2700, 0xb328a2880500, 0xf02fa2700210, 0xf22f20700508, 0xf22f20700500, 0xf22f20700408, 0xf22f20718918, 0x1087220a2700000, - 0xf02fa2700508, 0xf02fa2700500, 0xf02fa2700204, 0x708208300500, 0x708208300508, 0x708208300204, 0x8a2fa2894222, 0x8a2fa289c48c, - 0xf8209e082f88, 0xf0afa8780000, 0xe8a29e28af00, 0x7228a2700508, 0x7228a2700500, 0x7228a2700204, 0xb328a2880508, 0xb328a2880204, - 0x720f228a2880500, 0x7228a28a2721, 0x7228a28a2891, 0x872a2aa708000, 0x7a208238248c, 0x208f88f94880, 0x892e92392380, 0x18821c208c00, - 0xf22f20700210, 0x708208300210, 0x7228a2700210, 0xb328a2880210, 0x8a28a66806ac, 0x8a28b2aa689a, 0xf80f22f20700, 0xf807228a2700, - 0x722084200200, 0x20be000000, 0x2083e000000, 0x38422508524184, 0x10f1a508524184, 0x208208200200, 0x912252900000, 0x252912240000, - 0x888888888888888, 0xa95a95a95a95a95, 0xbbbbbbbbbbbbbbb, 0x208208208208208, 0x20820820f208208, 0x2082083c83c8208, 0x514514517514514, 0x51451451f000000, - 0x2082083c83c0000, 0x5145145d05d4514, 0x514514514514514, 0x5145145d07c0000, 0x7d05d4514, 0x1f514514, 0x3c83c8208, 0x20820820f000000, - 0x38208208, 0x3f208208, 0x20820823f000000, 0x208208238208208, 0x3f000000, 0x20820823f208208, 0x208208e08e08208, 0x514514534514514, - 0xf04d14514, 0x514514d04f00000, 0xfc0dd4514, 0x514514dc0fc0000, 0x514514d04d14514, 0xfc0fc0000, 0x514514dc0dd4514, 0xfc0fc8208, - 0x3f514514, 0x208208fc0fc0000, 0x51451453f000000, 0x3c514514, 0xe08e08208, 0x208208e08e00000, 0x51451453c000000, 0x51451453f514514, - 0x208208fc8fc8208, 0xf208208, 0x208208238000000, 0xfffffffffffffff, 0xfffffffc0000000, 0x1c71c71c71c71c7, 0xe38e38e38e38e38, 0x3fffffff, - 0xb12492b00000, 0x26a28924a2918, 0x820828a2f80, 0x514514f80000, 0xfa4210224f80, 0x312492f00000, 0x82b92492480000, 0xc08208f80000, - 0x70872289c21c, 0x7228be8a2700, 0xd948a28a2700, 0x624924604600, 0x72aaaa700000, 0x9caaa720000, 0xf0209c082f00, 0x8a28a28a2700, - 0x3f03f03f000, 0xf80208f88200, 0x700108408100, 0x700408108400, 0x208208208208c00, 0x6208208208208, 0x803e008000, 0x42a110a84000, - 0x31248c, 0x21c200000, 0x8000000, 0x10428a410800, 0x28a286, 0x384206, 0x71c71c71c000, 0x0,*/ +#define CHR_HEIGHT 10 +#define CHR_WIDTH 6 + +// Generated with an ugly python script; each u64 is a character's font data + +static const u64 font[] = { + /*0x0, 0x7adce1ce1780, 0x7b3b7fb7f780, 0x873ef94000, 0x873e708000, 0x708db671c000, 0x708fbe708000, 0x31e300000, + 0xffffffce1cfffff, 0xc4a148c000, 0xfffff3b5eb73fff, 0x72289e128f00, 0x21c21c8a2700, 0x18e208a28600, 0xdb6924f24f00, 0x22a73672a200, + 0x8639e386080, 0x830e3ce30800, 0x21ca88a9c200, 0x480492492480, 0xa28a3caaaabc, 0x72242891228489c, 0x7df7c0000000, 0x3e21ca88a9c200, + 0x208208a9c200, 0x21ca88208200, 0x843e408000, 0x813e108000, 0x782082000000, 0x1287f852000, 0xfbe71c208000, 0x20871cfbe000,*/ + 0x0, 0x200208208200, 0x14514, 0x53e514f94000, 0x872aa1c2aa708, 0xcb2108426980, 0xb12a84292300, 0x8208, + 0x10204104104210, 0x4210410410204, 0x22a72a200, 0x823e208000, 0x10830c000000000, 0x3e000000, 0x618000000000, 0x82104208410820, + 0x7229aaca2700, 0xf8820828c200, 0xf84210822700, 0x722818822700, 0x410f92518400, 0x722820782f80, 0x72289e084600, 0x208210820f80, + 0x72289c8a2700, 0x31083c8a2700, 0x618018600000, 0x10830c00c300000, 0x810204210800, 0xf80f80000, 0x108420408100, 0x200210822700, + 0x702eaaea2700, 0x8a2fa2894200, 0x7a491c924780, 0x7220820a2700, 0x7a4924924780, 0xf8209e082f80, 0x8209e082f80, 0x7228ba0a2700, + 0x8a28be8a2880, 0x708208208700, 0x312490410e00, 0x892286292880, 0xf82082082080, 0x8a28aaab6880, 0x8a28b2aa6880, 0x7228a28a2700, + 0x8209e8a2780, 0xb12aa28a2700, 0x89229e8a2780, 0x72281c0a2700, 0x208208208f80, 0x7228a28a2880, 0x2148a28a2880, 0x8b6aaa8a2880, + 0x8a2508522880, 0x2082148a2880, 0xf82108420f80, 0x18208208208218, 0x820410208104082, 0xc20820820820c, 0x894200, 0x3e000000000000, + 0x10204, 0xf22f20700000, 0x6a68a6682080, 0x7220a2700000, 0xb328b2b20800, 0xf02fa2700000, 0x20821c208c00, 0x720b328b2b00000, + 0x8a28a2782080, 0x708208300200, 0x188208208300200, 0x89238a482080, 0x708208208300, 0xaaaaaa580000, 0x8a28a6680000, 0x7228a2700000, + 0x826a68a6680000, 0x820b328b2b00000, 0x820a6680000, 0x7a0702f00000, 0xc08208708200, 0xb328a2880000, 0x2148a2880000, 0x52aaaaa80000, + 0x894214880000, 0x720f228a2880000, 0xf84210f80000, 0x10208204208210, 0x8208200208208, 0x4208210208204, 0x10a84000000, 0xfa2894200000, + /*0x1087220820a2700, 0xb328a2880500, 0xf02fa2700210, 0xf22f20700508, 0xf22f20700500, 0xf22f20700408, 0xf22f20718918, 0x1087220a2700000, + 0xf02fa2700508, 0xf02fa2700500, 0xf02fa2700204, 0x708208300500, 0x708208300508, 0x708208300204, 0x8a2fa2894222, 0x8a2fa289c48c, + 0xf8209e082f88, 0xf0afa8780000, 0xe8a29e28af00, 0x7228a2700508, 0x7228a2700500, 0x7228a2700204, 0xb328a2880508, 0xb328a2880204, + 0x720f228a2880500, 0x7228a28a2721, 0x7228a28a2891, 0x872a2aa708000, 0x7a208238248c, 0x208f88f94880, 0x892e92392380, 0x18821c208c00, + 0xf22f20700210, 0x708208300210, 0x7228a2700210, 0xb328a2880210, 0x8a28a66806ac, 0x8a28b2aa689a, 0xf80f22f20700, 0xf807228a2700, + 0x722084200200, 0x20be000000, 0x2083e000000, 0x38422508524184, 0x10f1a508524184, 0x208208200200, 0x912252900000, 0x252912240000, + 0x888888888888888, 0xa95a95a95a95a95, 0xbbbbbbbbbbbbbbb, 0x208208208208208, 0x20820820f208208, 0x2082083c83c8208, 0x514514517514514, 0x51451451f000000, + 0x2082083c83c0000, 0x5145145d05d4514, 0x514514514514514, 0x5145145d07c0000, 0x7d05d4514, 0x1f514514, 0x3c83c8208, 0x20820820f000000, + 0x38208208, 0x3f208208, 0x20820823f000000, 0x208208238208208, 0x3f000000, 0x20820823f208208, 0x208208e08e08208, 0x514514534514514, + 0xf04d14514, 0x514514d04f00000, 0xfc0dd4514, 0x514514dc0fc0000, 0x514514d04d14514, 0xfc0fc0000, 0x514514dc0dd4514, 0xfc0fc8208, + 0x3f514514, 0x208208fc0fc0000, 0x51451453f000000, 0x3c514514, 0xe08e08208, 0x208208e08e00000, 0x51451453c000000, 0x51451453f514514, + 0x208208fc8fc8208, 0xf208208, 0x208208238000000, 0xfffffffffffffff, 0xfffffffc0000000, 0x1c71c71c71c71c7, 0xe38e38e38e38e38, 0x3fffffff, + 0xb12492b00000, 0x26a28924a2918, 0x820828a2f80, 0x514514f80000, 0xfa4210224f80, 0x312492f00000, 0x82b92492480000, 0xc08208f80000, + 0x70872289c21c, 0x7228be8a2700, 0xd948a28a2700, 0x624924604600, 0x72aaaa700000, 0x9caaa720000, 0xf0209c082f00, 0x8a28a28a2700, + 0x3f03f03f000, 0xf80208f88200, 0x700108408100, 0x700408108400, 0x208208208208c00, 0x6208208208208, 0x803e008000, 0x42a110a84000, + 0x31248c, 0x21c200000, 0x8000000, 0x10428a410800, 0x28a286, 0x384206, 0x71c71c71c000, 0x0,*/ }; \ No newline at end of file diff --git a/common/memtests.c b/common/memtests.c index 226be81..18199df 100644 --- a/common/memtests.c +++ b/common/memtests.c @@ -1,186 +1,186 @@ -#include "memtests.h" - -#include "pxi.h" -#include "arm.h" - -#ifdef ARM9 -#include -#include -#else -#include -#include - -// TODO: use the mpcore timer stuff for this on ARM11 -// ... and find a nice way to not have totally different bit fade code on ARM9 -#define getFullTimerTicks pxiGetTimerTicks - -#endif //ARM9 - -#include - -extern MemtestError errors_buffer[MAX_ERRORS]; - -u32 memtest_walking_ones(u32 start_addr, u32 end_addr); -u32 memtest_own_address(u32 start_addr, u32 end_addr); -u32 memtest_moving_inversions_ones_zeros(u32 start_addr, u32 end_addr); -u32 memtest_moving_inversions_8bit_walking(u32 start_addr, u32 end_addr); -u32 memtest_bit_fade_check(u32 start_addr, u32 end_addr, u32 pattern); - -const MemestRegionInfo memtestRegions[] = { - { ARM9MEM_BASE, ARM9MEM_SIZE, "ARM9 Internal Memory" }, - { NEW_ARM9MEM_BASE, NEW_ARM9MEM_SIZE, "New3DS Extended ARM9 Memory" }, - { DSPMEM_BASE, DSPMEM_SIZE, "DSP Memory" }, - { AXIWRAM_BASE, AXIWRAM_SIZE, "AXI Work RAM" }, - { FCRAM_BASE, FCRAM_SIZE, "FCRAM" }, - { NEW_FCRAM_BASE, NEW_FCRAM_SIZE, "New3DS Extended FCRAM" }, -}; - -const MemtestInfo memtests[] = { - { memtest_walking_ones, "Walking Ones Test" }, - { memtest_own_address, "Own Address Test" }, - { memtest_moving_inversions_ones_zeros, "Moving Inversions Test, Ones & Zeros" }, - { memtest_moving_inversions_8bit_walking, "Moving inversions Test, 8 Bit Patterns" }, - { NULL, "Bit Fade Test" }, -}; - -_Static_assert(N_MEMTEST_REGIONS == countof(memtestRegions)); -_Static_assert(N_MEMTESTS == countof(memtests)); - -#ifndef ARM9 -static u64 __attribute__((section(".shared"))) errorsFromArm9; -#endif - -static u64 totalErrors = 0; -static u64 bitFadeTimers[N_MEMTEST_REGIONS] = { 0 }; - -static void logErrors(u32 nErrors) { - for (u32 i = 0; i < min(nErrors, MAX_ERRORS); i++) { - MemtestError* e = errors_buffer + i; - logDebugPrintf(true, "%lx: %lx -> %lx\n", e->address, e->original, e->observed); - } -} - -static bool checkBitFade(u32 maxRegion) { - bool ret = false; - - for (u32 regionIndex = 0; regionIndex < maxRegion; regionIndex++) { - u64 timer = bitFadeTimers[regionIndex]; - if (timer != 0) { - if (timer < getFullTimerTicks()) { - const u32 startAddr = memtestRegions[regionIndex].base, - size = memtestRegions[regionIndex].size, - endAddr = startAddr + size, - pattern = (timer & 1) ? 0 : ~0; - - debugPrintf("Processing bit fade pattern %lx for %s...\n", pattern, memtestRegions[regionIndex].name); - - u32 nErrors = memtest_bit_fade_check(startAddr, endAddr, pattern); - - if (nErrors) { - logErrors(nErrors); - totalErrors += nErrors; - } - - if (pattern == 0) { - bfnMemset32(~0, (u32*) startAddr, size); - bitFadeTimers[regionIndex] = (getFullTimerTicks() + BIT_FADE_DELAY) & ~1ULL; - ret = true; - } else { - bitFadeTimers[regionIndex] = 0; - } - } else { - ret = true; - } - } - } - - return ret; -} - -u64 testMemory(u32 regions, u32 tests, bool showFinal) { - totalErrors = 0; - - #ifndef ARM9 - bool watingForArm9 = false; - - // If we have any ARM9-only regions, tell ARM9 to test them - if (regions & MEMTEST_REGIONS_ARM9_ONLY) { - errorsFromArm9 = ~0ULL; - - PXI_Send((3 << 16) | PXICMD_RUN_MEMTEST); - PXI_Send((u32) &errorsFromArm9); - PXI_Send(regions & MEMTEST_REGIONS_ARM9_ONLY); - PXI_Send(tests); - - watingForArm9 = true; - regions &= ~MEMTEST_REGIONS_ARM9_ONLY; - } - #endif - - for (u32 regionIndex = 0; regionIndex < N_MEMTEST_REGIONS; regionIndex++) { - if (!(regions & BIT(regionIndex))) - continue; - - if (IS_O3DS && (BIT(regionIndex) & MEMTEST_REGIONS_NEW3DS_ONLY)) { - // TODO UI - debugPrintf("Skipping %s\n", memtestRegions[regionIndex].name); - - continue; - } - - // TODO: proper UI stuff - debugPrintf("Testing %s ...\n", memtestRegions[regionIndex].name); - - const u32 startAddr = memtestRegions[regionIndex].base, - size = memtestRegions[regionIndex].size, - endAddr = startAddr + size; - - for (u32 testIndex = 0; testIndex < N_MEMTESTS; testIndex++) { - if (!(tests & BIT(testIndex))) - continue; - - // Check bit fade timers on previous regions - checkBitFade(regionIndex); - - if (testIndex == MEMTEST_BIT_FADE) { - debugPrintf("Setting up %s...\n", memtests[MEMTEST_BIT_FADE].name); - bfnMemset32(0, (u32*) startAddr, size); - bitFadeTimers[regionIndex] = (getFullTimerTicks() + BIT_FADE_DELAY) | 1ULL; - break; - } - - // TODO UI - debugPrintf("Running %s...\n", memtests[testIndex].name); - - // TODO split this up to expose pattern etc - u32 nErrors = memtests[testIndex].func(startAddr, endAddr); - - if (nErrors) { - logErrors(nErrors); - totalErrors += nErrors; - } - } - - debugPrint("\n"); - } - - debugPrint("Waiting on remaining bit fades to finish ...\n"); - while (checkBitFade(N_MEMTEST_REGIONS)) - ARM_WFI(); - - #ifndef ARM9 - if (watingForArm9) { - debugPrint("Waiting on ARM9-side tests to finish ...\n"); - while (errorsFromArm9 == ~0ULL) - ARM_WFI(); - - totalErrors += errorsFromArm9; - watingForArm9 = false; - } - #endif - - if (showFinal) - debugPrintf("Done. %llu total errors detected.\n", totalErrors); - - return totalErrors; +#include "memtests.h" + +#include "pxi.h" +#include "arm.h" + +#ifdef ARM9 +#include +#include +#else +#include +#include + +// TODO: use the mpcore timer stuff for this on ARM11 +// ... and find a nice way to not have totally different bit fade code on ARM9 +#define getFullTimerTicks pxiGetTimerTicks + +#endif //ARM9 + +#include + +extern MemtestError errors_buffer[MAX_ERRORS]; + +u32 memtest_walking_ones(u32 start_addr, u32 end_addr); +u32 memtest_own_address(u32 start_addr, u32 end_addr); +u32 memtest_moving_inversions_ones_zeros(u32 start_addr, u32 end_addr); +u32 memtest_moving_inversions_8bit_walking(u32 start_addr, u32 end_addr); +u32 memtest_bit_fade_check(u32 start_addr, u32 end_addr, u32 pattern); + +const MemestRegionInfo memtestRegions[] = { + { ARM9MEM_BASE, ARM9MEM_SIZE, "ARM9 Internal Memory" }, + { NEW_ARM9MEM_BASE, NEW_ARM9MEM_SIZE, "New3DS Extended ARM9 Memory" }, + { DSPMEM_BASE, DSPMEM_SIZE, "DSP Memory" }, + { AXIWRAM_BASE, AXIWRAM_SIZE, "AXI Work RAM" }, + { FCRAM_BASE, FCRAM_SIZE, "FCRAM" }, + { NEW_FCRAM_BASE, NEW_FCRAM_SIZE, "New3DS Extended FCRAM" }, +}; + +const MemtestInfo memtests[] = { + { memtest_walking_ones, "Walking Ones Test" }, + { memtest_own_address, "Own Address Test" }, + { memtest_moving_inversions_ones_zeros, "Moving Inversions Test, Ones & Zeros" }, + { memtest_moving_inversions_8bit_walking, "Moving inversions Test, 8 Bit Patterns" }, + { NULL, "Bit Fade Test" }, +}; + +_Static_assert(N_MEMTEST_REGIONS == countof(memtestRegions)); +_Static_assert(N_MEMTESTS == countof(memtests)); + +#ifndef ARM9 +static u64 __attribute__((section(".shared"))) errorsFromArm9; +#endif + +static u64 totalErrors = 0; +static u64 bitFadeTimers[N_MEMTEST_REGIONS] = { 0 }; + +static void logErrors(u32 nErrors) { + for (u32 i = 0; i < min(nErrors, MAX_ERRORS); i++) { + MemtestError* e = errors_buffer + i; + logDebugPrintf(true, "%lx: %lx -> %lx\n", e->address, e->original, e->observed); + } +} + +static bool checkBitFade(u32 maxRegion) { + bool ret = false; + + for (u32 regionIndex = 0; regionIndex < maxRegion; regionIndex++) { + u64 timer = bitFadeTimers[regionIndex]; + if (timer != 0) { + if (timer < getFullTimerTicks()) { + const u32 startAddr = memtestRegions[regionIndex].base, + size = memtestRegions[regionIndex].size, + endAddr = startAddr + size, + pattern = (timer & 1) ? 0 : ~0; + + debugPrintf("Processing bit fade pattern %lx for %s...\n", pattern, memtestRegions[regionIndex].name); + + u32 nErrors = memtest_bit_fade_check(startAddr, endAddr, pattern); + + if (nErrors) { + logErrors(nErrors); + totalErrors += nErrors; + } + + if (pattern == 0) { + bfnMemset32(~0, (u32*) startAddr, size); + bitFadeTimers[regionIndex] = (getFullTimerTicks() + BIT_FADE_DELAY) & ~1ULL; + ret = true; + } else { + bitFadeTimers[regionIndex] = 0; + } + } else { + ret = true; + } + } + } + + return ret; +} + +u64 testMemory(u32 regions, u32 tests, bool showFinal) { + totalErrors = 0; + + #ifndef ARM9 + bool watingForArm9 = false; + + // If we have any ARM9-only regions, tell ARM9 to test them + if (regions & MEMTEST_REGIONS_ARM9_ONLY) { + errorsFromArm9 = ~0ULL; + + PXI_Send((3 << 16) | PXICMD_RUN_MEMTEST); + PXI_Send((u32) &errorsFromArm9); + PXI_Send(regions & MEMTEST_REGIONS_ARM9_ONLY); + PXI_Send(tests); + + watingForArm9 = true; + regions &= ~MEMTEST_REGIONS_ARM9_ONLY; + } + #endif + + for (u32 regionIndex = 0; regionIndex < N_MEMTEST_REGIONS; regionIndex++) { + if (!(regions & BIT(regionIndex))) + continue; + + if (IS_O3DS && (BIT(regionIndex) & MEMTEST_REGIONS_NEW3DS_ONLY)) { + // TODO UI + debugPrintf("Skipping %s\n", memtestRegions[regionIndex].name); + + continue; + } + + // TODO: proper UI stuff + debugPrintf("Testing %s ...\n", memtestRegions[regionIndex].name); + + const u32 startAddr = memtestRegions[regionIndex].base, + size = memtestRegions[regionIndex].size, + endAddr = startAddr + size; + + for (u32 testIndex = 0; testIndex < N_MEMTESTS; testIndex++) { + if (!(tests & BIT(testIndex))) + continue; + + // Check bit fade timers on previous regions + checkBitFade(regionIndex); + + if (testIndex == MEMTEST_BIT_FADE) { + debugPrintf("Setting up %s...\n", memtests[MEMTEST_BIT_FADE].name); + bfnMemset32(0, (u32*) startAddr, size); + bitFadeTimers[regionIndex] = (getFullTimerTicks() + BIT_FADE_DELAY) | 1ULL; + break; + } + + // TODO UI + debugPrintf("Running %s...\n", memtests[testIndex].name); + + // TODO split this up to expose pattern etc + u32 nErrors = memtests[testIndex].func(startAddr, endAddr); + + if (nErrors) { + logErrors(nErrors); + totalErrors += nErrors; + } + } + + debugPrint("\n"); + } + + debugPrint("Waiting on remaining bit fades to finish ...\n"); + while (checkBitFade(N_MEMTEST_REGIONS)) + ARM_WFI(); + + #ifndef ARM9 + if (watingForArm9) { + debugPrint("Waiting on ARM9-side tests to finish ...\n"); + while (errorsFromArm9 == ~0ULL) + ARM_WFI(); + + totalErrors += errorsFromArm9; + watingForArm9 = false; + } + #endif + + if (showFinal) + debugPrintf("Done. %llu total errors detected.\n", totalErrors); + + return totalErrors; } \ No newline at end of file diff --git a/common/memtests.h b/common/memtests.h index d94dca7..90af52a 100644 --- a/common/memtests.h +++ b/common/memtests.h @@ -1,70 +1,70 @@ -#pragma once - -#include "common.h" - -// Must have enough space in BSS to store MAX_ERRORS * ERROR_STRUCT_SIZE (struct defined below) -#define MAX_ERRORS 128 -#define ERROR_STRUCT_SIZE 12 - -// 3 minutes -#define BIT_FADE_DELAY (3ULL * 60ULL * (67027964ULL / 1024ULL)) - -#ifndef __ASSEMBLER__ - -enum { - MEMTEST_REGION_ARM9MEM = 0, - MEMTEST_REGION_NEW_ARM9MEM, - MEMTEST_REGION_DSPMEM, - MEMTEST_REGION_AXIWRAM, - MEMTEST_REGION_FCRAM, - MEMTEST_REGION_NEW_FCRAM, - - N_MEMTEST_REGIONS -}; - -enum { - MEMTEST_WALKING_ONES = 0, - MEMTEST_OWN_ADDRESS, - MEMTEST_MOV_INV_1_0, - MEMTEST_MOV_INV_8_BIT, - MEMTEST_BIT_FADE, - - N_MEMTESTS -}; - -// Bit fade must be done last for each region so other regions may begin testing while waiting -_Static_assert(MEMTEST_BIT_FADE + 1 == N_MEMTESTS); - -typedef struct { - u32 base; - u32 size; - const char* name; -} MemestRegionInfo; - -typedef struct { - u32 (*func)(u32, u32); - const char* name; -} MemtestInfo; - -extern const MemestRegionInfo memtestRegions[]; -extern const char* memtestNames[]; - -#define ALL_MEMTEST_REGIONS (BIT(N_MEMTEST_REGIONS) - 1) -#define ALL_MEMTESTS (BIT(N_MEMTESTS) - 1) - -#define MEMTEST_REGIONS_NEW3DS_ONLY \ - (BIT(MEMTEST_REGION_NEW_ARM9MEM) | BIT(MEMTEST_REGION_NEW_FCRAM)) -#define MEMTEST_REGIONS_ARM9_ONLY \ - (BIT(MEMTEST_REGION_ARM9MEM) | BIT(MEMTEST_REGION_NEW_ARM9MEM)) - -typedef struct { - u32 address; - u32 original; - u32 observed; -} PACKED_STRUCT MemtestError; -_Static_assert(ERROR_STRUCT_SIZE == sizeof(MemtestError)); - -// Returns total errors detected -u64 testMemory(u32 regions, u32 tests, bool showFinal); - -#endif //__ASSEMBLER__ +#pragma once + +#include "common.h" + +// Must have enough space in BSS to store MAX_ERRORS * ERROR_STRUCT_SIZE (struct defined below) +#define MAX_ERRORS 128 +#define ERROR_STRUCT_SIZE 12 + +// 3 minutes +#define BIT_FADE_DELAY (3ULL * 60ULL * (67027964ULL / 1024ULL)) + +#ifndef __ASSEMBLER__ + +enum { + MEMTEST_REGION_ARM9MEM = 0, + MEMTEST_REGION_NEW_ARM9MEM, + MEMTEST_REGION_DSPMEM, + MEMTEST_REGION_AXIWRAM, + MEMTEST_REGION_FCRAM, + MEMTEST_REGION_NEW_FCRAM, + + N_MEMTEST_REGIONS +}; + +enum { + MEMTEST_WALKING_ONES = 0, + MEMTEST_OWN_ADDRESS, + MEMTEST_MOV_INV_1_0, + MEMTEST_MOV_INV_8_BIT, + MEMTEST_BIT_FADE, + + N_MEMTESTS +}; + +// Bit fade must be done last for each region so other regions may begin testing while waiting +_Static_assert(MEMTEST_BIT_FADE + 1 == N_MEMTESTS); + +typedef struct { + u32 base; + u32 size; + const char* name; +} MemestRegionInfo; + +typedef struct { + u32 (*func)(u32, u32); + const char* name; +} MemtestInfo; + +extern const MemestRegionInfo memtestRegions[]; +extern const char* memtestNames[]; + +#define ALL_MEMTEST_REGIONS (BIT(N_MEMTEST_REGIONS) - 1) +#define ALL_MEMTESTS (BIT(N_MEMTESTS) - 1) + +#define MEMTEST_REGIONS_NEW3DS_ONLY \ + (BIT(MEMTEST_REGION_NEW_ARM9MEM) | BIT(MEMTEST_REGION_NEW_FCRAM)) +#define MEMTEST_REGIONS_ARM9_ONLY \ + (BIT(MEMTEST_REGION_ARM9MEM) | BIT(MEMTEST_REGION_NEW_ARM9MEM)) + +typedef struct { + u32 address; + u32 original; + u32 observed; +} PACKED_STRUCT MemtestError; +_Static_assert(ERROR_STRUCT_SIZE == sizeof(MemtestError)); + +// Returns total errors detected +u64 testMemory(u32 regions, u32 tests, bool showFinal); + +#endif //__ASSEMBLER__ diff --git a/common/screen.h b/common/screen.h index 14b790f..b39c226 100644 --- a/common/screen.h +++ b/common/screen.h @@ -1,36 +1,36 @@ -#pragma once - -#include - -#define BYTES_PER_PIXEL 2 -#define SCREEN_HEIGHT 240 -#define SCREEN_WIDTH_TOP 400 -#define SCREEN_WIDTH_BOT 320 - -_Static_assert(TOP_VRAM == SCREEN_HEIGHT * SCREEN_WIDTH_TOP * BYTES_PER_PIXEL); - -#define TOP_SCREEN ((u16*) VRAM_TOP_LA) -#define BOT_SCREEN ((u16*) VRAM_BOT_A) - -#ifdef ARM9 -#define MAIN_SCREEN BOT_SCREEN -#define MAIN_SCREEN_WIDTH SCREEN_WIDTH_BOT -#else -#define MAIN_SCREEN TOP_SCREEN -#define MAIN_SCREEN_WIDTH SCREEN_WIDTH_TOP -#endif - -#define RGB(r,g,b) ((u16)(r>>3<<11|g>>2<<5|b>>3)) // converts from 888 to 565 - -#define COLOR_BLACK RGB(0x00, 0x00, 0x00) -#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF) -#define COLOR_RED RGB(0xFF, 0x00, 0x00) -#define COLOR_GREEN RGB(0x00, 0xFF, 0x00) -#define COLOR_BLUE RGB(0x00, 0x00, 0xFF) -#define COLOR_LIGHT_BLUE RGB(0x00, 0xA0, 0xE8) -#define COLOR_CYAN RGB(0x00, 0xFF, 0xFF) -#define COLOR_MAGENTA RGB(0xFF, 0x00, 0xFF) -#define COLOR_YELLOW RGB(0xFF, 0xFF, 0x00) -#define COLOR_GREY RGB(0x77, 0x77, 0x77) -#define COLOR_LIGHT_GREY RGB(0xBB, 0xBB, 0xBB) +#pragma once + +#include + +#define BYTES_PER_PIXEL 2 +#define SCREEN_HEIGHT 240 +#define SCREEN_WIDTH_TOP 400 +#define SCREEN_WIDTH_BOT 320 + +_Static_assert(TOP_VRAM == SCREEN_HEIGHT * SCREEN_WIDTH_TOP * BYTES_PER_PIXEL); + +#define TOP_SCREEN ((u16*) VRAM_TOP_LA) +#define BOT_SCREEN ((u16*) VRAM_BOT_A) + +#ifdef ARM9 +#define MAIN_SCREEN BOT_SCREEN +#define MAIN_SCREEN_WIDTH SCREEN_WIDTH_BOT +#else +#define MAIN_SCREEN TOP_SCREEN +#define MAIN_SCREEN_WIDTH SCREEN_WIDTH_TOP +#endif + +#define RGB(r,g,b) ((u16)(r>>3<<11|g>>2<<5|b>>3)) // converts from 888 to 565 + +#define COLOR_BLACK RGB(0x00, 0x00, 0x00) +#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF) +#define COLOR_RED RGB(0xFF, 0x00, 0x00) +#define COLOR_GREEN RGB(0x00, 0xFF, 0x00) +#define COLOR_BLUE RGB(0x00, 0x00, 0xFF) +#define COLOR_LIGHT_BLUE RGB(0x00, 0xA0, 0xE8) +#define COLOR_CYAN RGB(0x00, 0xFF, 0xFF) +#define COLOR_MAGENTA RGB(0xFF, 0x00, 0xFF) +#define COLOR_YELLOW RGB(0xFF, 0xFF, 0x00) +#define COLOR_GREY RGB(0x77, 0x77, 0x77) +#define COLOR_LIGHT_GREY RGB(0xBB, 0xBB, 0xBB) //#define COLOR_TRANSPARENT RGB(0xFF, 0x00, 0xEF) // otherwise known as 'super fuchsia' \ No newline at end of file