diff --git a/sysmodules/rosalina/include/menu.h b/sysmodules/rosalina/include/menu.h index 6a42a67e..2e62656f 100644 --- a/sysmodules/rosalina/include/menu.h +++ b/sysmodules/rosalina/include/menu.h @@ -67,6 +67,7 @@ typedef struct Menu { extern u32 menuCombo; extern bool isHidInitialized; +extern bool isQtmInitialized; extern u32 mcuFwVersion; extern u8 mcuInfoTable[9]; extern bool mcuInfoTableRead; diff --git a/sysmodules/rosalina/include/menus/n3ds.h b/sysmodules/rosalina/include/menus/n3ds.h index 13c81162..294117e2 100644 --- a/sysmodules/rosalina/include/menus/n3ds.h +++ b/sysmodules/rosalina/include/menus/n3ds.h @@ -31,6 +31,10 @@ extern Menu N3DSMenu; +bool N3DSMenu_CheckNotN2dsXl(void); + void N3DSMenu_UpdateStatus(void); void N3DSMenu_ChangeClockRate(void); void N3DSMenu_EnableDisableL2Cache(void); + +void N3DSMenu_ToggleSs3d(void); diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index f85d699d..ea2d6ed5 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -166,7 +166,7 @@ static void handleShellNotification(u32 notificationId) { // Quick dirty fix Sleep__HandleNotification(notificationId); - + if (notificationId == 0x213) { // Shell opened // Note that this notification is also fired on system init. @@ -205,6 +205,8 @@ static void handlePreTermNotification(u32 notificationId) Draw_Lock(); if (isHidInitialized) hidExit(); + if (isQtmInitialized) + qtmExit(); // Termination request menuShouldExit = true; diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index e177c763..cfdec672 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -42,6 +42,7 @@ u32 menuCombo = 0; bool isHidInitialized = false; +bool isQtmInitialized = false; u32 mcuFwVersion = 0; u8 mcuInfoTable[9] = {0}; bool mcuInfoTableRead = false; @@ -283,6 +284,16 @@ static void menuReadScreenTypes(void) } } +static void menuInitializeQtm(void) +{ + if (isQtmInitialized) + return; + + // Open last remaining qtm:sp session (out of 3) on >= 9.3, + // or one of the two qtm:s handles below 9.3 + isQtmInitialized = R_SUCCEEDED(qtmInit(GET_VERSION_MINOR(osGetKernelVersion()) >= 48 ? QTM_SERVICE_SYSTEM_PROCESS : QTM_SERVICE_SYSTEM)); +} + static inline u32 menuAdvanceCursor(u32 pos, u32 numItems, s32 displ) { return (pos + numItems + displ) % numItems; @@ -317,12 +328,16 @@ u32 g_blockMenuOpen = 0; void menuThreadMain(void) { - if(isN3DS) - N3DSMenu_UpdateStatus(); - while (!isServiceUsable("ac:u") || !isServiceUsable("hid:USER") || !isServiceUsable("gsp::Gpu") || !isServiceUsable("gsp::Lcd") || !isServiceUsable("cdc:CHK")) svcSleepThread(250 * 1000 * 1000LL); + if (isN3DS) + { + while (!isServiceUsable("qtm:u")) + svcSleepThread(250 * 1000 * 1000LL); + N3DSMenu_UpdateStatus(); + } + handleShellOpened(); hidInit(); // assume this doesn't fail @@ -330,6 +345,8 @@ void menuThreadMain(void) menuReadScreenTypes(); + menuInitializeQtm(); + while(!preTerminationRequested) { svcSleepThread(50 * 1000 * 1000LL); diff --git a/sysmodules/rosalina/source/menus/n3ds.c b/sysmodules/rosalina/source/menus/n3ds.c index 9f90034e..f2c44e80 100644 --- a/sysmodules/rosalina/source/menus/n3ds.c +++ b/sysmodules/rosalina/source/menus/n3ds.c @@ -37,11 +37,20 @@ Menu N3DSMenu = { { { "Enable L2 cache", METHOD, .method = &N3DSMenu_EnableDisableL2Cache }, { clkRateBuf, METHOD, .method = &N3DSMenu_ChangeClockRate }, + { "Temporarily disable Super-Stable 3D", METHOD, .method = &N3DSMenu_ToggleSs3d, .visibility = &N3DSMenu_CheckNotN2dsXl }, {}, } }; static s64 clkRate = 0, higherClkRate = 0, L2CacheEnabled = 0; +static bool qtmUnavailableAndNotBlacklisted = false; // true on N2DSXL, though we check MCU system model data first +static QtmStatus lastUpdatedQtmStatus; + +bool N3DSMenu_CheckNotN2dsXl(void) +{ + // Also check if qtm could be initialized + return isQtmInitialized && mcuInfoTableRead && mcuInfoTable[9] != 5 && !qtmUnavailableAndNotBlacklisted; +} void N3DSMenu_UpdateStatus(void) { @@ -51,6 +60,28 @@ void N3DSMenu_UpdateStatus(void) N3DSMenu.items[0].title = L2CacheEnabled ? "Disable L2 cache" : "Enable L2 cache"; sprintf(clkRateBuf, "Set clock rate to %luMHz", clkRate != 268 ? 268 : (u32)higherClkRate); + + if (N3DSMenu_CheckNotN2dsXl()) + { + // Read status + if (R_FAILED(QTMS_GetQtmStatus(&lastUpdatedQtmStatus))) + qtmUnavailableAndNotBlacklisted = true; // stop showing QTM options if unavailable but not blacklisted + + if ((lastUpdatedQtmStatus & 0xFF) == QTM_STATUS_UNAVAILABLE) + __builtin_trap(); + + bool blacklisted = false; + if (lastUpdatedQtmStatus == QTM_STATUS_UNAVAILABLE) + qtmUnavailableAndNotBlacklisted = R_FAILED(QTMU_IsCurrentAppBlacklisted(&blacklisted)) || !blacklisted; + + + MenuItem *item = &N3DSMenu.items[2]; + + if (lastUpdatedQtmStatus == QTM_STATUS_ENABLED) + item->title = "Temporarily disable Super-Stable 3D"; + else + item->title = "Temporarily enable Super-Stable 3D"; + } } void N3DSMenu_ChangeClockRate(void) @@ -72,3 +103,16 @@ void N3DSMenu_EnableDisableL2Cache(void) N3DSMenu_UpdateStatus(); } + +void N3DSMenu_ToggleSs3d(void) +{ + if (qtmUnavailableAndNotBlacklisted) + return; + + if (lastUpdatedQtmStatus == QTM_STATUS_ENABLED) + QTMS_SetQtmStatus(QTM_STATUS_SS3D_DISABLED); + else // both SS3D disabled and unavailable/blacklisted states + QTMS_SetQtmStatus(QTM_STATUS_ENABLED); + + N3DSMenu_UpdateStatus(); +}