diff --git a/arm9/data/config_template.ini b/arm9/data/config_template.ini index 2960701..23dcf63 100644 Binary files a/arm9/data/config_template.ini and b/arm9/data/config_template.ini differ diff --git a/arm9/source/config.c b/arm9/source/config.c index cf5da84..0319f61 100644 --- a/arm9/source/config.c +++ b/arm9/source/config.c @@ -319,8 +319,14 @@ static int configIniHandler(void* user, const char* section, const char* name, c } else { CHECK_PARSE_OPTION(-1); } + } else if (strcmp(name, "autoboot_mode") == 0) { + s64 opt; + CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, 0, 2)); + cfg->multiConfig |= (u32)opt << (2 * (u32)AUTOBOOTMODE); + return 1; + } else { + CHECK_PARSE_OPTION(-1); } - CHECK_PARSE_OPTION(-1); } else if (strcmp(section, "rosalina") == 0) { // Rosalina options if (strcmp(name, "hbldr_3dsx_titleid") == 0) { @@ -347,6 +353,20 @@ static int configIniHandler(void* user, const char* section, const char* name, c else { CHECK_PARSE_OPTION(-1); } + } else if (strcmp(section, "autoboot") == 0) { + if (strcmp(name, "autoboot_dsi_titleid") == 0) { + u64 opt; + CHECK_PARSE_OPTION(parseHexIntOption(&opt, value, 0, 0xFFFFFFFFFFFFFFFFull)); + cfg->autobootTwlTitleId = opt; + return 1; + } else if (strcmp(name, "autoboot_3ds_app_mem_type") == 0) { + s64 opt; + CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, 0, 4)); + cfg->autobootCtrAppmemtype = (u8)opt; + return 1; + } else { + CHECK_PARSE_OPTION(-1); + } } else if (strcmp(section, "misc") == 0) { for (size_t i = 0; i < sizeof(singleOptionIniNamesMisc)/sizeof(singleOptionIniNamesMisc[0]); i++) { if (strcmp(name, singleOptionIniNamesMisc[i]) == 0) { @@ -414,11 +434,13 @@ static size_t saveLumaIniConfigToStr(char *out) 1 + (int)MULTICONFIG(DEFAULTEMU), 4 - (int)MULTICONFIG(BRIGHTNESS), splashPosStr, (unsigned int)cfg->splashDurationMsec, - pinNumDigits, n3dsCpuStr, + pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE), cfg->hbldr3dsxTitleId, rosalinaMenuComboStr, (int)cfg->screenFiltersCct, (int)cfg->ntpTzOffetMinutes, + cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype, + (int)CONFIG(PATCHUNITINFO), (int)CONFIG(DISABLEARM11EXCHANDLERS), (int)CONFIG(ENABLESAFEFIRMROSALINA) ); @@ -522,9 +544,10 @@ bool readConfig(void) configData.formatVersionMinor = CONFIG_VERSIONMINOR; configData.config |= 1u << PATCHVERSTRING; configData.splashDurationMsec = 3000; - configData.hbldr3dsxTitleId = 0x000400000D921E00ull; + configData.hbldr3dsxTitleId = HBLDR_DEFAULT_3DSX_TID; configData.rosalinaMenuCombo = 1u << 9 | 1u << 7 | 1u << 2; // L+Start+Select configData.screenFiltersCct = 6500; // default temp, no-op + configData.autobootTwlTitleId = AUTOBOOT_DEFAULT_TWL_TID; ret = false; } else @@ -566,6 +589,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) "Splash: Off( ) Before( ) After( ) payloads", "PIN lock: Off( ) 4( ) 6( ) 8( ) digits", "New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )", + "Homebrew autoboot: Off( ) 3DS( ) DSi( )", }; static const char *singleOptionsText[] = { "( ) Autoboot EmuNAND", @@ -607,6 +631,14 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) "'Clock+L2' can cause issues with some\n" "games.", + "Enable autobooting into homebrew,\n" + "either into 3DS or DSi mode.\n\n" + "Autobooting into a gamecard title is\n" + "not supported.\n\n" + "Refer to the \"autoboot\" section in the\n" + "configuration file to configure\n" + "this feature.", + "If enabled, an EmuNAND\n" "will be launched on boot.\n\n" "Otherwise, SysNAND will.\n\n" @@ -675,6 +707,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) { .visible = true }, { .visible = true }, { .visible = ISN3DS }, + { .visible = true }, }; struct singleOption { diff --git a/arm9/source/config.h b/arm9/source/config.h index 222fafc..cf64164 100644 --- a/arm9/source/config.h +++ b/arm9/source/config.h @@ -28,13 +28,16 @@ #include "types.h" +#define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ull +#define AUTOBOOT_DEFAULT_TWL_TID 0x0003000448424C41ull + #define CONFIG(a) (((configData.config >> (a)) & 1) != 0) #define MULTICONFIG(a) ((configData.multiConfig >> (2 * (a))) & 3) #define BOOTCONFIG(a, b) ((configData.bootConfig >> (a)) & (b)) #define CONFIG_FILE "config.bin" #define CONFIG_VERSIONMAJOR 3 -#define CONFIG_VERSIONMINOR 0 +#define CONFIG_VERSIONMINOR 1 #define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7) @@ -47,7 +50,8 @@ enum multiOptions BRIGHTNESS, SPLASH, PIN, - NEWCPU + NEWCPU, + AUTOBOOTMODE, }; enum singleOptions diff --git a/arm9/source/deliver_arg.c b/arm9/source/deliver_arg.c new file mode 100644 index 0000000..df8dccf --- /dev/null +++ b/arm9/source/deliver_arg.c @@ -0,0 +1,209 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2022 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 "deliver_arg.h" +#include "utils.h" +#include "memory.h" +#include "config.h" + +u8 *loadDeliverArg(void) +{ + static u8 deliverArg[0x1000] = {0}; + static bool deliverArgLoaded = false; + + if (!deliverArgLoaded) + { + u32 bootenv = CFG_BOOTENV; // this register is preserved across reboots + if ((bootenv & 1) == 0) // true coldboot + { + memset(deliverArg, 0, 0x1000); + } + else + { + u32 mode = bootenv >> 1; + if (mode == 0) // CTR mode + { + memcpy(deliverArg, (const void *)0x20000000, 0x1000); + + // Validate deliver arg + u32 testPattern = *(u32 *)(deliverArg + 0x438); + u32 crc = *(u32 *)(deliverArg + 0x43C); + u32 expectedCrc = crc32(deliverArg + 0x400, 0x140, 0xFFFFFFFF); + if (testPattern != 0xFFFF || crc != expectedCrc) + memset(deliverArg, 0, 0x1000); + } + else // Legacy modes + { + // Copy TWL deliver arg stuff as-is (0...0x300) + copyFromLegacyModeFcram(deliverArg, (const void *)0x20000000, 0x400); + + // Validate TLNC (TWL launcher params) block + // Note: Nintendo doesn't do crcLen bound check + u8 *tlnc = deliverArg + 0x300; + bool hasMagic = memcmp(tlnc, "TLNC", 4) == 0; + u8 crcLen = tlnc[5]; + u16 crc = *(u16 *)(tlnc + 6); + if (!hasMagic || crcLen <= 248 || crc != crc16(tlnc + 8, crcLen, 0xFFFF)) + memset(tlnc, 0, 0x100); + + memset(deliverArg + 0x400, 0, 0xC00); + } + } + deliverArgLoaded = true; + } + + return deliverArg; +} + +void commitDeliverArg(void) +{ + u8 *deliverArg = loadDeliverArg(); + u32 bootenv = CFG_BOOTENV; + + if ((bootenv & 1) == 0) // if true coldboot, set bootenv to "CTR mode reboot" + { + bootenv = 1; + CFG_BOOTENV = 1; + } + + u32 mode = bootenv >> 1; + if (mode == 0) // CTR mode + { + *(u32 *)(deliverArg + 0x438) = 0xFFFF; + *(u32 *)(deliverArg + 0x43C) = crc32(deliverArg + 0x400, 0x140, 0xFFFFFFFF); + memcpy((void *)0x20000000, deliverArg, 0x1000); + } + else // Legacy modes (just TWL mode, really) + { + copyToLegacyModeFcram((void *)0x20000000, deliverArg, 0x400); + } +} + +bool hasValidTlncAutobootParams(void) +{ + u8 *tlnc = loadDeliverArg() + 0x300; // loadDeliverArg clears invalid TLNC blocks + return memcmp(tlnc, "TLNC", 4) == 0 && (*(u16 *)(tlnc + 0x18) & 1) != 0; +} + +bool isTwlToCtrLaunch(void) +{ + // assumes TLNC block is valid + u8 *tlnc = loadDeliverArg() + 0x300; // loadDeliverArg clears invalid TLNC blocks + u64 twlTid = *(u64 *)(tlnc + 0x10); + + switch (twlTid & ~0xFFull) + { + case 0x0000000000000000ull: // TWL Launcher -> Home menu (note: NS checks full TID) + case 0x00030015484E4200ull: // TWL System Settings -> CTR System Settings (mset) + return true; + default: + return false; + } +} + +static bool configureHomebrewAutobootCtr(u8 *deliverArg) +{ + static const u8 appmemtypesO3ds[] = { 0, 2, 3, 4, 5 }; + static const u8 appmemtypesN3ds[] = { 6, 7, 7, 7, 7 }; + + u64 hbldrTid = configData.hbldr3dsxTitleId; + hbldrTid = hbldrTid == 0 ? HBLDR_DEFAULT_3DSX_TID : hbldrTid; // replicate Loader's behavior + if ((hbldrTid >> 46) != 0x10) // Not a CTR titleId. Bail out + return false; + + u8 memtype = configData.autobootCtrAppmemtype; + deliverArg[0x400] = ISN3DS ? appmemtypesN3ds[memtype] : appmemtypesO3ds[memtype]; + + // Determine whether to load from the SD card or from NAND. We don't support gamecards for this + u32 category = (hbldrTid >> 32) & 0xFFFF; + bool isSdApp = (category & 0x10) == 0 && category != 1; // not a system app nor a DLP child + *(u64 *)(deliverArg + 0x440) = hbldrTid; + *(u64 *)(deliverArg + 0x448) = isSdApp ? 1 : 0; + + // Tell NS to run the title, and that it's not a title jump from legacy mode + *(u32 *)(deliverArg + 0x460) = (0 << 1) | (1 << 0); + + CFG_BOOTENV = 1; + + return true; +} + +static bool configureHomebrewAutobootTwl(u8 *deliverArg) +{ + // Here, we pretend to be a TWL app rebooting into another TWL app. + // We get NS to do all the heavy lifting (starting NWM and AM, etc.) this way. + + memset(deliverArg + 0x000, 0, 0x300); // zero TWL deliver arg params + + // Now onto TLNC (launcher params): + u8 *tlnc = deliverArg + 0x300; + memset(tlnc, 0, 0x100); + memcpy(tlnc, "TLNC", 4); + tlnc[4] = 1; // version + tlnc[5] = 0x18; // length of data to calculate CRC over + + *(u64 *)(tlnc + 8) = 0; // old title ID + *(u64 *)(tlnc + 0x10) = configData.autobootTwlTitleId; // new title ID + // bit4: "skip logo" ; bits2:1: NAND boot ; bit0: valid + *(u16 *)(tlnc + 0x18) = (1 << 4) | (3 << 1) | (1 << 0); + + *(u16 *)(tlnc + 6) = crc16(tlnc + 8, 0x18, 0xFFFF); + + CFG_BOOTENV = 3; + + return true; +} + +bool configureHomebrewAutoboot(void) +{ + bool ret; + u8 *deliverArg = loadDeliverArg(); + + u32 bootenv = CFG_BOOTENV; + u32 mode = bootenv >> 1; + + u32 testPattern = *(u32 *)(deliverArg + 0x438); + if (mode != 0 || testPattern == 0xFFFF) + return false; // bail out if this isn't a coldboot/plain reboot + + switch (MULTICONFIG(AUTOBOOTMODE)) + { + case 1: + ret = configureHomebrewAutobootCtr(deliverArg); + break; + case 2: + ret = configureHomebrewAutobootTwl(deliverArg); + break; + case 0: + default: + ret = false; + break; + } + + if (ret) + commitDeliverArg(); + return ret; +} diff --git a/arm9/source/deliver_arg.h b/arm9/source/deliver_arg.h new file mode 100644 index 0000000..02c1d84 --- /dev/null +++ b/arm9/source/deliver_arg.h @@ -0,0 +1,37 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2022 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 "types.h" + +u8 *loadDeliverArg(void); +void commitDeliverArg(void); + +bool hasValidTlncAutobootParams(void); +bool isTwlToCtrLaunch(void); // assumes TLNC block is valid + +bool configureHomebrewAutoboot(void); diff --git a/arm9/source/main.c b/arm9/source/main.c index bc0ec08..e9232dd 100644 --- a/arm9/source/main.c +++ b/arm9/source/main.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2020 Aurora Wright, TuxSH +* Copyright (C) 2016-2022 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 @@ -35,6 +35,7 @@ #include "pin.h" #include "crypto.h" #include "memory.h" +#include "deliver_arg.h" #include "screen.h" #include "i2c.h" #include "fmt.h" @@ -216,8 +217,15 @@ void main(int argc, char **argv, u32 magicWord) //If it's a MCU reboot, try to force boot options if(CFG_BOOTENV && needConfig != CREATE_CONFIGURATION) { - //Always force a SysNAND boot when quitting AGB_FIRM - if(CFG_BOOTENV == 7) + u32 bootenv = CFG_BOOTENV; + bool validTlnc = bootenv == 3 && hasValidTlncAutobootParams(); + bool twlIntoCtr = validTlnc && isTwlToCtrLaunch(); + + if (validTlnc) + needToInitSd = true; + + //Always force a SysNAND boot when quitting AGB_FIRM, or when doing a TWL -> (ns ->) TWL reboot + if(bootenv == 7 || (validTlnc && !twlIntoCtr)) { nandType = FIRMWARE_SYSNAND; firmSource = (BOOTCFG_NAND != 0) == (BOOTCFG_FIRM != 0) ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCFG_FIRM; @@ -228,16 +236,9 @@ void main(int argc, char **argv, u32 magicWord) goto boot; } - //Account for DSiWare soft resets if exiting TWL_FIRM - if(CFG_BOOTENV == 3) - { - static const u8 TLNC[] = {0x54, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x43}; - if(memcmp((void *)0x20000C00, TLNC, 10) == 0) needToInitSd = true; - } - - /* Force the last used boot options if autobooting a TWL title, or unless a button is pressed + /* Force the last used boot options if doing TWL->CTR, or unless a button is pressed or the no-forcing flag is set */ - if(needToInitSd || memcmp((void *)0x20000300, "TLNC", 4) == 0 || (!pressed && !BOOTCFG_NOFORCEFLAG)) + if(twlIntoCtr || !(pressed || BOOTCFG_NOFORCEFLAG)) { nandType = (FirmwareSource)BOOTCFG_NAND; firmSource = (FirmwareSource)BOOTCFG_FIRM; @@ -309,6 +310,17 @@ void main(int argc, char **argv, u32 magicWord) goto boot; } + // Set-up autoboot, and if we're booting into TWL mode, always use SysNAND + if (MULTICONFIG(AUTOBOOTMODE) != 0) + { + bool ok = configureHomebrewAutoboot(); + if (ok && MULTICONFIG(AUTOBOOTMODE) == 2) + { + nandType = FIRMWARE_SYSNAND; + firmSource = FIRMWARE_SYSNAND; + } + } + //If booting from CTRNAND, always use SysNAND if(!isSdMode) nandType = FIRMWARE_SYSNAND; @@ -387,8 +399,10 @@ boot: switch(firmType) { case NATIVE_FIRM: + { res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, needToInitSd, doUnitinfoPatch); break; + } case TWL_FIRM: res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch); break; diff --git a/arm9/source/memory.c b/arm9/source/memory.c index ae4aee6..3b169a4 100644 --- a/arm9/source/memory.c +++ b/arm9/source/memory.c @@ -54,3 +54,27 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize) return NULL; } + +void *copyFromLegacyModeFcram(void *dst, const void *src, size_t size) +{ + // Copy 2 bytes with a stride of 8 + const u16 *src16 = (const u16 *)src; + u16 *dst16 = (u16 *)dst; + + for (size_t i = 0; i < size / 2; i++) + dst16[i] = src16[4 * i]; + + return dst; +} + +void *copyToLegacyModeFcram(void *dst, const void *src, size_t size) +{ + // Copy 2 bytes with a stride of 8 + const u16 *src16 = (const u16 *)src; + u16 *dst16 = (u16 *)dst; + + for (size_t i = 0; i < size / 2; i++) + dst16[4 * i] = src16[i]; + + return dst; +} diff --git a/arm9/source/memory.h b/arm9/source/memory.h index 37813b0..4d05f0e 100644 --- a/arm9/source/memory.h +++ b/arm9/source/memory.h @@ -34,3 +34,5 @@ #include "types.h" u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); +void *copyFromLegacyModeFcram(void *dst, const void *src, size_t size); +void *copyToLegacyModeFcram(void *dst, const void *src, size_t size); diff --git a/arm9/source/patches.c b/arm9/source/patches.c index e4c3799..65916b8 100644 --- a/arm9/source/patches.c +++ b/arm9/source/patches.c @@ -134,6 +134,8 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 u32 rosalinaMenuCombo; u16 screenFiltersCct; s16 ntpTzOffetMinutes; + u64 autobootTwlTitleId; + u8 autobootCtrAppmemtype; } info; }; @@ -209,6 +211,8 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 info->rosalinaMenuCombo = configData.rosalinaMenuCombo; info->screenFiltersCct = configData.screenFiltersCct; info->ntpTzOffetMinutes = configData.ntpTzOffetMinutes; + info->autobootTwlTitleId = configData.autobootTwlTitleId; + info->autobootCtrAppmemtype = configData.autobootCtrAppmemtype; info->versionMajor = VERSION_MAJOR; info->versionMinor = VERSION_MINOR; info->versionBuild = VERSION_BUILD; diff --git a/arm9/source/types.h b/arm9/source/types.h index 2a59e3d..c6406b9 100644 --- a/arm9/source/types.h +++ b/arm9/source/types.h @@ -71,6 +71,9 @@ typedef struct { u32 rosalinaMenuCombo; u16 screenFiltersCct; s16 ntpTzOffetMinutes; + + u64 autobootTwlTitleId; + u8 autobootCtrAppmemtype; } CfgData; typedef struct diff --git a/arm9/source/utils.c b/arm9/source/utils.c index 2bbf835..e97bc29 100644 --- a/arm9/source/utils.c +++ b/arm9/source/utils.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2020 Aurora Wright, TuxSH +* Copyright (C) 2016-2022 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 @@ -154,3 +154,55 @@ void error(const char *fmt, ...) mcuPowerOff(); } + +u16 crc16(const void *data, size_t size, u16 initialValue) +{ + static u16 lut[256] = {0}; + static bool lutInitialized = false; + + if (!lutInitialized) + { + static const u16 poly = 0xA001; + for (u32 i = 0; i < 256; i++) + { + u16 r = i; + for (u32 j = 0; j < 8; j++) + r = (r >> 1) ^ ((r & 1) != 0 ? poly : 0); + lut[i] = r; + } + lutInitialized = true; + } + + u16 r = initialValue; + const u8 *data8 = (const u8 *)data; + for (size_t i = 0; i < size; i++) + r = (r >> 8) ^ lut[(r ^ data8[i]) & 0xFF]; + + return r; +} + +u32 crc32(const void *data, size_t size, u32 initialValue) +{ + static u32 lut[256] = {0}; + static bool lutInitialized = false; + + if (!lutInitialized) + { + static const u32 poly = 0xEDB88320; + for (u32 i = 0; i < 256; i++) + { + u32 r = i; + for (u32 j = 0; j < 8; j++) + r = (r >> 1) ^ ((r & 1) != 0 ? poly : 0); + lut[i] = r; + } + lutInitialized = true; + } + + u32 r = initialValue; + const u8 *data8 = (const u8 *)data; + for (size_t i = 0; i < size; i++) + r = (r >> 8) ^ lut[(r ^ data8[i]) & 0xFF]; + + return ~r; +} diff --git a/arm9/source/utils.h b/arm9/source/utils.h index a1678b9..99b32c0 100644 --- a/arm9/source/utils.h +++ b/arm9/source/utils.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2020 Aurora Wright, TuxSH +* Copyright (C) 2016-2022 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 @@ -46,3 +46,6 @@ u32 waitInput(bool isMenu); void mcuPowerOff(void); void wait(u64 amount); void error(const char *fmt, ...); + +u16 crc16(const void *data, size_t size, u16 initialValue); +u32 crc32(const void *data, size_t size, u32 initialValue); diff --git a/k11_extension/include/config.h b/k11_extension/include/config.h index a482de0..26ee057 100644 --- a/k11_extension/include/config.h +++ b/k11_extension/include/config.h @@ -20,7 +20,8 @@ enum multiOptions BRIGHTNESS, SPLASH, PIN, - NEWCPU + NEWCPU, + AUTOBOOTMODE, }; enum singleOptions diff --git a/k11_extension/include/globals.h b/k11_extension/include/globals.h index 5272d04..94e37a0 100644 --- a/k11_extension/include/globals.h +++ b/k11_extension/include/globals.h @@ -132,6 +132,8 @@ typedef struct CfwInfo u32 rosalinaMenuCombo; u16 screenFiltersCct; s16 ntpTzOffetMinutes; + u64 autobootTwlTitleId; + u8 autobootCtrAppmemtype; } CfwInfo; extern CfwInfo cfwInfo; diff --git a/k11_extension/source/svc/GetSystemInfo.c b/k11_extension/source/svc/GetSystemInfo.c index f5f6bbf..72f22ee 100644 --- a/k11_extension/source/svc/GetSystemInfo.c +++ b/k11_extension/source/svc/GetSystemInfo.c @@ -61,6 +61,13 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param) *out = cfwInfo.splashDurationMsec; break; + case 0x10: + *out = (s64)cfwInfo.autobootTwlTitleId; + break; + case 0x11: + *out = cfwInfo.autobootCtrAppmemtype; + break; + case 0x100: *out = (s64)cfwInfo.hbldr3dsxTitleId; break; diff --git a/sysmodules/loader/source/patcher.h b/sysmodules/loader/source/patcher.h index ac6c3bf..9f14345 100644 --- a/sysmodules/loader/source/patcher.h +++ b/sysmodules/loader/source/patcher.h @@ -22,7 +22,8 @@ enum multiOptions BRIGHTNESS, SPLASH, PIN, - NEWCPU + NEWCPU, + AUTOBOOTMODE, }; enum singleOptions diff --git a/sysmodules/rosalina/data/config_template.ini b/sysmodules/rosalina/data/config_template.ini index 2960701..23dcf63 100644 Binary files a/sysmodules/rosalina/data/config_template.ini and b/sysmodules/rosalina/data/config_template.ini differ diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index 999cfe2..2833f4d 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -88,13 +88,6 @@ void RosalinaMenu_ShowDebugInfo(void) u32 kernelVer = osGetKernelVersion(); FS_SdMmcSpeedInfo speedInfo; - Handle hm = 0; - OpenProcessByName("menu", &hm); - s64 out = 0; - svcGetHandleInfo(&out, hm, 0); - svcCloseHandle(hm); - u64 timeToBootHm = 1000u * out / SYSCLOCK_ARM11; - do { Draw_Lock(); @@ -130,11 +123,10 @@ void RosalinaMenu_ShowDebugInfo(void) (int)speedInfo.highSpeedModeEnabled, SYSCLOCK_SDMMC / (1000 * clkDiv) ); } - if (timeToBootHm != 0) { posY = Draw_DrawFormattedString( - 10, posY, COLOR_WHITE, "Time to boot to Home Menu: %llums\n", - timeToBootHm + 10, posY, COLOR_WHITE, "APPMEMTYPE: %lu\n", + OS_KernelConfig->app_memtype ); } Draw_FlushFramebuffer(); diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 9dc055c..bf76139 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -62,7 +62,8 @@ enum multiOptions BRIGHTNESS, SPLASH, PIN, - NEWCPU + NEWCPU, + AUTOBOOTMODE, }; typedef struct DspFirmSegmentHeader { u32 offset; @@ -99,6 +100,9 @@ typedef struct CfgData { u32 rosalinaMenuCombo; u16 screenFiltersCct; s16 ntpTzOffetMinutes; + + u64 autobootTwlTitleId; + u8 autobootCtrAppmemtype; } CfgData; Menu miscellaneousMenu = { @@ -291,11 +295,13 @@ static size_t saveLumaIniConfigToStr(char *out, const CfgData *cfg) 1 + (int)MULTICONFIG(DEFAULTEMU), 4 - (int)MULTICONFIG(BRIGHTNESS), splashPosStr, (unsigned int)cfg->splashDurationMsec, - pinNumDigits, n3dsCpuStr, + pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE), cfg->hbldr3dsxTitleId, rosalinaMenuComboStr, (int)cfg->screenFiltersCct, (int)cfg->ntpTzOffetMinutes, + cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype, + (int)CONFIG(PATCHUNITINFO), (int)CONFIG(DISABLEARM11EXCHANDLERS), (int)CONFIG(ENABLESAFEFIRMROSALINA) ); @@ -318,8 +324,12 @@ void MiscellaneousMenu_SaveSettings(void) u32 config, multiConfig, bootConfig; u32 splashDurationMsec; + u8 autobootCtrAppmemtype; + u64 autobootTwlTitleId; + s64 out; bool isSdMode; + svcGetSystemInfo(&out, 0x10000, 2); formatVersion = (u32)out; svcGetSystemInfo(&out, 0x10000, 3); @@ -330,6 +340,12 @@ void MiscellaneousMenu_SaveSettings(void) bootConfig = (u32)out; svcGetSystemInfo(&out, 0x10000, 6); splashDurationMsec = (u32)out; + + svcGetSystemInfo(&out, 0x10000, 0x10); + autobootTwlTitleId = (u64)out; + svcGetSystemInfo(&out, 0x10000, 0x11); + autobootCtrAppmemtype = (u8)out; + svcGetSystemInfo(&out, 0x10000, 0x203); isSdMode = (bool)out; @@ -343,6 +359,8 @@ void MiscellaneousMenu_SaveSettings(void) configData.rosalinaMenuCombo = menuCombo; configData.screenFiltersCct = (u16)screenFiltersCurrentTemperature; configData.ntpTzOffetMinutes = (s16)lastNtpTzOffset; + configData.autobootTwlTitleId = autobootTwlTitleId; + configData.autobootCtrAppmemtype = autobootCtrAppmemtype; size_t n = saveLumaIniConfigToStr(inibuf, &configData); FS_ArchiveID archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;