From fe4bb0857b28541b8c907216a6104903220676e4 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:30:07 +0100 Subject: [PATCH] Implement autobooting into homebrew (3DS and DSi modes) Add config option to autoboot into 3DS and DSi homebrew menu, without going through Home Menu (nor launching it). For 3DS homebrew, this requires homebrew built with libctru v2.0.0 or later (v2.0.0 was released 2.5y ago). We simulate a "reboot into title" to achieve this. This being said, when launching stuff like Pokemon US/UM on O3DS, Home Menu reboots into itself and not the game directly. This will cause Home Menu to crash if you use this feature and configure it to use a non-default memory layout (but if you don't, Home Menu will work just fine). --- arm9/data/config_template.ini | Bin 3656 -> 4616 bytes arm9/source/config.c | 39 +++- arm9/source/config.h | 8 +- arm9/source/deliver_arg.c | 209 ++++++++++++++++++ arm9/source/deliver_arg.h | 37 ++++ arm9/source/main.c | 38 +++- arm9/source/memory.c | 24 ++ arm9/source/memory.h | 2 + arm9/source/patches.c | 4 + arm9/source/types.h | 3 + arm9/source/utils.c | 54 ++++- arm9/source/utils.h | 5 +- k11_extension/include/config.h | 3 +- k11_extension/include/globals.h | 2 + k11_extension/source/svc/GetSystemInfo.c | 7 + sysmodules/loader/source/patcher.h | 3 +- sysmodules/rosalina/data/config_template.ini | Bin 3656 -> 4616 bytes sysmodules/rosalina/source/menus.c | 12 +- .../rosalina/source/menus/miscellaneous.c | 22 +- 19 files changed, 439 insertions(+), 33 deletions(-) create mode 100644 arm9/source/deliver_arg.c create mode 100644 arm9/source/deliver_arg.h diff --git a/arm9/data/config_template.ini b/arm9/data/config_template.ini index 2960701fde49cdd06002896903e06be4f27745af..23dcf63228bf05910a72880eb3e442b864353d15 100644 GIT binary patch delta 950 zcmZuw&2G~`5EkN;@CtzDK&4cWHcq0nq~cIWrCyR$EfObWt?e;hwBEJ6yG<<)zV_Z1 zLFxtZ1Uv)}!|d9QLg2QV`M&x4zWw$5{?+%Nz4{E!tx=Iu26C0)ynhBm7|kK!nneN= z82Fr2WzK}C4t+kDgO74)6qpQQvbX`mjX=-^#wjOWR6!PrqzosCz6*VlC!RgtVSn)S z#SPz~^N!Ej$-+eQZG~;njSKJKAbI@J`}X9Zi+`pb+m%#dxRSb0G2i3ickg9wHNqxC z2_1#YF9h(*IFu`V1RrUwW~JO}0}&EH8@d7QrX;M+SBs;5S7CQTH`6GX332DzE-_bS z1%g$|8lZF8`akWP=I)A_$}uW&vlU|HFAw=&bq2F3EZ>7lffa?|F>`Bn7<#R#)Env^ zj2j%yOOZyrn$%n1ZP3Bn(FSj4uH-QUC#Upiup|{h$NSLJQ496u8|cJCC;QNo@jkR3 z!qj7@``F1p*eijI&Lx#0F*0VrY7z^WtW4$}ip*EKjPyQgT-uhU_1o15LyB`DAZAwA z2$ytZQbt-QNL(_V0Z)M&B3Kz`=zKb`+B(O>EoZ*?<$8Gmku`?yt6WortM#Xg>n=8g zuVfTrI)Axrp*C2mG(9fS|CYv#FiT67!?n^(aLH&`8pBx&S#r4JDEc-bi5rsep{WXd JeEsaj(?1^#It>5- delta 17 YcmeBBIU%!Q7w6_Wu1dzupZP?Y0YO&=g#Z8m 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 2960701fde49cdd06002896903e06be4f27745af..23dcf63228bf05910a72880eb3e442b864353d15 100644 GIT binary patch delta 950 zcmZuw&2G~`5EkN;@CtzDK&4cWHcq0nq~cIWrCyR$EfObWt?e;hwBEJ6yG<<)zV_Z1 zLFxtZ1Uv)}!|d9QLg2QV`M&x4zWw$5{?+%Nz4{E!tx=Iu26C0)ynhBm7|kK!nneN= z82Fr2WzK}C4t+kDgO74)6qpQQvbX`mjX=-^#wjOWR6!PrqzosCz6*VlC!RgtVSn)S z#SPz~^N!Ej$-+eQZG~;njSKJKAbI@J`}X9Zi+`pb+m%#dxRSb0G2i3ickg9wHNqxC z2_1#YF9h(*IFu`V1RrUwW~JO}0}&EH8@d7QrX;M+SBs;5S7CQTH`6GX332DzE-_bS z1%g$|8lZF8`akWP=I)A_$}uW&vlU|HFAw=&bq2F3EZ>7lffa?|F>`Bn7<#R#)Env^ zj2j%yOOZyrn$%n1ZP3Bn(FSj4uH-QUC#Upiup|{h$NSLJQ496u8|cJCC;QNo@jkR3 z!qj7@``F1p*eijI&Lx#0F*0VrY7z^WtW4$}ip*EKjPyQgT-uhU_1o15LyB`DAZAwA z2$ytZQbt-QNL(_V0Z)M&B3Kz`=zKb`+B(O>EoZ*?<$8Gmku`?yt6WortM#Xg>n=8g zuVfTrI)Axrp*C2mG(9fS|CYv#FiT67!?n^(aLH&`8pBx&S#r4JDEc-bi5rsep{WXd JeEsaj(?1^#It>5- delta 17 YcmeBBIU%!Q7w6_Wu1dzupZP?Y0YO&=g#Z8m 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;