diff --git a/.gitignore b/.gitignore
index e5c172f3a..6ab80d7f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@ exceptions/arm11/build
*.elf
*.cxi
*.3dsx
+*.lst
.DS_Store
*.dmp
.project
diff --git a/sysmodules/rosalina/include/debugger.h b/sysmodules/rosalina/include/debugger.h
new file mode 100644
index 000000000..649d56c85
--- /dev/null
+++ b/sysmodules/rosalina/include/debugger.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of Luma3DS
+ * Copyright (C) 2016-2020 Aurora Wright, TuxSH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+ * * Requiring preservation of specified reasonable legal notices or
+ * author attributions in that material or in the Appropriate Legal
+ * Notices displayed by works containing it.
+ * * Prohibiting misrepresentation of the origin of that material,
+ * or requiring that modified versions of such material be marked in
+ * reasonable ways as different from the original version.
+ */
+
+#pragma once
+#include <3ds/types.h>
+#include "gdb/server.h"
+#include "gdb/debug.h"
+#include "gdb/monitor.h"
+#include "gdb/net.h"
+#include "MyThread.h"
+
+extern GDBServer gdbServer;
+extern GDBContext *nextApplicationGdbCtx;
+
+MyThread *debuggerCreateSocketThread(void);
+MyThread *debuggerCreateDebugThread(void);
+void debuggerSocketThreadMain(void);
+void debuggerDebugThreadMain(void);
+
+void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata);
+
+Result debuggerDisable(s64 timeout);
+Result debuggerEnable(s64 timeout);
+Result debugNextApplicationByForce();
+
+// Not sure if actually needed, but I keep it as it is just in case, from my tests, simply using debugNextApplicationByForce is sufficient
+void handleNextApplicationDebuggedByForce(u32 notificationId);
+
+void handleRosalinaDebugger(void *ctx);
\ No newline at end of file
diff --git a/sysmodules/rosalina/include/menus/debugger.h b/sysmodules/rosalina/include/menus/debugger.h
deleted file mode 100644
index 4dec5fefa..000000000
--- a/sysmodules/rosalina/include/menus/debugger.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-* This file is part of Luma3DS
-* Copyright (C) 2016-2020 Aurora Wright, TuxSH
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*
-* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
-* * Requiring preservation of specified reasonable legal notices or
-* author attributions in that material or in the Appropriate Legal
-* Notices displayed by works containing it.
-* * Prohibiting misrepresentation of the origin of that material,
-* or requiring that modified versions of such material be marked in
-* reasonable ways as different from the original version.
-*/
-
-#pragma once
-
-#include <3ds/types.h>
-#include "menu.h"
-
-extern Menu debuggerMenu;
-
-void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata);
-Result debuggerDisable(s64 timeout);
-
-void DebuggerMenu_EnableDebugger(void);
-void DebuggerMenu_DisableDebugger(void);
-void DebuggerMenu_DebugNextApplicationByForce(void);
diff --git a/sysmodules/rosalina/include/menus/debugger_menu.h b/sysmodules/rosalina/include/menus/debugger_menu.h
new file mode 100644
index 000000000..617721dfb
--- /dev/null
+++ b/sysmodules/rosalina/include/menus/debugger_menu.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of Luma3DS
+ * Copyright (C) 2016-2020 Aurora Wright, TuxSH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+ * * Requiring preservation of specified reasonable legal notices or
+ * author attributions in that material or in the Appropriate Legal
+ * Notices displayed by works containing it.
+ * * Prohibiting misrepresentation of the origin of that material,
+ * or requiring that modified versions of such material be marked in
+ * reasonable ways as different from the original version.
+ */
+
+#pragma once
+
+#include "menu.h"
+#include "debugger.h"
+#include <3ds/types.h>
+extern Menu debuggerMenu;
+
+void DebuggerMenu_EnableDebugger(void);
+void DebuggerMenu_DisableDebugger(void);
+void DebuggerMenu_DebugNextApplicationByForce(void);
diff --git a/sysmodules/rosalina/source/debugger.c b/sysmodules/rosalina/source/debugger.c
new file mode 100644
index 000000000..ae3232228
--- /dev/null
+++ b/sysmodules/rosalina/source/debugger.c
@@ -0,0 +1,210 @@
+/*
+ * This file is part of Luma3DS
+ * Copyright (C) 2016-2020 Aurora Wright, TuxSH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+ * * Requiring preservation of specified reasonable legal notices or
+ * author attributions in that material or in the Appropriate Legal
+ * Notices displayed by works containing it.
+ * * Prohibiting misrepresentation of the origin of that material,
+ * or requiring that modified versions of such material be marked in
+ * reasonable ways as different from the original version.
+ */
+
+#include "debugger.h"
+#include "memory.h"
+#include "minisoc.h"
+#include "fmt.h"
+#include "pmdbgext.h"
+#include "pmdbgext.h"
+#include "MyThread.h"
+#include "task_runner.h"
+#include <3ds.h>
+#include <3ds/ipc.h>
+#include <3ds/services/cfgu.h>
+#include <3ds/applets/error.h>
+#include "menu.h"
+
+GDBServer gdbServer = {0};
+GDBContext *nextApplicationGdbCtx = NULL;
+
+static MyThread debuggerSocketThread;
+static MyThread debuggerDebugThread;
+static u8 ALIGN(8) debuggerSocketThreadStack[0x5000];
+static u8 ALIGN(8) debuggerDebugThreadStack[0x3000];
+
+void debuggerSocketThreadMain(void)
+{
+ GDB_IncrementServerReferenceCount(&gdbServer);
+ GDB_RunServer(&gdbServer);
+ GDB_DecrementServerReferenceCount(&gdbServer);
+}
+
+MyThread *debuggerCreateSocketThread(void)
+{
+ MyThread_Create(&debuggerSocketThread, debuggerSocketThreadMain, debuggerSocketThreadStack, 0x5000, 0x20, CORE_SYSTEM);
+ return &debuggerSocketThread;
+}
+
+void debuggerDebugThreadMain(void)
+{
+ GDB_IncrementServerReferenceCount(&gdbServer);
+ GDB_RunMonitor(&gdbServer);
+ GDB_DecrementServerReferenceCount(&gdbServer);
+}
+
+MyThread *debuggerCreateDebugThread(void)
+{
+ MyThread_Create(&debuggerDebugThread, debuggerDebugThreadMain, debuggerDebugThreadStack, 0x3000, 0x20, CORE_SYSTEM);
+ return &debuggerDebugThread;
+}
+
+void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata)
+{
+ (void)argdata;
+ if (!nextApplicationGdbCtx)
+ return;
+ Handle debug = 0;
+ PMDBG_RunQueuedProcess(&debug);
+ GDB_LockAllContexts(&gdbServer);
+ nextApplicationGdbCtx->debug = debug;
+ if (debug == 0)
+ nextApplicationGdbCtx->flags = 0;
+ else
+ nextApplicationGdbCtx->flags |= GDB_FLAG_ATTACHED_AT_START;
+ nextApplicationGdbCtx = NULL;
+ GDB_UnlockAllContexts(&gdbServer);
+}
+
+Result debuggerDisable(s64 timeout)
+{
+ Result res = 0;
+ bool initialized = gdbServer.referenceCount != 0;
+ if (initialized)
+ {
+ svcSignalEvent(gdbServer.super.shall_terminate_event);
+ server_kill_connections(&gdbServer.super);
+
+ res = MyThread_Join(&debuggerDebugThread, timeout);
+ if (res == 0)
+ res = MyThread_Join(&debuggerSocketThread, timeout);
+
+ Handle dummy = 0;
+ PMDBG_RunQueuedProcess(&dummy);
+ svcCloseHandle(dummy);
+ PMDBG_DebugNextApplicationByForce(false);
+ nextApplicationGdbCtx = NULL;
+ }
+
+ return res;
+}
+
+Result debuggerEnable(s64 timeout)
+{
+ Result res = 0;
+ bool initialized = gdbServer.super.running;
+ if (!initialized)
+ {
+ res = GDB_InitializeServer(&gdbServer);
+ Handle handles[3] = {gdbServer.super.started_event, gdbServer.super.shall_terminate_event, preTerminationEvent};
+ s32 idx;
+ if (res == 0)
+ {
+ debuggerCreateSocketThread();
+ debuggerCreateDebugThread();
+ res = svcWaitSynchronizationN(&idx, handles, 3, false, timeout);
+ if (res == 0)
+ res = gdbServer.super.init_result;
+ }
+ }
+ return res;
+}
+
+Result debugNextApplicationByForce()
+{
+ Result res = 0;
+ if (nextApplicationGdbCtx != NULL)
+ return 0;
+ else
+ {
+ nextApplicationGdbCtx = GDB_SelectAvailableContext(&gdbServer, GDB_PORT_BASE + 3, GDB_PORT_BASE + 4);
+ if (nextApplicationGdbCtx != NULL)
+ {
+ nextApplicationGdbCtx->debug = 0;
+ nextApplicationGdbCtx->pid = 0xFFFFFFFF;
+ res = PMDBG_DebugNextApplicationByForce(true);
+ if (R_SUCCEEDED(res))
+ return 1;
+ else
+ {
+ nextApplicationGdbCtx->flags = 0;
+ nextApplicationGdbCtx->localPort = 0;
+ nextApplicationGdbCtx = NULL;
+ return res;
+ }
+ }
+ else
+ return 2;
+ }
+}
+
+void handleRosalinaDebugger(void *ctx)
+{
+ (void)ctx;
+ u32 *cmdbuf = getThreadCommandBuffer();
+ Result res = 0;
+ switch (cmdbuf[0] >> 16)
+ {
+ case 1: // Enable debugger
+ if (cmdbuf[0] != IPC_MakeHeader(1, 1, 0))
+ {
+ cmdbuf[0] = IPC_MakeHeader(0, 1, 0);
+ cmdbuf[1] = 0xD9001830;
+ break;
+ }
+ if (cmdbuf[1])
+ {
+ res = debuggerEnable(5 * 1000 * 1000 * 1000LL);
+ }
+ else
+ {
+ res = debuggerDisable(2 * 1000 * 1000 * 1000LL);
+ }
+
+ cmdbuf[0] = IPC_MakeHeader(0, 1, 0);
+ cmdbuf[1] = res;
+ break;
+ case 2: // Debug next process
+ if (cmdbuf[0] != IPC_MakeHeader(2, 0, 0))
+ {
+ cmdbuf[0] = IPC_MakeHeader(0, 1, 0);
+ cmdbuf[1] = 0xD9001830;
+ break;
+ }
+ GDB_LockAllContexts(&gdbServer);
+ res = debugNextApplicationByForce();
+ GDB_UnlockAllContexts(&gdbServer);
+ cmdbuf[1] = res;
+ break;
+ }
+}
+
+void handleNextApplicationDebuggedByForce(u32 notificationId)
+{
+ (void)notificationId;
+ // Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread.
+ TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, NULL, 0);
+}
\ No newline at end of file
diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c
index 6bd77cb63..6efcc8762 100644
--- a/sysmodules/rosalina/source/main.c
+++ b/sysmodules/rosalina/source/main.c
@@ -1,30 +1,31 @@
/*
-* This file is part of Luma3DS
-* Copyright (C) 2016-2021 Aurora Wright, TuxSH
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*
-* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
-* * Requiring preservation of specified reasonable legal notices or
-* author attributions in that material or in the Appropriate Legal
-* Notices displayed by works containing it.
-* * Prohibiting misrepresentation of the origin of that material,
-* or requiring that modified versions of such material be marked in
-* reasonable ways as different from the original version.
-*/
+ * This file is part of Luma3DS
+ * Copyright (C) 2016-2021 Aurora Wright, TuxSH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+ * * Requiring preservation of specified reasonable legal notices or
+ * author attributions in that material or in the Appropriate Legal
+ * Notices displayed by works containing it.
+ * * Prohibiting misrepresentation of the origin of that material,
+ * or requiring that modified versions of such material be marked in
+ * reasonable ways as different from the original version.
+ */
#include <3ds.h>
+#include <3ds/services/hid.h>
#include "memory.h"
#include "menu.h"
#include "service_manager.h"
@@ -32,7 +33,7 @@
#include "utils.h"
#include "MyThread.h"
#include "menus/miscellaneous.h"
-#include "menus/debugger.h"
+#include "menus/debugger_menu.h"
#include "menus/screen_filters.h"
#include "menus/cheats.h"
#include "menus/sysconfig.h"
@@ -40,6 +41,7 @@
#include "minisoc.h"
#include "draw.h"
#include "bootdiag.h"
+#include "debugger.h"
#include "task_runner.h"
@@ -86,14 +88,12 @@ void initSystem(void)
svcGetSystemInfo(&out, 0x10000, 0x103);
lastNtpTzOffset = (s16)out;
- miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ?
- "Switch the hb. title to the current app." :
- "Switch the hb. title to " HBLDR_DEFAULT_3DSX_TITLE_NAME;
+ miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." : "Switch the hb. title to " HBLDR_DEFAULT_3DSX_TITLE_NAME;
- for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
+ for (res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL))
{
res = srvInit();
- if(R_FAILED(res) && res != (Result)0xD88007FA)
+ if (R_FAILED(res) && res != (Result)0xD88007FA)
svcBreak(USERBREAK_PANIC);
}
@@ -138,29 +138,30 @@ static void handleSleepNotification(u32 notificationId)
s32 ackValue = ptmSysmGetNotificationAckValue(notificationId);
switch (notificationId)
{
- case PTMNOTIFID_SLEEP_REQUESTED:
- menuShouldExit = true;
- PTMSYSM_ReplyToSleepQuery(miniSocEnabled); // deny sleep request if we have network stuff running
- break;
- case PTMNOTIFID_GOING_TO_SLEEP:
- case PTMNOTIFID_SLEEP_ALLOWED:
- case PTMNOTIFID_FULLY_WAKING_UP:
- case PTMNOTIFID_HALF_AWAKE:
- PTMSYSM_NotifySleepPreparationComplete(ackValue);
- break;
- case PTMNOTIFID_SLEEP_DENIED:
- case PTMNOTIFID_FULLY_AWAKE:
- menuShouldExit = false;
- break;
- default:
- break;
+ case PTMNOTIFID_SLEEP_REQUESTED:
+ menuShouldExit = true;
+ PTMSYSM_ReplyToSleepQuery(miniSocEnabled); // deny sleep request if we have network stuff running
+ break;
+ case PTMNOTIFID_GOING_TO_SLEEP:
+ case PTMNOTIFID_SLEEP_ALLOWED:
+ case PTMNOTIFID_FULLY_WAKING_UP:
+ case PTMNOTIFID_HALF_AWAKE:
+ PTMSYSM_NotifySleepPreparationComplete(ackValue);
+ break;
+ case PTMNOTIFID_SLEEP_DENIED:
+ case PTMNOTIFID_FULLY_AWAKE:
+ menuShouldExit = false;
+ break;
+ default:
+ break;
}
ptmSysmExit();
}
static void handleShellNotification(u32 notificationId)
{
- if (notificationId == 0x213) {
+ if (notificationId == 0x213)
+ {
// Shell opened
// Note that this notification is also fired on system init.
// Sequence goes like this: MCU fires notif. 0x200 on shell open
@@ -173,11 +174,12 @@ static void handleShellNotification(u32 notificationId)
if (isServiceUsable("gsp::Gpu"))
ScreenFiltersMenu_RestoreSettings();
menuShouldExit = false;
- } else {
+ }
+ else
+ {
// Shell closed
menuShouldExit = true;
}
-
}
static void handlePreTermNotification(u32 notificationId)
@@ -194,7 +196,7 @@ static void handlePreTermNotification(u32 notificationId)
debuggerDisable(100 * 1000 * 1000LL);
// Kill the ac session if needed
- if(isConnectionForced)
+ if (isConnectionForced)
{
acExit();
isConnectionForced = false;
@@ -212,13 +214,6 @@ static void handlePreTermNotification(u32 notificationId)
Draw_Unlock();
}
-static void handleNextApplicationDebuggedByForce(u32 notificationId)
-{
- (void)notificationId;
- // Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread.
- TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, NULL, 0);
-}
-
#if 0
static void handleRestartHbAppNotification(u32 notificationId)
{
@@ -228,28 +223,26 @@ static void handleRestartHbAppNotification(u32 notificationId)
#endif
static const ServiceManagerServiceEntry services[] = {
- { NULL },
-};
+ {"rosalina:dbg", 2, handleRosalinaDebugger, false}, {NULL}};
static const ServiceManagerNotificationEntry notifications[] = {
- { 0x100 , handleTermNotification },
- { PTMNOTIFID_SLEEP_REQUESTED, handleSleepNotification },
- { PTMNOTIFID_SLEEP_DENIED, handleSleepNotification },
- { PTMNOTIFID_SLEEP_ALLOWED, handleSleepNotification },
- { PTMNOTIFID_GOING_TO_SLEEP, handleSleepNotification },
- { PTMNOTIFID_FULLY_WAKING_UP, handleSleepNotification },
- { PTMNOTIFID_FULLY_AWAKE, handleSleepNotification },
- { PTMNOTIFID_HALF_AWAKE, handleSleepNotification },
- { 0x213, handleShellNotification },
- { 0x214, handleShellNotification },
- { 0x1000, handleNextApplicationDebuggedByForce },
- { 0x2000, handlePreTermNotification },
- { 0x000, NULL },
-};
+ {0x100, handleTermNotification},
+ {PTMNOTIFID_SLEEP_REQUESTED, handleSleepNotification},
+ {PTMNOTIFID_SLEEP_DENIED, handleSleepNotification},
+ {PTMNOTIFID_SLEEP_ALLOWED, handleSleepNotification},
+ {PTMNOTIFID_GOING_TO_SLEEP, handleSleepNotification},
+ {PTMNOTIFID_FULLY_WAKING_UP, handleSleepNotification},
+ {PTMNOTIFID_FULLY_AWAKE, handleSleepNotification},
+ {PTMNOTIFID_HALF_AWAKE, handleSleepNotification},
+ {0x213, handleShellNotification},
+ {0x214, handleShellNotification},
+ {0x1000, handleNextApplicationDebuggedByForce},
+ {0x2000, handlePreTermNotification},
+ {0x000, NULL}};
int main(void)
{
- if(R_FAILED(svcCreateEvent(&preTerminationEvent, RESET_STICKY)))
+ if (R_FAILED(svcCreateEvent(&preTerminationEvent, RESET_STICKY)))
svcBreak(USERBREAK_ASSERT);
Draw_Init();
diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c
index 48e627c34..383b06620 100644
--- a/sysmodules/rosalina/source/menus.c
+++ b/sysmodules/rosalina/source/menus.c
@@ -1,28 +1,28 @@
/*
-* This file is part of Luma3DS
-* Copyright (C) 2016-2020 Aurora Wright, TuxSH
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*
-* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
-* * Requiring preservation of specified reasonable legal notices or
-* author attributions in that material or in the Appropriate Legal
-* Notices displayed by works containing it.
-* * Prohibiting misrepresentation of the origin of that material,
-* or requiring that modified versions of such material be marked in
-* reasonable ways as different from the original version.
-*/
+ * This file is part of Luma3DS
+ * Copyright (C) 2016-2020 Aurora Wright, TuxSH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+ * * Requiring preservation of specified reasonable legal notices or
+ * author attributions in that material or in the Appropriate Legal
+ * Notices displayed by works containing it.
+ * * Prohibiting misrepresentation of the origin of that material,
+ * or requiring that modified versions of such material be marked in
+ * reasonable ways as different from the original version.
+ */
#include <3ds.h>
#include <3ds/os.h>
@@ -31,7 +31,7 @@
#include "draw.h"
#include "menus/process_list.h"
#include "menus/n3ds.h"
-#include "menus/debugger.h"
+#include "menus/debugger_menu.h"
#include "menus/miscellaneous.h"
#include "menus/sysconfig.h"
#include "menus/screen_filters.h"
@@ -45,23 +45,22 @@
Menu rosalinaMenu = {
"Rosalina menu",
{
- { "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 },
- { "System configuration...", MENU, .menu = &sysconfigMenu },
- { "Screen filters...", MENU, .menu = &screenFiltersMenu },
- { "New 3DS menu...", MENU, .menu = &N3DSMenu, .visibility = &menuCheckN3ds },
- { "Miscellaneous options...", MENU, .menu = &miscellaneousMenu },
- { "Save settings", METHOD, .method = &RosalinaMenu_SaveSettings },
- { "Power off", METHOD, .method = &RosalinaMenu_PowerOff },
- { "Reboot", METHOD, .method = &RosalinaMenu_Reboot },
- { "Credits", METHOD, .method = &RosalinaMenu_ShowCredits },
- { "Debug info", METHOD, .method = &RosalinaMenu_ShowDebugInfo, .visibility = &rosalinaMenuShouldShowDebugInfo },
+ {"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},
+ {"System configuration...", MENU, .menu = &sysconfigMenu},
+ {"Screen filters...", MENU, .menu = &screenFiltersMenu},
+ {"New 3DS menu...", MENU, .menu = &N3DSMenu, .visibility = &menuCheckN3ds},
+ {"Miscellaneous options...", MENU, .menu = &miscellaneousMenu},
+ {"Save settings", METHOD, .method = &RosalinaMenu_SaveSettings},
+ {"Power off", METHOD, .method = &RosalinaMenu_PowerOff},
+ {"Reboot", METHOD, .method = &RosalinaMenu_Reboot},
+ {"Credits", METHOD, .method = &RosalinaMenu_ShowCredits},
+ {"Debug info", METHOD, .method = &RosalinaMenu_ShowDebugInfo, .visibility = &rosalinaMenuShouldShowDebugInfo},
{},
- }
-};
+ }};
bool rosalinaMenuShouldShowDebugInfo(void)
{
@@ -84,14 +83,13 @@ void RosalinaMenu_SaveSettings(void)
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Save settings");
- if(R_SUCCEEDED(res))
+ if (R_SUCCEEDED(res))
Draw_DrawString(10, 30, COLOR_WHITE, "Operation succeeded.");
else
Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Operation failed (0x%08lx).", res);
Draw_FlushFramebuffer();
Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
}
void RosalinaMenu_ShowDebugInfo(void)
@@ -121,14 +119,12 @@ void RosalinaMenu_ShowDebugInfo(void)
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Kernel ext PA: %08lx - %08lx\n\n", kextPa, kextPa + kextSize);
posY = Draw_DrawFormattedString(
10, posY, COLOR_WHITE, "Kernel version: %lu.%lu-%lu\n",
- GET_VERSION_MAJOR(kernelVer), GET_VERSION_MINOR(kernelVer), GET_VERSION_REVISION(kernelVer)
- );
+ GET_VERSION_MAJOR(kernelVer), GET_VERSION_MINOR(kernelVer), GET_VERSION_REVISION(kernelVer));
if (mcuFwVersion != 0)
{
posY = Draw_DrawFormattedString(
10, posY, COLOR_WHITE, "MCU FW version: %lu.%lu\n",
- GET_VERSION_MAJOR(mcuFwVersion), GET_VERSION_MINOR(mcuFwVersion)
- );
+ GET_VERSION_MAJOR(mcuFwVersion), GET_VERSION_MINOR(mcuFwVersion));
}
if (R_SUCCEEDED(FSUSER_GetSdmcSpeedInfo(&speedInfo)))
@@ -136,27 +132,23 @@ void RosalinaMenu_ShowDebugInfo(void)
u32 clkDiv = 1 << (1 + (speedInfo.sdClkCtrl & 0xFF));
posY = Draw_DrawFormattedString(
10, posY, COLOR_WHITE, "SDMC speed: HS=%d %lukHz\n",
- (int)speedInfo.highSpeedModeEnabled, SYSCLOCK_SDMMC / (1000 * clkDiv)
- );
+ (int)speedInfo.highSpeedModeEnabled, SYSCLOCK_SDMMC / (1000 * clkDiv));
}
if (R_SUCCEEDED(FSUSER_GetNandSpeedInfo(&speedInfo)))
{
u32 clkDiv = 1 << (1 + (speedInfo.sdClkCtrl & 0xFF));
posY = Draw_DrawFormattedString(
10, posY, COLOR_WHITE, "NAND speed: HS=%d %lukHz\n",
- (int)speedInfo.highSpeedModeEnabled, SYSCLOCK_SDMMC / (1000 * clkDiv)
- );
+ (int)speedInfo.highSpeedModeEnabled, SYSCLOCK_SDMMC / (1000 * clkDiv));
}
{
posY = Draw_DrawFormattedString(
10, posY, COLOR_WHITE, "APPMEMTYPE: %lu\n",
- OS_KernelConfig->app_memtype
- );
+ OS_KernelConfig->app_memtype);
}
Draw_FlushFramebuffer();
Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
}
void RosalinaMenu_ShowCredits(void)
@@ -180,17 +172,15 @@ void RosalinaMenu_ShowCredits(void)
posY += 2 * SPACING_Y;
Draw_DrawString(10, posY, COLOR_WHITE,
- (
- "Special thanks to:\n"
- " fincs, WinterMute, mtheall, piepie62,\n"
- " Luma3DS contributors, libctru contributors,\n"
- " other people"
- ));
+ (
+ "Special thanks to:\n"
+ " fincs, WinterMute, mtheall, piepie62,\n"
+ " Luma3DS contributors, libctru contributors,\n"
+ " other people"));
Draw_FlushFramebuffer();
Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
}
void RosalinaMenu_Reboot(void)
@@ -210,15 +200,15 @@ void RosalinaMenu_Reboot(void)
u32 pressed = waitInputWithTimeout(1000);
- if(pressed & KEY_A)
+ if (pressed & KEY_A)
{
menuLeave();
APT_HardwareResetAsync();
return;
- } else if(pressed & KEY_B)
+ }
+ else if (pressed & KEY_B)
return;
- }
- while(!menuShouldExit);
+ } while (!menuShouldExit);
}
void RosalinaMenu_ChangeScreenBrightness(void)
@@ -246,8 +236,7 @@ void RosalinaMenu_ChangeScreenBrightness(void)
"Current luminance: %lu (min. %lu, max. %lu)\n\n",
luminance,
minLum,
- maxLum
- );
+ maxLum);
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Controls: Up/Down for +-1, Right/Left for +-10.\n");
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press A to start, B to exit.\n\n");
@@ -264,8 +253,7 @@ void RosalinaMenu_ChangeScreenBrightness(void)
if (pressed & KEY_B)
return;
- }
- while (!menuShouldExit);
+ } while (!menuShouldExit);
Draw_Lock();
@@ -273,7 +261,7 @@ void RosalinaMenu_ChangeScreenBrightness(void)
Draw_FreeFramebufferCache();
svcKernelSetState(0x10000, 2); // unblock gsp
- gspLcdInit(); // assume it doesn't fail. If it does, brightness won't change, anyway.
+ gspLcdInit(); // assume it doesn't fail. If it does, brightness won't change, anyway.
// gsp:LCD will normalize the brightness between top/bottom screen, handle PWM, etc.
@@ -303,8 +291,7 @@ void RosalinaMenu_ChangeScreenBrightness(void)
if (pressed & KEY_B)
break;
- }
- while (!menuShouldExit);
+ } while (!menuShouldExit);
gspLcdExit();
svcKernelSetState(0x10000, 2); // block gsp again
@@ -337,20 +324,20 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
u32 pressed = waitInputWithTimeout(1000);
- if(pressed & KEY_A)
+ if (pressed & KEY_A)
{
menuLeave();
srvPublishToSubscriber(0x203, 0);
return;
}
- else if(pressed & KEY_B)
+ else if (pressed & KEY_B)
return;
- }
- while(!menuShouldExit);
+ } while (!menuShouldExit);
}
-
-#define TRY(expr) if(R_FAILED(res = (expr))) goto end;
+#define TRY(expr) \
+ if (R_FAILED(res = (expr))) \
+ goto end;
static s64 timeSpentConvertingScreenshot = 0;
static s64 timeSpentWritingScreenshot = 0;
@@ -390,7 +377,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, boo
remaining -= lineSize * nlines;
buf = framebufferCache;
}
- end:
+end:
Draw_FreeFramebufferCache();
return res;
@@ -412,7 +399,8 @@ void RosalinaMenu_TakeScreenshot(void)
timeSpentConvertingScreenshot = 0;
timeSpentWritingScreenshot = 0;
- if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT);
+ if (R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203)))
+ svcBreak(USERBREAK_ASSERT);
isSdMode = (bool)out;
archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
@@ -429,10 +417,10 @@ void RosalinaMenu_TakeScreenshot(void)
Draw_GetCurrentScreenInfo(&topWidth, &is3d, true);
res = FSUSER_OpenArchive(&archive, archiveId, fsMakePath(PATH_EMPTY, ""));
- if(R_SUCCEEDED(res))
+ if (R_SUCCEEDED(res))
{
res = FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/luma/screenshots"), 0);
- if((u32)res == 0xC82044BE) // directory already exists
+ if ((u32)res == 0xC82044BE) // directory already exists
res = 0;
FSUSER_CloseArchive(archive);
}
@@ -449,7 +437,7 @@ void RosalinaMenu_TakeScreenshot(void)
TRY(RosalinaMenu_WriteScreenshot(&file, bottomWidth, false, true));
TRY(IFile_Close(&file));
- if(is3d && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false)))
+ if (is3d && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false)))
{
sprintf(filename, "/luma/screenshots/%s_top_right.bmp", dateTimeStr);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
@@ -471,7 +459,7 @@ void RosalinaMenu_TakeScreenshot(void)
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Screenshot");
- if(R_FAILED(res))
+ if (R_FAILED(res))
Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Operation failed (0x%08lx).", (u32)res);
else
{
@@ -485,8 +473,7 @@ void RosalinaMenu_TakeScreenshot(void)
Draw_FlushFramebuffer();
Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
#undef TRY
}
diff --git a/sysmodules/rosalina/source/menus/debugger.c b/sysmodules/rosalina/source/menus/debugger.c
deleted file mode 100644
index 7d3eda1c3..000000000
--- a/sysmodules/rosalina/source/menus/debugger.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
-* This file is part of Luma3DS
-* Copyright (C) 2016-2020 Aurora Wright, TuxSH
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program. If not, see .
-*
-* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
-* * Requiring preservation of specified reasonable legal notices or
-* author attributions in that material or in the Appropriate Legal
-* Notices displayed by works containing it.
-* * Prohibiting misrepresentation of the origin of that material,
-* or requiring that modified versions of such material be marked in
-* reasonable ways as different from the original version.
-*/
-
-#include "menus/debugger.h"
-#include "memory.h"
-#include "draw.h"
-#include "minisoc.h"
-#include "fmt.h"
-#include "pmdbgext.h"
-#include "gdb/server.h"
-#include "gdb/debug.h"
-#include "gdb/monitor.h"
-#include "gdb/net.h"
-#include "pmdbgext.h"
-
-Menu debuggerMenu = {
- "Debugger options menu",
- {
- { "Enable debugger", METHOD, .method = &DebuggerMenu_EnableDebugger },
- { "Disable debugger", METHOD, .method = &DebuggerMenu_DisableDebugger },
- { "Force-debug next application at launch", METHOD, .method = &DebuggerMenu_DebugNextApplicationByForce },
- {},
- }
-};
-
-static MyThread debuggerSocketThread;
-static MyThread debuggerDebugThread;
-static u8 ALIGN(8) debuggerSocketThreadStack[0x5000];
-static u8 ALIGN(8) debuggerDebugThreadStack[0x3000];
-
-GDBServer gdbServer = { 0 };
-
-GDBContext *nextApplicationGdbCtx = NULL;
-
-void debuggerSocketThreadMain(void);
-MyThread *debuggerCreateSocketThread(void)
-{
- MyThread_Create(&debuggerSocketThread, debuggerSocketThreadMain, debuggerSocketThreadStack, 0x5000, 0x20, CORE_SYSTEM);
- return &debuggerSocketThread;
-}
-
-void debuggerDebugThreadMain(void);
-MyThread *debuggerCreateDebugThread(void)
-{
- MyThread_Create(&debuggerDebugThread, debuggerDebugThreadMain, debuggerDebugThreadStack, 0x3000, 0x20, CORE_SYSTEM);
- return &debuggerDebugThread;
-}
-
-void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata)
-{
- (void)argdata;
- if(!nextApplicationGdbCtx)
- return;
- Handle debug = 0;
- PMDBG_RunQueuedProcess(&debug);
- GDB_LockAllContexts(&gdbServer);
- nextApplicationGdbCtx->debug = debug;
- if (debug == 0)
- nextApplicationGdbCtx->flags = 0;
- else
- nextApplicationGdbCtx->flags |= GDB_FLAG_ATTACHED_AT_START;
- nextApplicationGdbCtx = NULL;
- GDB_UnlockAllContexts(&gdbServer);
-}
-
-Result debuggerDisable(s64 timeout)
-{
- Result res = 0;
- bool initialized = gdbServer.referenceCount != 0;
- if(initialized)
- {
- svcSignalEvent(gdbServer.super.shall_terminate_event);
- server_kill_connections(&gdbServer.super);
-
- res = MyThread_Join(&debuggerDebugThread, timeout);
- if(res == 0)
- res = MyThread_Join(&debuggerSocketThread, timeout);
-
- Handle dummy = 0;
- PMDBG_RunQueuedProcess(&dummy);
- svcCloseHandle(dummy);
- PMDBG_DebugNextApplicationByForce(false);
- nextApplicationGdbCtx = NULL;
- }
-
- return res;
-}
-
-void DebuggerMenu_EnableDebugger(void)
-{
- bool done = false, alreadyEnabled = gdbServer.super.running;
- Result res = 0;
- char buf[65];
- bool isSocURegistered;
-
- res = srvIsServiceRegistered(&isSocURegistered, "soc:U");
- isSocURegistered = R_SUCCEEDED(res) && isSocURegistered;
-
- Draw_Lock();
- Draw_ClearFramebuffer();
- Draw_FlushFramebuffer();
- Draw_Unlock();
-
- do
- {
- Draw_Lock();
- Draw_DrawString(10, 10, COLOR_TITLE, "Debugger options menu");
-
- if(alreadyEnabled)
- Draw_DrawString(10, 30, COLOR_WHITE, "Already enabled!");
- else if(!isSocURegistered)
- Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the debugger before the system has fi-\nnished loading.");
- else
- {
- Draw_DrawString(10, 30, COLOR_WHITE, "Starting debugger...");
-
- if(!done)
- {
- res = GDB_InitializeServer(&gdbServer);
- Handle handles[3] = { gdbServer.super.started_event, gdbServer.super.shall_terminate_event, preTerminationEvent };
- s32 idx;
- if(R_SUCCEEDED(res))
- {
- debuggerCreateSocketThread();
- debuggerCreateDebugThread();
- res = svcWaitSynchronizationN(&idx, handles, 3, false, 5 * 1000 * 1000 * 1000LL);
- if(res == 0) res = gdbServer.super.init_result;
- }
-
- if(res != 0)
- sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res);
- done = true;
- }
- if(res == 0)
- Draw_DrawString(10, 30, COLOR_WHITE, "Starting debugger... OK.");
- else
- Draw_DrawString(10, 30, COLOR_WHITE, buf);
- }
-
- Draw_FlushFramebuffer();
- Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
-}
-
-void DebuggerMenu_DisableDebugger(void)
-{
- bool initialized = gdbServer.referenceCount != 0;
-
- Result res = initialized ? debuggerDisable(2 * 1000 * 1000 * 1000LL) : 0;
- char buf[65];
-
- if(res != 0)
- sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res);
-
- do
- {
- Draw_Lock();
- Draw_DrawString(10, 10, COLOR_TITLE, "Debugger options menu");
- Draw_DrawString(10, 30, COLOR_WHITE, initialized ? (res == 0 ? "Debugger disabled successfully." : buf) : "Debugger not enabled.");
- Draw_FlushFramebuffer();
- Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
-}
-
-void DebuggerMenu_DebugNextApplicationByForce(void)
-{
- bool initialized = gdbServer.referenceCount != 0;
- Result res = 0;
- char buf[256];
-
- if(initialized)
- {
- GDB_LockAllContexts(&gdbServer);
-
- if (nextApplicationGdbCtx != NULL)
- strcpy(buf, "Operation already performed.");
- else
- {
- nextApplicationGdbCtx = GDB_SelectAvailableContext(&gdbServer, GDB_PORT_BASE + 3, GDB_PORT_BASE + 4);
- if (nextApplicationGdbCtx != NULL)
- {
- nextApplicationGdbCtx->debug = 0;
- nextApplicationGdbCtx->pid = 0xFFFFFFFF;
- res = PMDBG_DebugNextApplicationByForce(true);
- if(R_SUCCEEDED(res))
- sprintf(buf, "Operation succeeded.\nUse port %d to connect to the next launched\napplication.", nextApplicationGdbCtx->localPort);
- else
- {
- nextApplicationGdbCtx->flags = 0;
- nextApplicationGdbCtx->localPort = 0;
- nextApplicationGdbCtx = NULL;
- sprintf(buf, "Operation failed (0x%08lx).", (u32)res);
- }
- }
- else
- strcpy(buf, "Failed to allocate a slot.\nPlease unselect a process in the process list first");
- }
- GDB_UnlockAllContexts(&gdbServer);
- }
- else
- strcpy(buf, "Debugger not enabled.");
-
- do
- {
- Draw_Lock();
- Draw_DrawString(10, 10, COLOR_TITLE, "Debugger options menu");
- Draw_DrawString(10, 30, COLOR_WHITE, buf);
- Draw_FlushFramebuffer();
- Draw_Unlock();
- }
- while(!(waitInput() & KEY_B) && !menuShouldExit);
-}
-
-void debuggerSocketThreadMain(void)
-{
- GDB_IncrementServerReferenceCount(&gdbServer);
- GDB_RunServer(&gdbServer);
- GDB_DecrementServerReferenceCount(&gdbServer);
-}
-
-void debuggerDebugThreadMain(void)
-{
- GDB_IncrementServerReferenceCount(&gdbServer);
- GDB_RunMonitor(&gdbServer);
- GDB_DecrementServerReferenceCount(&gdbServer);
-}
diff --git a/sysmodules/rosalina/source/menus/debugger_menu.c b/sysmodules/rosalina/source/menus/debugger_menu.c
new file mode 100644
index 000000000..eec443a97
--- /dev/null
+++ b/sysmodules/rosalina/source/menus/debugger_menu.c
@@ -0,0 +1,146 @@
+/*
+ * This file is part of Luma3DS
+ * Copyright (C) 2016-2020 Aurora Wright, TuxSH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+ * * Requiring preservation of specified reasonable legal notices or
+ * author attributions in that material or in the Appropriate Legal
+ * Notices displayed by works containing it.
+ * * Prohibiting misrepresentation of the origin of that material,
+ * or requiring that modified versions of such material be marked in
+ * reasonable ways as different from the original version.
+ */
+
+#include
+#include "menus/debugger_menu.h"
+#include "draw.h"
+
+Menu debuggerMenu = {
+ "Debugger options menu",
+ {
+ {"Enable debugger", METHOD, .method = &DebuggerMenu_EnableDebugger},
+ {"Disable debugger", METHOD, .method = &DebuggerMenu_DisableDebugger},
+ {"Force-debug next application at launch", METHOD, .method = &DebuggerMenu_DebugNextApplicationByForce},
+ {},
+ }};
+
+void DebuggerMenu_EnableDebugger(void)
+{
+ bool done = false, alreadyEnabled = gdbServer.super.running;
+ Result res = 0;
+ char buf[65];
+ bool isSocURegistered;
+ res = srvIsServiceRegistered(&isSocURegistered, "soc:U");
+ isSocURegistered = R_SUCCEEDED(res) && isSocURegistered;
+
+ Draw_Lock();
+ Draw_ClearFramebuffer();
+ Draw_FlushFramebuffer();
+ Draw_Unlock();
+
+ do
+ {
+ Draw_Lock();
+ Draw_DrawString(10, 10, COLOR_TITLE, "Debugger options menu");
+
+ if (alreadyEnabled)
+ Draw_DrawString(10, 30, COLOR_WHITE, "Already enabled!");
+ else if (!isSocURegistered)
+ Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the debugger before the system has fi-\nnished loading.");
+ else
+ {
+ Draw_DrawString(10, 30, COLOR_WHITE, "Starting debugger...");
+
+ if (!done)
+ {
+ res = debuggerEnable(5 * 1000 * 1000 * 1000LL);
+ if (res != 0)
+ sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res);
+ done = true;
+ }
+ if (res == 0)
+ Draw_DrawString(10, 30, COLOR_WHITE, "Starting debugger... OK.");
+ else
+ Draw_DrawString(10, 30, COLOR_WHITE, buf);
+ }
+
+ Draw_FlushFramebuffer();
+ Draw_Unlock();
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
+}
+
+void DebuggerMenu_DisableDebugger(void)
+{
+ bool initialized = gdbServer.referenceCount != 0;
+
+ Result res = initialized ? debuggerDisable(2 * 1000 * 1000 * 1000LL) : 0;
+ char buf[65];
+
+ if (res != 0)
+ sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res);
+
+ do
+ {
+ Draw_Lock();
+ Draw_DrawString(10, 10, COLOR_TITLE, "Debugger options menu");
+ Draw_DrawString(10, 30, COLOR_WHITE, initialized ? (res == 0 ? "Debugger disabled successfully." : buf) : "Debugger not enabled.");
+ Draw_FlushFramebuffer();
+ Draw_Unlock();
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
+}
+
+void DebuggerMenu_DebugNextApplicationByForce(void)
+{
+ bool initialized = gdbServer.referenceCount != 0;
+ Result res = 0;
+ char buf[256];
+
+ if (initialized)
+ {
+ GDB_LockAllContexts(&gdbServer);
+ res = debugNextApplicationByForce();
+ GDB_UnlockAllContexts(&gdbServer);
+ switch (res)
+ {
+ case 0:
+ strcpy(buf, "Operation already performed.");
+ break;
+ case 1:
+ sprintf(buf, "Operation succeeded.\nUse port %d to connect to the next launched\napplication.", nextApplicationGdbCtx->localPort);
+ break;
+ case 2:
+ strcpy(buf, "Failed to allocate a slot.\nPlease unselect a process in the process list first");
+ break;
+ default:
+ if (!R_SUCCEEDED(res))
+ {
+ sprintf(buf, "Operation failed (0x%08lx).", (u32)res);
+ }
+ break;
+ }
+ }
+ else
+ strcpy(buf, "Debugger not enabled.");
+
+ do
+ {
+ Draw_Lock();
+ Draw_DrawString(10, 10, COLOR_TITLE, "Debugger options menu");
+ Draw_DrawString(10, 30, COLOR_WHITE, buf);
+ Draw_FlushFramebuffer();
+ Draw_Unlock();
+ } while (!(waitInput() & KEY_B) && !menuShouldExit);
+}