diff --git a/sysmodules/rosalina/include/draw.h b/sysmodules/rosalina/include/draw.h index 5de1753..2b75375 100644 --- a/sysmodules/rosalina/include/draw.h +++ b/sysmodules/rosalina/include/draw.h @@ -54,6 +54,9 @@ #define GPU_TRANSFER_CNT REG32(0x10400C18) #define GPU_CMDLIST_CNT REG32(0x104018F0) +#define LCD_TOP_BRIGHTNESS REG32(0x10202240) +#define LCD_BOT_BRIGHTNESS REG32(0x10202A40) + #define FB_BOTTOM_VRAM_ADDR ((void *)0x1F48F000) // cached #define FB_BOTTOM_VRAM_PA 0x1848F000 #define FB_BOTTOM_SIZE (320 * 240 * 2) diff --git a/sysmodules/rosalina/include/menu.h b/sysmodules/rosalina/include/menu.h index 5dfc9e7..d012027 100644 --- a/sysmodules/rosalina/include/menu.h +++ b/sysmodules/rosalina/include/menu.h @@ -60,6 +60,7 @@ typedef struct Menu { MenuItem items[0x40]; } Menu; +extern bool isN3DS; extern bool menuShouldExit; extern bool preTerminationRequested; extern Handle preTerminationEvent; diff --git a/sysmodules/rosalina/include/menus.h b/sysmodules/rosalina/include/menus.h index 1105a69..1764420 100644 --- a/sysmodules/rosalina/include/menus.h +++ b/sysmodules/rosalina/include/menus.h @@ -33,6 +33,7 @@ extern Menu rosalinaMenu; void RosalinaMenu_TakeScreenshot(void); +void RosalinaMenu_ChangeScreenBrightness(void); void RosalinaMenu_ShowCredits(void); void RosalinaMenu_ProcessList(void); void RosalinaMenu_PowerOff(void); diff --git a/sysmodules/rosalina/include/process_patches.h b/sysmodules/rosalina/include/process_patches.h index 698efb7..4ecec3c 100644 --- a/sysmodules/rosalina/include/process_patches.h +++ b/sysmodules/rosalina/include/process_patches.h @@ -30,3 +30,4 @@ #include "menu.h" Result OpenProcessByName(const char *name, Handle *h); +Result PatchProcessByName(const char *name, Result (*func)(u32 size)); diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index 28fdc8e..b383f4b 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -151,7 +151,6 @@ MyThread *menuCreateThread(void) return &menuThread; } -extern bool isN3DS; u32 menuCombo; void menuThreadMain(void) @@ -159,7 +158,7 @@ void menuThreadMain(void) if(!isN3DS) { rosalinaMenu.nbItems--; - for(u32 i = 6; i <= rosalinaMenu.nbItems; i++) + for(u32 i = 7; i <= rosalinaMenu.nbItems; i++) rosalinaMenu.items[i] = rosalinaMenu.items[i+1]; } else diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index 8870768..324adec 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -38,12 +38,14 @@ #include "ifile.h" #include "memory.h" #include "fmt.h" +#include "process_patches.h" Menu rosalinaMenu = { "Rosalina menu", - .nbItems = 11, + .nbItems = 12, { { "Take screenshot", METHOD, .method = &RosalinaMenu_TakeScreenshot }, + { "Change screen brightness", METHOD, .method = &RosalinaMenu_ChangeScreenBrightness }, { "Cheats...", METHOD, .method = &RosalinaMenu_Cheats }, { "Process list", METHOD, .method = &RosalinaMenu_ProcessList }, { "Debugger options...", MENU, .menu = &debuggerMenu }, @@ -119,6 +121,109 @@ void RosalinaMenu_Reboot(void) while(!menuShouldExit); } +static u32 gspPatchAddrN3ds, gspPatchValuesN3ds[2]; +static bool gspPatchDoneN3ds; + +static Result RosalinaMenu_PatchN3dsGspForBrightness(u32 size) +{ + u32 *off = (u32 *)0x00100000; + u32 *end = (u32 *)(0x00100000 + size); + + for (; off < end && (off[0] != 0xE92D4030 || off[1] != 0xE1A04000 || off[2] != 0xE2805C01 || off[3] != 0xE5D0018C); off++); + + if (off >= end) { + return -1; + } + + gspPatchAddrN3ds = (u32)off; + gspPatchValuesN3ds[0] = off[26]; + gspPatchValuesN3ds[1] = off[50]; + + // NOP brightness changing in GSP + off[26] = 0xE1A00000; + off[50] = 0xE1A00000; + + return 0; +} +static Result RosalinaMenu_RevertN3dsGspPatch(u32 size) +{ + (void)size; + + u32 *off = (u32 *)gspPatchAddrN3ds; + off[26] = gspPatchValuesN3ds[0]; + off[50] = gspPatchValuesN3ds[1]; + + return 0; +} + +void RosalinaMenu_ChangeScreenBrightness(void) +{ + Result patchResult = 0; + if (isN3DS && !gspPatchDoneN3ds) + { + patchResult = PatchProcessByName("gsp", RosalinaMenu_PatchN3dsGspForBrightness); + gspPatchDoneN3ds = R_SUCCEEDED(patchResult); + } + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + // Assume the current brightness for both screens are the same. + s32 brightness = (s32)(LCD_TOP_BRIGHTNESS & 0xFF); + + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu"); + u32 posY = 30; + posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Current brightness (0..255): %3lu\n\n", brightness); + if (R_SUCCEEDED(patchResult)) + { + posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Up/Down for +-1, Right/Left for +-10.\n"); + posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Y to revert the GSP patch and exit.\n\n"); + + posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n"); + posY = Draw_DrawString(10, posY, COLOR_WHITE, " * very high values might damage your screens\n"); + posY = Draw_DrawString(10, posY, COLOR_WHITE, " * normal brightness mngmt. is now broken on N3DS.\nYou'll need to press Y to revert"); + } + else + Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Failed to patch GSP (0x%08lx).", (u32)patchResult); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if ((pressed & DIRECTIONAL_KEYS) && R_SUCCEEDED(patchResult)) + { + if (pressed & KEY_UP) + brightness += 1; + else if (pressed & KEY_DOWN) + brightness -= 1; + else if (pressed & KEY_RIGHT) + brightness += 10; + else if (pressed & KEY_LEFT) + brightness -= 10; + + brightness = brightness < 0 ? 0 : brightness; + brightness = brightness > 255 ? 255 : brightness; + LCD_TOP_BRIGHTNESS = (u32)brightness; + LCD_BOT_BRIGHTNESS = (u32)brightness; + } + else if ((pressed & KEY_Y) && gspPatchDoneN3ds) + { + patchResult = PatchProcessByName("gsp", RosalinaMenu_RevertN3dsGspPatch); + gspPatchDoneN3ds = !R_SUCCEEDED(patchResult); + return; + } + else if (pressed & KEY_B) + return; + } + while (!menuShouldExit); +} + void RosalinaMenu_PowerOff(void) // Soft shutdown. { Draw_Lock(); diff --git a/sysmodules/rosalina/source/process_patches.c b/sysmodules/rosalina/source/process_patches.c index 3535780..8ba7843 100644 --- a/sysmodules/rosalina/source/process_patches.c +++ b/sysmodules/rosalina/source/process_patches.c @@ -59,7 +59,7 @@ Result OpenProcessByName(const char *name, Handle *h) return 0; } -/*static u32 ProcessPatchesMenu_PatchUnpatchProcessByName(const char *name, Result (*func)(u32 size)) +Result PatchProcessByName(const char *name, Result (*func)(u32 size)) { Result res; Handle processHandle; @@ -75,4 +75,4 @@ Result OpenProcessByName(const char *name, Handle *h) svcUnmapProcessMemoryEx(processHandle, 0x00100000, textTotalRoundedSize); return res; -}*/ +}