rosalina: add brightness control menu

This commit is contained in:
TuxSH 2020-05-16 02:37:47 +01:00
parent a21eee9207
commit a564d8536a
7 changed files with 115 additions and 5 deletions

View File

@ -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)

View File

@ -60,6 +60,7 @@ typedef struct Menu {
MenuItem items[0x40];
} Menu;
extern bool isN3DS;
extern bool menuShouldExit;
extern bool preTerminationRequested;
extern Handle preTerminationEvent;

View File

@ -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);

View File

@ -30,3 +30,4 @@
#include "menu.h"
Result OpenProcessByName(const char *name, Handle *h);
Result PatchProcessByName(const char *name, Result (*func)(u32 size));

View File

@ -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

View File

@ -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();

View File

@ -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;
}*/
}