diff --git a/arm11/source/main.c b/arm11/source/main.c index 99923892..e3904b25 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -195,6 +195,28 @@ static void deinitScreens(void) *(vu32 *)0x10202014 = 0; } +static void zerofillN3dsAblRegisters(void) +{ + // It should be fine to write to these regs even on O3DS as they + // are RAZ/WI + + // TODO: read from calibration, but null values should do just + // fine. From testing, LUT explicitly ignores null values, and + // it is probably the case of reg @ 0x54 as well. + *(vu32 *)0x10202250 = 0; // unknown 24-bit value, seen: 0 + *(vu32 *)0x10202254 = 0; // unknown 24-bit value, seen: nonzero + + *(vu32 *)0x10202A50 = 0; // unknown 24-bit value, seen: 0 + *(vu32 *)0x10202A54 = 0; // unknown 24-bit value, seen: nonzero + + for (u32 i = 0; i < 64; i++) { + // Blend colors (w/ color multiplication) for each group + // of 4 relative-luminance Rs + *(vu32 *)(0x10202300 + 4*i) = 0; + *(vu32 *)(0x10202B00 + 4*i) = 0; + } +} + void main(void) { operation = ARM11_READY; @@ -223,6 +245,9 @@ void main(void) case DEINIT_SCREENS: deinitScreens(); break; + case ZEROFILL_N3DS_ABL_REGISTERS: + zerofillN3dsAblRegisters(); + break; case PREPARE_ARM11_FOR_FIRMLAUNCH: memcpy((void *)0x1FFFFC00, (void *)prepareForFirmlaunch, prepareForFirmlaunchSize); *(vu32 *)0x1FFFFFFC = 0; diff --git a/arm11/source/types.h b/arm11/source/types.h index 43eacc92..551b7d93 100644 --- a/arm11/source/types.h +++ b/arm11/source/types.h @@ -60,6 +60,7 @@ typedef enum SWAP_FRAMEBUFFERS, UPDATE_BRIGHTNESS, DEINIT_SCREENS, + ZEROFILL_N3DS_ABL_REGISTERS, PREPARE_ARM11_FOR_FIRMLAUNCH, ARM11_READY, } Arm11Operation; diff --git a/arm9/source/deliver_arg.c b/arm9/source/deliver_arg.c index 0ef1a596..d360e616 100644 --- a/arm9/source/deliver_arg.c +++ b/arm9/source/deliver_arg.c @@ -30,6 +30,7 @@ #include "config.h" #include "fs.h" #include "i2c.h" +#include "screen.h" u8 *loadDeliverArg(void) { @@ -200,6 +201,29 @@ static bool configureHomebrewAutobootTwl(u8 *deliverArg) *(u16 *)(tlnc + 6) = crc16(tlnc + 8, 0x18, 0xFFFF); + // Even though (when running TWL/AGB FIRM) the SoC is in O3DS mode, and the GPU also is, + // as well as most other components behaving as such (external RAM, L2C not usable, etc.), + // this is NOT the case for the LCD and adaptive backlight logic which retains FULL N3DS + // functionality, including a feature where the window is blended with a given color depending + // on the overall relative luminance of that window. + + // However, Nintendo's own code mistakenly assumes the opposite, and clearly so ("if GPU in N3DS mode" + // checks, not passing N3DS extra adaptive backlight (ABL) to TWL/AGB_FIRM). This has implications: + + // - Powersaving (ABL) settings in TWL/AGB_FIRM is inconsistent with *both* O3DS (because the new RGB blend LUT + // has been set to its current value by NATIVE_FIRM) and N3DS (because "pwn_cnt" and "inertia" are missing + // their N3DS-only bits) + // - "rave party" when booting into TWL/AGB_FIRM or O3DS NATIVE_FIRM without these regs (well, the LUT) initialized. + // Easiest way to do so is by leveraging the "DSi autooboot" feature Luma provides. It is worth noting at least + // the LUT survives hardware reboots (if Nintendo were using DSi software that was using TLNC-based reboots, + // they wouldn't have noticed). + + // As such, zerofill these registers (from testing, hardware explicitly discards null values, so this + // should be fine). For now, only touch the Luma-initiated autoboot path + + if (ISN3DS) + zerofillN3dsAblRegisters(); + CFG_BOOTENV = 3; return true; diff --git a/arm9/source/screen.c b/arm9/source/screen.c index bb01525b..e82475d5 100644 --- a/arm9/source/screen.c +++ b/arm9/source/screen.c @@ -118,3 +118,8 @@ void initScreens(void) clearScreens(false); swapFramebuffers(false); } + +void zerofillN3dsAblRegisters(void) +{ + invokeArm11Function(ZEROFILL_N3DS_ABL_REGISTERS); +} \ No newline at end of file diff --git a/arm9/source/screen.h b/arm9/source/screen.h index 275ed686..01b21d1e 100644 --- a/arm9/source/screen.h +++ b/arm9/source/screen.h @@ -59,6 +59,7 @@ typedef enum SWAP_FRAMEBUFFERS, UPDATE_BRIGHTNESS, DEINIT_SCREENS, + ZEROFILL_N3DS_ABL_REGISTERS, PREPARE_ARM11_FOR_FIRMLAUNCH, ARM11_READY, } Arm11Operation; @@ -73,3 +74,4 @@ void swapFramebuffers(bool isAlternate); void updateBrightness(u32 brightnessIndex); void clearScreens(bool isAlternate); void initScreens(void); +void zerofillN3dsAblRegisters(void);