From c3b97999f57e652d7b3609cedcc79ae38d564903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 7 Jul 2019 15:06:15 +0200 Subject: [PATCH 01/18] loader: Fix boolean logic error --- sysmodules/loader/source/patcher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysmodules/loader/source/patcher.c b/sysmodules/loader/source/patcher.c index 119ee3f..8884106 100644 --- a/sysmodules/loader/source/patcher.c +++ b/sysmodules/loader/source/patcher.c @@ -369,7 +369,7 @@ bool loadTitleExheaderInfo(u64 progId, ExHeader_Info *exheaderInfo) u64 fileSize; - if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(ExHeader_Info) || fileSize != sizeof(ExHeader)) goto error; + if(R_FAILED(IFile_GetSize(&file, &fileSize)) || (fileSize != sizeof(ExHeader_Info) && fileSize != sizeof(ExHeader))) goto error; else { u64 total; From 236dbb043cb68c41a57a2b61c03a7da912201130 Mon Sep 17 00:00:00 2001 From: LiquidFenrir Date: Sun, 21 Jul 2019 19:05:37 +0200 Subject: [PATCH 02/18] add wifi connection forcing to rosalina breaks regular auto connect until reboot allows connecting to a wifi without internet (for example, for transferring stuff with 3dslink or ftpd/3DShell) --- sysmodules/rosalina/include/menus/sysconfig.h | 1 + sysmodules/rosalina/source/main.c | 4 + sysmodules/rosalina/source/menus/sysconfig.c | 115 +++++++++++++++++- 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/sysmodules/rosalina/include/menus/sysconfig.h b/sysmodules/rosalina/include/menus/sysconfig.h index fcae0a4..d02a9d0 100644 --- a/sysmodules/rosalina/include/menus/sysconfig.h +++ b/sysmodules/rosalina/include/menus/sysconfig.h @@ -33,3 +33,4 @@ extern Menu sysconfigMenu; void SysConfigMenu_ToggleLEDs(void); void SysConfigMenu_ToggleWireless(void); +void SysConfigMenu_ControlWifi(void); diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index 74a7d27..e557277 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -90,11 +90,15 @@ void __appInit() if (R_FAILED(pmDbgInit())) svcBreak(USERBREAK_PANIC); + + if (R_FAILED(acInit())) + svcBreak(USERBREAK_PANIC); } // this is called after main exits void __appExit() { + acExit(); pmDbgExit(); fsExit(); svcCloseHandle(*fsRegGetSessionHandle()); diff --git a/sysmodules/rosalina/source/menus/sysconfig.c b/sysmodules/rosalina/source/menus/sysconfig.c index f2f8851..2eb36c4 100644 --- a/sysmodules/rosalina/source/menus/sysconfig.c +++ b/sysmodules/rosalina/source/menus/sysconfig.c @@ -34,10 +34,11 @@ Menu sysconfigMenu = { "System configuration menu", - .nbItems = 2, + .nbItems = 3, { { "Toggle LEDs", METHOD, .method = &SysConfigMenu_ToggleLEDs }, { "Toggle Wireless", METHOD, .method = &SysConfigMenu_ToggleWireless }, + { "Control Wireless connection", METHOD, .method = &SysConfigMenu_ControlWifi }, } }; @@ -146,3 +147,115 @@ void SysConfigMenu_ToggleWireless(void) } while(!terminationRequest); } + +static void SysConfigMenu_ForceWifiConnection(int slot) +{ + char ssid[0x20 + 1] = {0}; + + u8 data[0x200] = {0}; + ACU_CreateDefaultConfig(data); + ACU_SetNetworkArea(data, 2); + ACU_SetAllowApType(data, 1 << slot); + ACU_SetRequestEulaVersion(data); + + Handle connectEvent = 0; + svcCreateEvent(&connectEvent, RESET_ONESHOT); + + bool forcedConnection = false; + if(R_SUCCEEDED(ACU_ConnectAsync(data, connectEvent))) + { + if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1))) + { + ACU_GetSSID(ssid); + forcedConnection = true; + } + } + svcCloseHandle(connectEvent); + + char infoString[80] = {0}; + u32 infoStringColor = forcedConnection ? COLOR_GREEN : COLOR_RED; + if(forcedConnection) + sprintf(infoString, "Succesfully forced a connection to: %s", ssid); + else + sprintf(infoString, "Failed to connect to slot %d", slot + 1); + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu"); + Draw_DrawString(10, 30, infoStringColor, infoString); + Draw_DrawString(10, 40, COLOR_WHITE, "Press B to go back."); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & BUTTON_B) + return; + } + while(!terminationRequest); +} + +void SysConfigMenu_ControlWifi(void) +{ + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + int slot = 0; + char slotString[12] = {0}; + sprintf(slotString, ">1< 2 3 "); + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu"); + Draw_DrawString(10, 30, COLOR_WHITE, "Press A to force a connection to slot:"); + Draw_DrawString(10, 40, COLOR_WHITE, slotString); + Draw_DrawString(10, 60, COLOR_WHITE, "Press B to go back."); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & BUTTON_A) + { + SysConfigMenu_ForceWifiConnection(slot); + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + } + else if(pressed & BUTTON_LEFT) + { + slotString[slot * 4] = ' '; + slotString[(slot * 4) + 2] = ' '; + slot--; + if(slot == -1) + slot = 2; + slotString[slot * 4] = '>'; + slotString[(slot * 4) + 2] = '<'; + } + else if(pressed & BUTTON_RIGHT) + { + slotString[slot * 4] = ' '; + slotString[(slot * 4) + 2] = ' '; + slot++; + if(slot == 3) + slot = 0; + slotString[slot * 4] = '>'; + slotString[(slot * 4) + 2] = '<'; + } + else if(pressed & BUTTON_B) + return; + } + while(!terminationRequest); +} From 93e87284aae81d6e4395b5a60aa84721d6fc2a3d Mon Sep 17 00:00:00 2001 From: LiquidFenrir Date: Tue, 23 Jul 2019 00:13:17 +0200 Subject: [PATCH 03/18] follow changes in ctrulib PR --- sysmodules/rosalina/source/menus/sysconfig.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sysmodules/rosalina/source/menus/sysconfig.c b/sysmodules/rosalina/source/menus/sysconfig.c index 2eb36c4..530fe16 100644 --- a/sysmodules/rosalina/source/menus/sysconfig.c +++ b/sysmodules/rosalina/source/menus/sysconfig.c @@ -152,17 +152,17 @@ static void SysConfigMenu_ForceWifiConnection(int slot) { char ssid[0x20 + 1] = {0}; - u8 data[0x200] = {0}; - ACU_CreateDefaultConfig(data); - ACU_SetNetworkArea(data, 2); - ACU_SetAllowApType(data, 1 << slot); - ACU_SetRequestEulaVersion(data); + acuConfig config = {0}; + ACU_CreateDefaultConfig(&config); + ACU_SetNetworkArea(&config, 2); + ACU_SetAllowApType(&config, 1 << slot); + ACU_SetRequestEulaVersion(&config); Handle connectEvent = 0; svcCreateEvent(&connectEvent, RESET_ONESHOT); bool forcedConnection = false; - if(R_SUCCEEDED(ACU_ConnectAsync(data, connectEvent))) + if(R_SUCCEEDED(ACU_ConnectAsync(&config, connectEvent))) { if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1))) { From a4befc29c81444ecd9a30c2fb2eefbe2bb19aa5d Mon Sep 17 00:00:00 2001 From: piepie62 Date: Mon, 12 Aug 2019 00:58:16 -0400 Subject: [PATCH 04/18] Fix off-by-one error with extra cheat page --- sysmodules/rosalina/source/menus/cheats.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sysmodules/rosalina/source/menus/cheats.c b/sysmodules/rosalina/source/menus/cheats.c index 635ddc9..9e67ffa 100644 --- a/sysmodules/rosalina/source/menus/cheats.c +++ b/sysmodules/rosalina/source/menus/cheats.c @@ -168,7 +168,7 @@ static u8 ReadWriteBuffer8 = 0; static bool Cheat_Write8(const Handle processHandle, u32 offset, u8 value) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) + if (addr >= 0x01E81000 && addr < 0x01E82000) { cheatPage[addr - 0x01E81000] = value; return true; @@ -184,7 +184,7 @@ static bool Cheat_Write8(const Handle processHandle, u32 offset, u8 value) static bool Cheat_Write16(const Handle processHandle, u32 offset, u16 value) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 2 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) { *(u16*)(cheatPage + addr - 0x01E81000) = value; return true; @@ -200,7 +200,7 @@ static bool Cheat_Write16(const Handle processHandle, u32 offset, u16 value) static bool Cheat_Write32(const Handle processHandle, u32 offset, u32 value) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 4 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 3 < 0x01E82000) { *(u32*)(cheatPage + addr - 0x01E81000) = value; return true; @@ -216,7 +216,7 @@ static bool Cheat_Write32(const Handle processHandle, u32 offset, u32 value) static bool Cheat_Read8(const Handle processHandle, u32 offset, u8* retValue) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) + if (addr >= 0x01E81000 && addr < 0x01E82000) { *retValue = cheatPage[addr - 0x01E81000]; return true; @@ -233,7 +233,7 @@ static bool Cheat_Read8(const Handle processHandle, u32 offset, u8* retValue) static bool Cheat_Read16(const Handle processHandle, u32 offset, u16* retValue) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 2 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) { *retValue = *(u16*)(cheatPage + addr - 0x01E81000); return true; @@ -250,7 +250,7 @@ static bool Cheat_Read16(const Handle processHandle, u32 offset, u16* retValue) static bool Cheat_Read32(const Handle processHandle, u32 offset, u32* retValue) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 4 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 3 < 0x01E82000) { *retValue = *(u32*)(cheatPage + addr - 0x01E81000); return true; From 7e14c83bddf61b7c3491403ca50cf4986d61403d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 13 Aug 2019 02:54:09 -0400 Subject: [PATCH 05/18] rosalina/gdb/server: Prevent potential null dereference case While unlikely to commonly occur, this is a trivially avoidable case. --- sysmodules/rosalina/source/gdb/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysmodules/rosalina/source/gdb/server.c b/sysmodules/rosalina/source/gdb/server.c index 5be53d5..0536f92 100644 --- a/sysmodules/rosalina/source/gdb/server.c +++ b/sysmodules/rosalina/source/gdb/server.c @@ -136,9 +136,9 @@ GDBContext *GDB_SelectAvailableContext(GDBServer *server, u16 minPort, u16 maxPo { ctx->flags |= GDB_FLAG_SELECTED; ctx->localPort = port; + ctx->parent = server; } - ctx->parent = server; GDB_UnlockAllContexts(server); return ctx; } From c95b59c72eb025567ff05680604a44e8e3251057 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 13 Aug 2019 03:01:24 -0400 Subject: [PATCH 06/18] sm/notifications: Prevent potential null pointer dereference in ReceiveNotification Based off the conditions, this is a potential null pointer dereference that can occur. We need to check for null before accessing nbPendingNotifications. This is unlikely to occur in common usage, however it's a fairly straightforward amendment. --- sysmodules/sm/source/notifications.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysmodules/sm/source/notifications.c b/sysmodules/sm/source/notifications.c index ca87da5..8294957 100644 --- a/sysmodules/sm/source/notifications.c +++ b/sysmodules/sm/source/notifications.c @@ -101,7 +101,7 @@ Result ReceiveNotification(SessionData *sessionData, u32 *notificationId) if(processData == NULL || !processData->notificationEnabled || processData->nbPendingNotifications == 0) { - if(processData->nbPendingNotifications) + if(processData != NULL && processData->nbPendingNotifications) *notificationId = 0; return 0xD8806404; } From 60a8bf56c652324fffcde6cfe5384b18272a72a3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 13 Aug 2019 03:11:45 -0400 Subject: [PATCH 07/18] rosalina/errdisp: Correct uninitialized variable usage in ERRF_HandleCommands This was previously using the value of the uninitialized sz variable before it was actually assigned a value, rather than assigning the size indicated within the command buffer. --- sysmodules/rosalina/source/errdisp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysmodules/rosalina/source/errdisp.c b/sysmodules/rosalina/source/errdisp.c index 914895f..e3b11b5 100644 --- a/sysmodules/rosalina/source/errdisp.c +++ b/sysmodules/rosalina/source/errdisp.c @@ -273,7 +273,7 @@ void ERRF_HandleCommands(void *ctx) else { cmdbuf[0] = 0x20040; - u32 sz = cmdbuf[1] <= 0x100 ? sz : 0x100; + u32 sz = cmdbuf[1] <= 0x100 ? cmdbuf[1] : 0x100; memcpy(userString, cmdbuf + 3, sz); userString[sz] = 0; } From e8493d18c58b6ac3f0a8d6a3451789bc822f02c4 Mon Sep 17 00:00:00 2001 From: nathan hitch Date: Mon, 16 Sep 2019 17:13:23 +0930 Subject: [PATCH 08/18] Add ability to offset ntp by any amount of minutes --- sysmodules/rosalina/source/menus/miscellaneous.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 4cadf8b..3f3b131 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -336,6 +336,7 @@ void MiscellaneousMenu_SyncTimeDate(void) cantStart = R_FAILED(res) || !isSocURegistered; int utcOffset = 12; + int utcOffsetMinute = 0; int absOffset; do { @@ -344,14 +345,15 @@ void MiscellaneousMenu_SyncTimeDate(void) absOffset = utcOffset - 12; absOffset = absOffset < 0 ? -absOffset : absOffset; - posY = Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Current UTC offset: %c%02d", utcOffset < 12 ? '-' : '+', absOffset); - posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Use DPAD Left/Right to change offset.\nPress A when done.") + SPACING_Y; + posY = Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Current UTC offset: %c%02d%02d", utcOffset < 12 ? '-' : '+', absOffset, utcOffsetMinute); + posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Use DPAD Left/Right to change hour offset.\nUse DPAD Up/Down to change minute offset.\nPress A when done.") + SPACING_Y; input = waitInput(); if(input & BUTTON_LEFT) utcOffset = (24 + utcOffset - 1) % 24; // ensure utcOffset >= 0 if(input & BUTTON_RIGHT) utcOffset = (utcOffset + 1) % 24; - + if(input & BUTTON_UP) utcOffsetMinute = (utcOffsetMinute + 1) % 60; + if(input & BUTTON_DOWN) utcOffsetMinute = (60 + utcOffsetMinute - 1) % 60; Draw_FlushFramebuffer(); Draw_Unlock(); } @@ -371,6 +373,7 @@ void MiscellaneousMenu_SyncTimeDate(void) if(R_SUCCEEDED(res)) { t += 3600 * utcOffset; + t += 60 * utcOffsetMinute; gmtime_r(&t, &localt); res = ntpSetTimeDate(&localt); } From 0886b10619e5cc7c73ef739ea65f3d0c6f254c52 Mon Sep 17 00:00:00 2001 From: oreo639 <31916379+Oreo639@users.noreply.github.com> Date: Tue, 22 Oct 2019 16:03:00 -0700 Subject: [PATCH 09/18] rosilina: save errdisp info before doing anything else --- sysmodules/rosalina/source/errdisp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sysmodules/rosalina/source/errdisp.c b/sysmodules/rosalina/source/errdisp.c index 914895f..bcffea3 100644 --- a/sysmodules/rosalina/source/errdisp.c +++ b/sysmodules/rosalina/source/errdisp.c @@ -50,6 +50,11 @@ static inline int ERRF_FormatRegisterValue(char *out, const char *name, u32 valu return sprintf(out, "%-9s %08lx", name, value); } +static inline void ERRF_GetErrInfo(ERRF_FatalErrInfo* info, u32* in, u32 size) +{ + memcpy(info, in, size); +} + static int ERRF_FormatError(char *out, ERRF_FatalErrInfo *info) { char *outStart = out; @@ -154,7 +159,7 @@ static int ERRF_FormatError(char *out, ERRF_FatalErrInfo *info) desc = "The System Memory has been damaged."; break; case ERRF_ERRTYPE_FAILURE: - info->data.failure_mesg[0x60] = 0; // make sure the last byte in the IPC buffer is NULL + info->data.failure_mesg[0x5F] = 0; // make sure the last byte in the IPC buffer is NULL desc = info->data.failure_mesg; break; default: @@ -229,14 +234,15 @@ void ERRF_HandleCommands(void *ctx) { (void)ctx; u32 *cmdbuf = getThreadCommandBuffer(); + ERRF_FatalErrInfo info; switch(cmdbuf[0] >> 16) { case 1: // Throw { - ERRF_FatalErrInfo *info = (ERRF_FatalErrInfo *)(cmdbuf + 1); - ERRF_SaveErrorToFile(info); - if(info->type != ERRF_ERRTYPE_LOGGED || info->procId == 0) + ERRF_GetErrInfo(&info, (cmdbuf + 1), sizeof(ERRF_FatalErrInfo)); + ERRF_SaveErrorToFile(&info); + if(info.type != ERRF_ERRTYPE_LOGGED || info.procId == 0) { menuEnter(); @@ -244,7 +250,7 @@ void ERRF_HandleCommands(void *ctx) Draw_ClearFramebuffer(); Draw_FlushFramebuffer(); - ERRF_DisplayError(info); + ERRF_DisplayError(&info); /* If we ever wanted to return: From 5edfbfc1f78e15e0ec64e9f71071eda1100b6a4d Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Tue, 17 Dec 2019 15:00:37 +0100 Subject: [PATCH 10/18] Fix stack overflow on screen filters --- .../rosalina/source/menus/screen_filters.c | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index 53b4eb8..ca7932b 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -55,37 +55,38 @@ typedef struct { u8 z; } Pixel; +static u16 g_c[0x600]; +static Pixel g_px[0x400]; + void applyColorSettings(color_setting_t* cs) { - u16 c[0x600]; - Pixel px[0x400]; u8 i = 0; - memset(c, 0, sizeof(c)); - memset(px, 0, sizeof(px)); + memset(g_c, 0, sizeof(g_c)); + memset(g_px, 0, sizeof(g_px)); do { - px[i].r = i; - px[i].g = i; - px[i].b = i; - px[i].z = 0; + g_px[i].r = i; + g_px[i].g = i; + g_px[i].b = i; + g_px[i].z = 0; } while(++i); do { - *(c + i + 0x000) = px[i].r | (px[i].r << 8); - *(c + i + 0x100) = px[i].g | (px[i].g << 8); - *(c + i + 0x200) = px[i].b | (px[i].b << 8); + *(g_c + i + 0x000) = g_px[i].r | (g_px[i].r << 8); + *(g_c + i + 0x100) = g_px[i].g | (g_px[i].g << 8); + *(g_c + i + 0x200) = g_px[i].b | (g_px[i].b << 8); } while(++i); - colorramp_fill(c + 0x000, c + 0x100, c + 0x200, 0x100, cs); + colorramp_fill(g_c + 0x000, g_c + 0x100, g_c + 0x200, 0x100, cs); do { - px[i].r = *(c + i + 0x000) >> 8; - px[i].g = *(c + i + 0x100) >> 8; - px[i].b = *(c + i + 0x200) >> 8; + g_px[i].r = *(g_c + i + 0x000) >> 8; + g_px[i].g = *(g_c + i + 0x100) >> 8; + g_px[i].b = *(g_c + i + 0x200) >> 8; } while(++i); - writeLut((u32*)px); + writeLut((u32*)g_px); } Menu screenFiltersMenu = { From ca49956219d5f505de2555210fbc3cdf293a8263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 24 Nov 2019 11:38:02 +0100 Subject: [PATCH 11/18] loader: Compile C++ code with -std=gnu++17 --- sysmodules/loader/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sysmodules/loader/Makefile b/sysmodules/loader/Makefile index 14c390d..c24cde7 100755 --- a/sysmodules/loader/Makefile +++ b/sysmodules/loader/Makefile @@ -28,13 +28,13 @@ INCLUDES := include ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \ +COMMON_FLAGS = -g -Wall -Wextra -Werror -O2 -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections \ - $(ARCH) $(DEFINES) + $(ARCH) $(DEFINES) $(INCLUDE) -CFLAGS += $(INCLUDE) +CFLAGS := -std=gnu11 $(COMMON_FLAGS) -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 +CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17 $(COMMON_FLAGS) ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000 From 8233d4e2267041366d06bdd2ae6369bc57a5de26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 8 Jul 2019 18:28:35 +0200 Subject: [PATCH 12/18] loader: Add support for BPS patches The BPS format allows distributing patches that are smaller and that do not contain copyrighted content if data is relocated (unlike non-trivial IPS patches). This is essential for games such as Majora's Mask 3D that have three barely different code revisions. Supporting all three versions would demand an unreasonable amount of work; with BPS patches only one version has to be supported. The patcher is written in C++ in order to make it possible to share the implementation with Citra and because a C version would be a lot more ugly and tedious to write. The patcher is non-intrusive for the rest of the codebase and self-contained so hopefully that isn't an issue. This adds roughly ~0x500 bytes of code to the loader sysmodule. Code looks reasonably optimised (in IDA). Tested and works on an o3DS. --- sysmodules/loader/source/bps_patcher.cpp | 283 +++++++++++++++++++++++ sysmodules/loader/source/bps_patcher.h | 12 + sysmodules/loader/source/file_util.h | 76 ++++++ sysmodules/loader/source/patcher.c | 2 + 4 files changed, 373 insertions(+) create mode 100644 sysmodules/loader/source/bps_patcher.cpp create mode 100644 sysmodules/loader/source/bps_patcher.h create mode 100644 sysmodules/loader/source/file_util.h diff --git a/sysmodules/loader/source/bps_patcher.cpp b/sysmodules/loader/source/bps_patcher.cpp new file mode 100644 index 0000000..0c8ca0a --- /dev/null +++ b/sysmodules/loader/source/bps_patcher.cpp @@ -0,0 +1,283 @@ +#include "bps_patcher.h" + +#include +#include +#include +#include +#include + +extern "C" +{ +#include <3ds/os.h> +#include <3ds/result.h> +#include <3ds/services/fs.h> +#include <3ds/svc.h> + +#include "patcher.h" +#include "strings.h" +} + +#include "file_util.h" + +namespace patcher +{ +namespace Bps +{ +// The BPS format uses variable length encoding for all integers. +// Realistically uint32s are more than enough for code patching. +using Number = u32; + +constexpr std::size_t FooterSize = 12; + +// The BPS format uses CRC32 checksums. +[[gnu::optimize("Os")]] static u32 crc32(const u8 *data, std::size_t size) +{ + u32 crc = 0xFFFFFFFF; + for(std::size_t i = 0; i < size; ++i) + { + crc ^= data[i]; + for(std::size_t j = 0; j < 8; ++j) + { + u32 mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + } + return ~crc; +} + +// Utility class to make keeping track of offsets and bound checks less error prone. +template +class Stream +{ +public: + Stream(T *ptr, std::size_t size) : m_ptr{ptr}, m_size{size} {} + + bool Read(void *buffer, std::size_t length) + { + if(m_offset + length > m_size) + return false; + std::memcpy(buffer, m_ptr + m_offset, length); + m_offset += length; + return true; + } + + template + [[gnu::optimize("Os")]] bool CopyFrom(Stream &other, std::size_t length) + { + if(m_offset + length > m_size) + return false; + if(!other.Read(m_ptr + m_offset, length)) + return false; + m_offset += length; + return true; + } + + template + std::optional Read() + { + static_assert(std::is_pod_v); + ValueType val{}; + if(!Read(&val, sizeof(val))) + return std::nullopt; + return val; + } + + [[gnu::optimize("Os")]] Number ReadNumber() + { + Number data = 0, shift = 1; + std::optional x; + while((x = Read())) + { + data += (*x & 0x7f) * shift; + if(*x & 0x80) + break; + shift <<= 7; + data += shift; + } + return data; + } + + auto data() const { return m_ptr; } + std::size_t size() const { return m_size; } + std::size_t Tell() const { return m_offset; } + + bool Seek(size_t offset) + { + m_offset = offset; + return true; + } + +private: + T *m_ptr = nullptr; + std::size_t m_size = 0; + std::size_t m_offset = 0; +}; + +class PatchApplier +{ +public: + PatchApplier(Stream source, Stream target, Stream patch) + : m_source{source}, m_target{target}, m_patch{patch} + { + } + + [[gnu::always_inline]] bool Apply() + { + const auto magic = *m_patch.Read>(); + if(std::string_view(magic.data(), magic.size()) != "BPS1") + return false; + + const Bps::Number source_size = m_patch.ReadNumber(); + const Bps::Number target_size = m_patch.ReadNumber(); + const Bps::Number metadata_size = m_patch.ReadNumber(); + if(source_size > m_source.size() || target_size > m_target.size() || metadata_size != 0) + return false; + + const std::size_t command_start_offset = m_patch.Tell(); + const std::size_t command_end_offset = m_patch.size() - FooterSize; + m_patch.Seek(command_end_offset); + const u32 source_crc32 = *m_patch.Read(); + const u32 target_crc32 = *m_patch.Read(); + m_patch.Seek(command_start_offset); + + if(crc32(m_source.data(), source_size) != source_crc32) + return false; + + // Process all patch commands. + std::memset(m_target.data(), 0, m_target.size()); + while(m_patch.Tell() < command_end_offset) + { + const bool ok = HandleCommand(); + if(!ok) + return false; + } + + return crc32(m_target.data(), target_size) == target_crc32; + } + +private: + bool HandleCommand() + { + const Number data = m_patch.ReadNumber(); + const Number command = data & 3; + const Number length = (data >> 2) + 1; + + switch(command) + { + case 0: + return SourceRead(length); + case 1: + return TargetRead(length); + case 2: + return SourceCopy(length); + case 3: + return TargetCopy(length); + default: + return false; + } + } + + bool SourceRead(Number length) + { + return m_source.Seek(m_target.Tell()) && m_target.CopyFrom(m_source, length); + } + + bool TargetRead(Number length) { return m_target.CopyFrom(m_patch, length); } + + bool SourceCopy(Number length) + { + const Number data = m_patch.ReadNumber(); + m_source_relative_offset += (data & 1 ? -1 : +1) * int(data >> 1); + if(!m_source.Seek(m_source_relative_offset) || !m_target.CopyFrom(m_source, length)) + return false; + m_source_relative_offset += length; + return true; + } + + bool TargetCopy(Number length) + { + const Number data = m_patch.ReadNumber(); + m_target_relative_offset += (data & 1 ? -1 : +1) * int(data >> 1); + if(m_target.Tell() + length > m_target.size()) + return false; + if(m_target_relative_offset + length > m_target.size()) + return false; + // Byte by byte copy. + for(size_t i = 0; i < length; ++i) + m_target.data()[m_target.Tell() + i] = m_target.data()[m_target_relative_offset++]; + m_target.Seek(m_target.Tell() + length); + return true; + } + + std::size_t m_source_relative_offset = 0; + std::size_t m_target_relative_offset = 0; + Stream m_source; + Stream m_target; + Stream m_patch; +}; + +} // namespace Bps + +class ScopedAppHeap +{ +public: + ScopedAppHeap() + { + u32 tmp; + m_size = osGetMemRegionFree(MEMREGION_APPLICATION); + if(!R_SUCCEEDED(svcControlMemory(&tmp, BaseAddress, 0, m_size, + MemOp(MEMOP_ALLOC | MEMOP_REGION_APP), + MemPerm(MEMPERM_READ | MEMPERM_WRITE)))) + { + svcBreak(USERBREAK_PANIC); + } + } + + ~ScopedAppHeap() + { + u32 tmp; + svcControlMemory(&tmp, BaseAddress, 0, m_size, MEMOP_FREE, MemPerm(0)); + } + + static constexpr u32 BaseAddress = 0x08000000; + +private: + u32 m_size; +}; + +static inline bool ApplyCodeBpsPatch(u64 prog_id, u8 *code, u32 size) +{ + char bps_path[] = "/luma/titles/0000000000000000/code.bps"; + progIdToStr(bps_path + 28, prog_id); + util::File patch_file; + if(!patch_file.Open(bps_path, FS_OPEN_READ)) + return true; + const u32 patch_size = u32(patch_file.GetSize().value_or(0)); + + // Temporarily use APPLICATION memory to store the source and patch data. + ScopedAppHeap memory; + + u8 *source_data = reinterpret_cast(memory.BaseAddress); + u8 *patch_data = source_data + size; + std::memcpy(source_data, code, size); + if(!patch_file.Read(patch_data, patch_size, 0)) + return false; + + Bps::Stream source_stream{source_data, size}; + Bps::Stream target_stream{code, size}; + Bps::Stream patch_stream{patch_data, patch_size}; + Bps::PatchApplier applier{source_stream, target_stream, patch_stream}; + if(!applier.Apply()) + svcBreak(USERBREAK_PANIC); + return true; +} + +} // namespace patcher + +extern "C" +{ + bool patcherApplyCodeBpsPatch(u64 progId, u8 *code, u32 size) + { + return patcher::ApplyCodeBpsPatch(progId, code, size); + } +} diff --git a/sysmodules/loader/source/bps_patcher.h b/sysmodules/loader/source/bps_patcher.h new file mode 100644 index 0000000..25e76b0 --- /dev/null +++ b/sysmodules/loader/source/bps_patcher.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif +#include <3ds/types.h> + +bool patcherApplyCodeBpsPatch(u64 progId, u8* code, u32 size); + +#ifdef __cplusplus +} +#endif diff --git a/sysmodules/loader/source/file_util.h b/sysmodules/loader/source/file_util.h new file mode 100644 index 0000000..21aee71 --- /dev/null +++ b/sysmodules/loader/source/file_util.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +extern "C" +{ +#include <3ds/result.h> +#include <3ds/services/fs.h> +#include <3ds/svc.h> +#include <3ds/types.h> +} + +namespace util +{ +inline FS_Path MakePath(const char *path) +{ + return {PATH_ASCII, strnlen(path, 255) + 1, path}; +} + +// A small wrapper to make forgetting to close a file and +// to check read lengths impossible. +class File +{ +public: + File() = default; + File(const File &other) = delete; + File &operator=(const File &) = delete; + File(File &&other) { *this = std::move(other); } + File &operator=(File &&other) + { + std::swap(m_handle, other.m_handle); + return *this; + } + + ~File() { Close(); } + + bool Close() + { + const bool ok = !m_handle || R_SUCCEEDED(FSFILE_Close(*m_handle)); + if(ok) + m_handle = std::nullopt; + return ok; + } + + bool Open(const char *path, int open_flags) + { + const FS_Path archive_path = {PATH_EMPTY, 1, ""}; + Handle handle; + const bool ok = R_SUCCEEDED(FSUSER_OpenFileDirectly(&handle, ARCHIVE_SDMC, archive_path, + MakePath(path), open_flags, 0)); + if(ok) + m_handle = handle; + return ok; + } + + bool Read(void *buffer, u32 size, u64 offset) + { + u32 bytes_read = 0; + const Result res = FSFILE_Read(*m_handle, &bytes_read, offset, buffer, size); + return R_SUCCEEDED(res) && bytes_read == size; + } + + std::optional GetSize() const + { + u64 size; + if(!R_SUCCEEDED(FSFILE_GetSize(*m_handle, &size))) + return std::nullopt; + return size; + } + +private: + std::optional m_handle; +}; + +} // namespace util diff --git a/sysmodules/loader/source/patcher.c b/sysmodules/loader/source/patcher.c index 8884106..7967cdd 100644 --- a/sysmodules/loader/source/patcher.c +++ b/sysmodules/loader/source/patcher.c @@ -1,5 +1,6 @@ #include <3ds.h> #include "patcher.h" +#include "bps_patcher.h" #include "memory.h" #include "strings.h" #include "romfsredir.h" @@ -845,6 +846,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro if(CONFIG(PATCHGAMES)) { + if(!patcherApplyCodeBpsPatch(progId, code, size)) goto error; if(!applyCodeIpsPatch(progId, code, size)) goto error; if((u32)((progId >> 0x20) & 0xFFFFFFEDULL) == 0x00040000) From d34f0a8eca0c56487098e2725ebea01266d64d1c Mon Sep 17 00:00:00 2001 From: Margen67 Date: Thu, 2 Apr 2020 05:19:35 -0700 Subject: [PATCH 13/18] README: Formatting Update Project CTR makerom link. --- README.md | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index a1cf5c2..9e12c44 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,36 @@ # Luma3DS *Noob-proof (N)3DS "Custom Firmware"* -## What it is +### What it is +**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock. -**Luma3DS** is a program to patch the system software of (New) Nintendo 3DS handheld consoles "on the fly", adding features (such as per-game language settings and debugging capabilities for developers) and removing restrictions enforced by Nintendo (such as the region lock). It also allows you to run unauthorized ("homebrew") content by removing signature checks. To use it, you will need a console capable of running homebrew software on the ARM9 processor. We recommend [Plailect's guide](https://3ds.hacks.guide/) for details on how to get your system ready. -Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Select` (see the [release notes](https://github.com/AuroraWright/Luma3DS/releases/tag/v8.0)). +Since v8.0, Luma3DS has its own in-game menu, triggerable by L+Down+Select (see the [release notes](https://github.com/AuroraWright/Luma3DS/releases/tag/v8.0)). ---- +# +### Compiling +* Prerequisites + 1. git + 2. [makerom](https://github.com/jakcron/Project_CTR) in PATH + 3. [firmtool](https://github.com/TuxSH/firmtool) + 4. Up-to-date devkitARM+libctru +1. Clone the repository with `git clone https://github.com/AuroraWright/Luma3DS.git` +2. Run `make`. -## Compiling - -First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git` -To compile, you'll need a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions. -You'll also need to update your libctru and devkitARM installation to their latest releases. -Then, run `make`. -The produced file is called `boot.firm` and is meant to be copied to the root of your SD card, for usage with boot9strap. - ---- - -## Setup / Usage / Features + The produced `boot.firm` is meant to be copied to the root of your SD card for usage with Boot9Strap. +# +### Setup / Usage / Features See https://github.com/AuroraWright/Luma3DS/wiki ---- - -## Credits - +# +### Credits See https://github.com/AuroraWright/Luma3DS/wiki/Credits ---- +# +### Licensing +This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file. -## Licensing - -This software is licensed under the terms of the GPLv3. -You can find a copy of the license in the LICENSE.txt file. - -Files in the GDB stub are instead double-licensed as MIT or "GPLv2 or any later version", in which case it is specified in the file header. +Files in the GDB stub are instead double-licensed as MIT or "GPLv2 or any later version", in which case it's specified in the file header. From 55d51217d8ab53daa2af061be17ce4ae319decd3 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Wed, 15 Apr 2020 22:28:38 +0100 Subject: [PATCH 14/18] Fix hex parsing in patcher.c (langemu). Fixes #1375 Thanks @Lizardon1 --- sysmodules/loader/source/patcher.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sysmodules/loader/source/patcher.c b/sysmodules/loader/source/patcher.c index 8884106..8d7ac17 100644 --- a/sysmodules/loader/source/patcher.c +++ b/sysmodules/loader/source/patcher.c @@ -468,13 +468,13 @@ static inline bool loadTitleLocaleConfig(u64 progId, u8 *mask, u8 *regionId, u8 ((buf[10] >= '0' && buf[10] <= '9') || (buf[10] >= 'a' && buf[10] <= 'f') || (buf[10] >= 'A' && buf[10] <= 'F')) && ((buf[11] >= '0' && buf[11] <= '9') || (buf[11] >= 'a' && buf[11] <= 'f') || (buf[11] >= 'A' && buf[11] <= 'F'))) { - if (buf[10] >= '0' && buf[10] <= '9') *stateId = 16 * (buf[10] - '0'); - else if(buf[10] >= 'a' && buf[10] <= 'f') *stateId = 16 * (buf[10] - 'a'); - else if(buf[10] >= 'A' && buf[10] <= 'F') *stateId = 16 * (buf[10] - 'A'); + if (buf[10] >= '0' && buf[10] <= '9') *stateId = 16 * (buf[10] - '0' + 10); + else if(buf[10] >= 'a' && buf[10] <= 'f') *stateId = 16 * (buf[10] - 'a' + 10); + else if(buf[10] >= 'A' && buf[10] <= 'F') *stateId = 16 * (buf[10] - 'A' + 10); - if (buf[11] >= '0' && buf[11] <= '9') *stateId += buf[11] - '0'; - else if(buf[11] >= 'a' && buf[11] <= 'f') *stateId += buf[11] - 'a'; - else if(buf[11] >= 'A' && buf[11] <= 'F') *stateId += buf[11] - 'A'; + if (buf[11] >= '0' && buf[11] <= '9') *stateId += buf[11] - '0' + 10; + else if(buf[11] >= 'a' && buf[11] <= 'f') *stateId += buf[11] - 'a' + 10; + else if(buf[11] >= 'A' && buf[11] <= 'F') *stateId += buf[11] - 'A' + 10; *mask |= 8; } From d9c54379020a91d6479ae205873542f73f24d541 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Wed, 15 Apr 2020 23:15:02 +0100 Subject: [PATCH 15/18] rosalina: revert menu thread stack size now that screen filters LUT is in .bss --- sysmodules/rosalina/source/menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index f2eb724..2893afc 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -125,12 +125,12 @@ u32 waitCombo(void) } static MyThread menuThread; -static u8 ALIGN(8) menuThreadStack[0x3000]; +static u8 ALIGN(8) menuThreadStack[0x1000]; static u8 batteryLevel = 255; MyThread *menuCreateThread(void) { - if(R_FAILED(MyThread_Create(&menuThread, menuThreadMain, menuThreadStack, 0x3000, 52, CORE_SYSTEM))) + if(R_FAILED(MyThread_Create(&menuThread, menuThreadMain, menuThreadStack, 0x1000, 52, CORE_SYSTEM))) svcBreak(USERBREAK_PANIC); return &menuThread; } From c7551a731c829719dca1effec04bf0b96738ecb6 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 16 Apr 2020 00:16:25 +0100 Subject: [PATCH 16/18] rosalina: revert errdisp ipc handling --- sysmodules/rosalina/include/errdisp.h | 5 +- sysmodules/rosalina/source/errdisp.c | 96 +++++++++++++++++++++++++-- sysmodules/rosalina/source/main.c | 3 +- 3 files changed, 96 insertions(+), 8 deletions(-) diff --git a/sysmodules/rosalina/include/errdisp.h b/sysmodules/rosalina/include/errdisp.h index 33e69bc..2e718d3 100644 --- a/sysmodules/rosalina/include/errdisp.h +++ b/sysmodules/rosalina/include/errdisp.h @@ -27,5 +27,8 @@ #pragma once #include <3ds/types.h> +#include "MyThread.h" -void ERRF_HandleCommands(void *ctx); +MyThread *errDispCreateThread(void); +void ERRF_HandleCommands(void); +void errDispThreadMain(void); diff --git a/sysmodules/rosalina/source/errdisp.c b/sysmodules/rosalina/source/errdisp.c index df9cfe0..bff9d09 100644 --- a/sysmodules/rosalina/source/errdisp.c +++ b/sysmodules/rosalina/source/errdisp.c @@ -32,13 +32,26 @@ #include "fmt.h" #include "ifile.h" +extern Handle terminationRequestEvent; + static inline void assertSuccess(Result res) { if(R_FAILED(res)) svcBreak(USERBREAK_PANIC); } +static MyThread errDispThread; +static u8 ALIGN(8) errDispThreadStack[0xD00]; + static char userString[0x100 + 1] = {0}; +static char staticBuf[0x100 + 1] = {0}; + +MyThread *errDispCreateThread(void) +{ + if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0xD00, 0x18, CORE_SYSTEM))) + svcBreak(USERBREAK_PANIC); + return &errDispThread; +} static inline u32 ERRF_DisplayRegisterValue(u32 posX, u32 posY, const char *name, u32 value) { @@ -230,9 +243,8 @@ static Result ERRF_SaveErrorToFile(ERRF_FatalErrInfo *info) return res; } -void ERRF_HandleCommands(void *ctx) +void ERRF_HandleCommands(void) { - (void)ctx; u32 *cmdbuf = getThreadCommandBuffer(); ERRF_FatalErrInfo info; @@ -264,26 +276,98 @@ void ERRF_HandleCommands(void *ctx) __builtin_unreachable(); } - cmdbuf[0] = 0x10040; + cmdbuf[0] = IPC_MakeHeader(1, 1, 0); cmdbuf[1] = 0; break; } case 2: // SetUserString { - if(cmdbuf[0] != 0x20042 || (cmdbuf[2] & 0x3C0F) != 2) + if(cmdbuf[0] != IPC_MakeHeader(2, 1, 2) || (cmdbuf[2] & 0x3C0F) != 2) { - cmdbuf[0] = 0x40; + cmdbuf[0] = IPC_MakeHeader(0, 1, 0); cmdbuf[1] = 0xD9001830; } else { - cmdbuf[0] = 0x20040; u32 sz = cmdbuf[1] <= 0x100 ? cmdbuf[1] : 0x100; memcpy(userString, cmdbuf + 3, sz); userString[sz] = 0; + + cmdbuf[0] = IPC_MakeHeader(2, 1, 0); + cmdbuf[1] = 0; } break; } } } + +void errDispThreadMain(void) +{ + Handle handles[3]; + Handle serverHandle, clientHandle, sessionHandle = 0; + + u32 replyTarget = 0; + s32 index; + + Result res; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *sbuf = getThreadStaticBuffers(); + + sbuf[0] = IPC_Desc_StaticBuffer(0x100, 0); + sbuf[1] = (u32)staticBuf; + + assertSuccess(svcCreatePort(&serverHandle, &clientHandle, "err:f", 1)); + + do + { + handles[0] = terminationRequestEvent; + handles[1] = serverHandle; + handles[2] = sessionHandle; + + if(replyTarget == 0) // k11 + cmdbuf[0] = 0xFFFF0000; + res = svcReplyAndReceive(&index, handles, 1 + (sessionHandle == 0 ? 1 : 2), replyTarget); + + if(R_FAILED(res)) + { + if((u32)res == 0xC920181A) // session closed by remote + { + svcCloseHandle(sessionHandle); + sessionHandle = 0; + replyTarget = 0; + } + + else + svcBreak(USERBREAK_PANIC); + } + + else + { + if (index == 0) + { + break; + } + else if(index == 1) + { + Handle session; + assertSuccess(svcAcceptSession(&session, serverHandle)); + + if(sessionHandle == 0) + sessionHandle = session; + else + svcCloseHandle(session); + } + else + { + ERRF_HandleCommands(); + replyTarget = sessionHandle; + } + } + } + while(!terminationRequest); + + svcCloseHandle(sessionHandle); + svcCloseHandle(clientHandle); + svcCloseHandle(serverHandle); +} diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index e557277..440d1e8 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -170,7 +170,6 @@ static void handleNextApplicationDebuggedByForce(u32 notificationId) } static const ServiceManagerServiceEntry services[] = { - { "err:f", 1, ERRF_HandleCommands, true }, { "hb:ldr", 2, HBLDR_HandleCommands, true }, { NULL }, }; @@ -198,12 +197,14 @@ int main(void) MyThread *menuThread = menuCreateThread(); MyThread *taskRunnerThread = taskRunnerCreateThread(); + MyThread *errDispThread = errDispCreateThread(); if (R_FAILED(ServiceManager_Run(services, notifications, NULL))) svcBreak(USERBREAK_PANIC); MyThread_Join(menuThread, -1LL); MyThread_Join(taskRunnerThread, -1LL); + MyThread_Join(errDispThread, -1LL); return 0; } From a67e8e60c6dd17bd6048366dbac48b2f1cdfbdec Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 16 Apr 2020 19:50:18 +0100 Subject: [PATCH 17/18] rosalina: screen_filter: save up around 10K using this simple trick --- sysmodules/rosalina/Makefile | 4 ++-- sysmodules/rosalina/source/menus/screen_filters.c | 4 ++-- sysmodules/rosalina/source/redshift/colorramp.c | 10 ++++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sysmodules/rosalina/Makefile b/sysmodules/rosalina/Makefile index fdbec83..0616f6f 100644 --- a/sysmodules/rosalina/Makefile +++ b/sysmodules/rosalina/Makefile @@ -29,7 +29,7 @@ ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Wno-unused-value -O2 -mword-relocations \ - -fomit-frame-pointer -ffunction-sections -fdata-sections \ + -fomit-frame-pointer -ffunction-sections -fdata-sections -ffast-math \ $(ARCH) $(DEFINES) CFLAGS += $(INCLUDE) @@ -39,7 +39,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000 -LIBS := -lctru -lm +LIBS := -lctru #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index ca7932b..481e343 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -144,10 +144,10 @@ void screenFiltersSetTemperature(int temperature) memset(&cs, 0, sizeof(cs)); cs.temperature = temperature; - cs.gamma[0] = 1.0F; + /*cs.gamma[0] = 1.0F; cs.gamma[1] = 1.0F; cs.gamma[2] = 1.0F; - cs.brightness = 1.0F; + cs.brightness = 1.0F;*/ applyColorSettings(&cs); } diff --git a/sysmodules/rosalina/source/redshift/colorramp.c b/sysmodules/rosalina/source/redshift/colorramp.c index 6d647a9..e24b9d7 100644 --- a/sysmodules/rosalina/source/redshift/colorramp.c +++ b/sysmodules/rosalina/source/redshift/colorramp.c @@ -19,7 +19,7 @@ */ #include -#include +//#include #include "redshift/redshift.h" @@ -282,8 +282,10 @@ interpolate_color(float a, const float *c1, const float *c2, float *c) } /* Helper macro used in the fill functions */ -#define F(Y, C) pow((Y) * setting->brightness * \ - white_point[C], 1.0/setting->gamma[C]) +#define F(Y, C) ((Y) * white_point[C]) + +/*#define F(Y, C) pow((Y) * setting->brightness * \ + white_point[C], 1.0/setting->gamma[C])*/ void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b, @@ -324,4 +326,4 @@ colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b, } } -#undef F \ No newline at end of file +#undef F From 8785fd0236732d7fc20f5595beb881dc47fd265d Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 16 Apr 2020 21:05:33 +0100 Subject: [PATCH 18/18] Use -Os for rosalina, pm, sm. Decrease gdb buffer sizes, etc. --- sysmodules/pm/Makefile | 2 +- sysmodules/rosalina/Makefile | 4 ++-- sysmodules/rosalina/include/gdb.h | 4 ++-- sysmodules/sm/Makefile | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sysmodules/pm/Makefile b/sysmodules/pm/Makefile index b14d489..63ba36f 100644 --- a/sysmodules/pm/Makefile +++ b/sysmodules/pm/Makefile @@ -28,7 +28,7 @@ INCLUDES := include ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \ +CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Os -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections \ $(ARCH) $(DEFINES) diff --git a/sysmodules/rosalina/Makefile b/sysmodules/rosalina/Makefile index 0616f6f..e88238b 100644 --- a/sysmodules/rosalina/Makefile +++ b/sysmodules/rosalina/Makefile @@ -28,8 +28,8 @@ INCLUDES := include include/gdb include/menus include/redshift ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Wno-unused-value -O2 -mword-relocations \ - -fomit-frame-pointer -ffunction-sections -fdata-sections -ffast-math \ +CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Wno-unused-value -Os -mword-relocations \ + -fomit-frame-pointer -ffunction-sections -fdata-sections -fno-math-errno \ $(ARCH) $(DEFINES) CFLAGS += $(INCLUDE) diff --git a/sysmodules/rosalina/include/gdb.h b/sysmodules/rosalina/include/gdb.h index aa1499f..b9266a2 100644 --- a/sysmodules/rosalina/include/gdb.h +++ b/sysmodules/rosalina/include/gdb.h @@ -18,14 +18,14 @@ #define MAX_DEBUG 3 #define MAX_DEBUG_THREAD 127 -#define MAX_BREAKPOINT 256 +#define MAX_BREAKPOINT 64 #define MAX_TIO_OPEN_FILE 32 // 512+24 is the ideal size as IDA will try to read exactly 0x100 bytes at a time. Add 4 to this, for $#, see below. // IDA seems to want additional bytes as well. // 1024 is fine enough to put all regs in the 'T' stop reply packets -#define GDB_BUF_LEN 2048 +#define GDB_BUF_LEN 1024 #define GDB_HANDLER(name) GDB_Handle##name #define GDB_QUERY_HANDLER(name) GDB_HANDLER(Query##name) diff --git a/sysmodules/sm/Makefile b/sysmodules/sm/Makefile index b14d489..63ba36f 100644 --- a/sysmodules/sm/Makefile +++ b/sysmodules/sm/Makefile @@ -28,7 +28,7 @@ INCLUDES := include ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \ +CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Os -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections \ $(ARCH) $(DEFINES)