diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..280866b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.xml text eol=lf diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 7e0e1f4..11d093b 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -11,7 +11,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload -- -- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue. -- --- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.hacks.guide/troubleshooting +-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: use https://github.com/MechanicalDragon0687/TWLFix-CFW and update your system. -- If you're using an emu/redNAND try installing anything on it to sysNAND. -- Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s). -- @@ -25,7 +25,8 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload **SysNAND version (+emu/redNAND version if applicable):** -[e.g. 11.6.0-39U SysNAND, 11.6.0-39J EmuNAND] +[e.g. 11.13.0-45U SysNAND, 11.13.0-45E EmuNAND] + **Entrypoint (How/what you're using to boot Luma3DS):** @@ -33,9 +34,7 @@ about: Use this to report bugs you encounter with Luma3DS. Make sure you upload **Luma3DS version:** -[e.g. 8.1.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e] - - +[e.g. v10.1.3 stable or if using non-releases specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c] **Luma3DS configuration/options:** @@ -71,11 +70,11 @@ Show NAND or user string in System Settings: ( ) Show GBA boot screen in patched AGB_FIRM: ( ) -Patch ARM9 access: ( ) +Patch Arm9 access: ( ) Set developer UNITINFO: ( ) -Disable ARM11 exception handlers: ( ) +Disable Arm11 exception handlers: ( ) -- @@ -95,6 +94,6 @@ Disable ARM11 exception handlers: ( ) **Dump file:** - diff --git a/README.md b/README.md index a1cf5c2..ee59bfe 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,36 @@ # Luma3DS *Noob-proof (N)3DS "Custom Firmware"* -## What it is +### What it is +**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock. -**Luma3DS** is a program to patch the system software of (New) Nintendo 3DS handheld consoles "on the fly", adding features (such as per-game language settings and debugging capabilities for developers) and removing restrictions enforced by Nintendo (such as the region lock). It also allows you to run unauthorized ("homebrew") content by removing signature checks. -To use it, you will need a console capable of running homebrew software on the ARM9 processor. We recommend [Plailect's guide](https://3ds.hacks.guide/) for details on how to get your system ready. +To use it, you will need a console capable of running homebrew software on the Arm9 processor. -Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Select` (see the [release notes](https://github.com/AuroraWright/Luma3DS/releases/tag/v8.0)). +Since v8.0, Luma3DS has its own in-game menu, triggerable by L+Down+Select (see the [release notes](https://github.com/LumaTeam/Luma3DS/releases/tag/v8.0)). ---- +# +### Compiling +* Prerequisites + 1. git + 2. [makerom](https://github.com/jakcron/Project_CTR) in PATH + 3. [firmtool](https://github.com/TuxSH/firmtool) + 4. Up-to-date devkitARM+libctru +1. Clone the repository with `git clone https://github.com/LumaTeam/Luma3DS.git` +2. Run `make`. -## Compiling + The produced `boot.firm` is meant to be copied to the root of your SD card for usage with Boot9Strap. -First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git` -To compile, you'll need a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions. -You'll also need to update your libctru and devkitARM installation to their latest releases. -Then, run `make`. -The produced file is called `boot.firm` and is meant to be copied to the root of your SD card, for usage with boot9strap. +# +### Setup / Usage / Features +See https://github.com/LumaTeam/Luma3DS/wiki ---- +# +### Credits +See https://github.com/LumaTeam/Luma3DS/wiki/Credits -## Setup / Usage / Features +# +### Licensing +This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file. -See https://github.com/AuroraWright/Luma3DS/wiki - ---- - -## Credits - -See https://github.com/AuroraWright/Luma3DS/wiki/Credits - ---- - -## Licensing - -This software is licensed under the terms of the GPLv3. -You can find a copy of the license in the LICENSE.txt file. - -Files in the GDB stub are instead double-licensed as MIT or "GPLv2 or any later version", in which case it is specified in the file header. +Files in the GDB stub are instead triple-licensed as MIT or "GPLv2 or any later version", in which case it's specified in the file header. diff --git a/arm11/source/main.c b/arm11/source/main.c index 5be2c5e..48fecbc 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm11/source/memory.c b/arm11/source/memory.c index 34ce973..bce71f5 100644 --- a/arm11/source/memory.c +++ b/arm11/source/memory.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm11/source/memory.h b/arm11/source/memory.h index 99c7a08..47d4e1f 100644 --- a/arm11/source/memory.h +++ b/arm11/source/memory.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm11/source/start.s b/arm11/source/start.s index 93135cf..af0f2cb 100644 --- a/arm11/source/start.s +++ b/arm11/source/start.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 @@ -71,7 +71,7 @@ start: .global prepareForFirmlaunch .type prepareForFirmlaunch, %function prepareForFirmlaunch: - str r0, [r1] @ tell ARM9 we're done + str r0, [r1] @ tell Arm9 we're done mov r0, #0x20000000 _wait_for_core0_entrypoint_loop: diff --git a/arm11/source/types.h b/arm11/source/types.h index 0426614..43eacc9 100644 --- a/arm11/source/types.h +++ b/arm11/source/types.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/3dsheaders.h b/arm9/source/3dsheaders.h index 313448e..6b6a0ee 100644 --- a/arm9/source/3dsheaders.h +++ b/arm9/source/3dsheaders.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/alignedseqmemcpy.h b/arm9/source/alignedseqmemcpy.h index dc915bf..7d529b3 100644 --- a/arm9/source/alignedseqmemcpy.h +++ b/arm9/source/alignedseqmemcpy.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/alignedseqmemcpy.s b/arm9/source/alignedseqmemcpy.s index 6784b69..b347c2a 100644 --- a/arm9/source/alignedseqmemcpy.s +++ b/arm9/source/alignedseqmemcpy.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/arm9/source/arm9_exception_handlers.c b/arm9/source/arm9_exception_handlers.c index 2cce582..0adf337 100644 --- a/arm9/source/arm9_exception_handlers.c +++ b/arm9/source/arm9_exception_handlers.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/arm9_exception_handlers.h b/arm9/source/arm9_exception_handlers.h index 8c21f6f..a53fe0d 100644 --- a/arm9/source/arm9_exception_handlers.h +++ b/arm9/source/arm9_exception_handlers.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/arm9_exception_handlers_asm.s b/arm9/source/arm9_exception_handlers_asm.s index 4ab622e..458023f 100644 --- a/arm9/source/arm9_exception_handlers_asm.s +++ b/arm9/source/arm9_exception_handlers_asm.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/arm9/source/buttons.h b/arm9/source/buttons.h index 96dff1b..d1c3023 100644 --- a/arm9/source/buttons.h +++ b/arm9/source/buttons.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/cache.h b/arm9/source/cache.h index f0db75d..af3b0e9 100644 --- a/arm9/source/cache.h +++ b/arm9/source/cache.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,7 +33,7 @@ The data cache and/or the instruction cache MUST be flushed before doing one of the following: - rebooting - powering down - - setting the ARM11 entrypoint to execute a function + - setting the Arm11 entrypoint to execute a function - jumping to a payload ***/ diff --git a/arm9/source/cache.s b/arm9/source/cache.s index 0990022..ff74e9d 100644 --- a/arm9/source/cache.s +++ b/arm9/source/cache.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 @@ -31,7 +31,7 @@ flushEntireDCache: @ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html, @ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well - @ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has) + @ Note: Arm's example is actually for a 8KB DCache (which is what the 3DS has) @ Implemented in bootROM at address 0xffff0830 mov r1, #0 @ segment counter diff --git a/arm9/source/chainloader.c b/arm9/source/chainloader.c index c35cd72..3976f32 100644 --- a/arm9/source/chainloader.c +++ b/arm9/source/chainloader.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/chainloader.h b/arm9/source/chainloader.h index 742fc58..ff059ad 100644 --- a/arm9/source/chainloader.h +++ b/arm9/source/chainloader.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -29,4 +29,4 @@ #include "types.h" #include "firm.h" -void chainload(int argc, char **argv, Firm *firm); \ No newline at end of file +void chainload(int argc, char **argv, Firm *firm); diff --git a/arm9/source/config.c b/arm9/source/config.c index d5a9879..fcac6c5 100644 --- a/arm9/source/config.c +++ b/arm9/source/config.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -94,7 +94,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) "( ) Show NAND or user string in System Settings", "( ) Show GBA boot screen in patched AGB_FIRM", "( ) Set developer UNITINFO", - "( ) Disable ARM11 exception handlers", + "( ) Disable Arm11 exception handlers", + "( ) Enable Rosalina on SAFE_FIRM", }; static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n" @@ -189,11 +190,20 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) "are doing!", "Disables the fatal error exception\n" - "handlers for the ARM11 CPU.\n\n" + "handlers for the Arm11 CPU.\n\n" "Note: Disabling the exception handlers\n" "will disqualify you from submitting\n" "issues or bug reports to the Luma3DS\n" - "GitHub repository!" + "GitHub repository!", + + "Enables Rosalina, the kernel ext.\n" + "and sysmodule reimplementations on\n" + "SAFE_FIRM (New 3DS only).\n\n" + "Also suppresses QTM error 0xF96183FE,\n" + "allowing to use 8.1-11.3 N3DS on\n" + "New 2DS XL consoles.\n\n" + "Only select this if you know what you\n" + "are doing!", }; FirmwareSource nandType = FIRMWARE_SYSNAND; @@ -229,7 +239,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode) { .visible = true }, { .visible = true }, { .visible = true }, - { .visible = true } + { .visible = true }, + { .visible = ISN3DS }, }; //Calculate the amount of the various kinds of options and pre-select the first single one diff --git a/arm9/source/config.h b/arm9/source/config.h index 50cb5b1..de81062 100644 --- a/arm9/source/config.h +++ b/arm9/source/config.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -34,7 +34,7 @@ #define CONFIG_FILE "config.bin" #define CONFIG_VERSIONMAJOR 2 -#define CONFIG_VERSIONMINOR 3 +#define CONFIG_VERSIONMINOR 4 #define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7) @@ -60,7 +60,8 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHUNITINFO, - DISABLEARM11EXCHANDLERS + DISABLEARM11EXCHANDLERS, + ENABLESAFEFIRMROSALINA, }; typedef enum ConfigurationStatus diff --git a/arm9/source/crypto.c b/arm9/source/crypto.c index 19cc6e3..ea23570 100755 --- a/arm9/source/crypto.c +++ b/arm9/source/crypto.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -599,11 +599,11 @@ void kernel9Loader(Arm9Bin *arm9Section) __attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE]; memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr)); - //Decrypt ARM9 binary + //Decrypt Arm9 binary aes_use_keyslot(arm9BinSlot); aes(startOfArm9Bin, startOfArm9Bin, arm9SectionSize / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); - if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary."); + if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the Arm9 binary."); } void computePinHash(u8 *outbuf, const u8 *inbuf) @@ -612,7 +612,7 @@ void computePinHash(u8 *outbuf, const u8 *inbuf) cipherText[AES_BLOCK_SIZE]; sdmmc_get_cid(1, (u32 *)cid); - aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the ARM9 bootROM + aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the Arm9 bootROM aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE); } diff --git a/arm9/source/crypto.h b/arm9/source/crypto.h index f3e1543..ea74496 100755 --- a/arm9/source/crypto.h +++ b/arm9/source/crypto.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/draw.c b/arm9/source/draw.c index b8582e5..3ec6c1c 100644 --- a/arm9/source/draw.c +++ b/arm9/source/draw.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/draw.h b/arm9/source/draw.h index 75f04ef..f1f966d 100644 --- a/arm9/source/draw.h +++ b/arm9/source/draw.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/emunand.c b/arm9/source/emunand.c index f9aa6e0..1f9bd76 100644 --- a/arm9/source/emunand.c +++ b/arm9/source/emunand.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/emunand.h b/arm9/source/emunand.h index 3aba2df..58941ca 100644 --- a/arm9/source/emunand.h +++ b/arm9/source/emunand.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/exceptions.c b/arm9/source/exceptions.c index f3d7b36..ca45a77 100644 --- a/arm9/source/exceptions.c +++ b/arm9/source/exceptions.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -85,8 +85,8 @@ void detectAndProcessExceptionDumps(void) drawString(true, 10, 10, COLOR_RED, "An exception occurred"); u32 posY; - if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: ARM11 (core %u)", dumpHeader->core); - else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: ARM9"); + if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: Arm11 (core %u)", dumpHeader->core); + else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: Arm9"); if(dumpHeader->type == 2) { diff --git a/arm9/source/exceptions.h b/arm9/source/exceptions.h index 11bd9e4..66c4af2 100644 --- a/arm9/source/exceptions.h +++ b/arm9/source/exceptions.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/firm.c b/arm9/source/firm.c index 1f44499..eb2dd1c 100755 --- a/arm9/source/firm.c +++ b/arm9/source/firm.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -58,7 +58,7 @@ static __attribute__((noinline)) bool inRange(u32 as, u32 ae, u32 bs, u32 be) static bool checkFirm(u32 firmSize) { - if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the ARM11 entrypoint to be zero in which case nothing is done on the ARM11 side + if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the Arm11 entrypoint to be zero in which case nothing is done on the Arm11 side return false; bool arm9EpFound = false, @@ -184,7 +184,7 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF else if(ctrNandError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one."); } - //Check that the FIRM is right for the console from the ARM9 section address + //Check that the FIRM is right for the console from the Arm9 section address if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800)) error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND"); @@ -278,7 +278,8 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo srcModuleSize = moduleList[nbModules].size = ((Cxi *)src)->ncch.contentSize * 0x200; } - if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D)) + // SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on + if((firmType == NATIVE_FIRM || firmType == SAFE_FIRM) && (ISN3DS || firmVersion >= 0x1D)) { //2) Merge that info with our own modules' for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize) @@ -303,7 +304,9 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo //3) Read or copy the modules u8 *dst = firm->section[0].address; const char *extModuleSizeError = "The external FIRM modules are too large."; - for(u32 i = 0, dstModuleSize, maxModuleSize = firmType == NATIVE_FIRM ? 0x80000 : 0x600000; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize) + // SAFE_FIRM only for N3DS and only if ENABLESAFEFIRMROSALINA is on + u32 maxModuleSize = (firmType == NATIVE_FIRM || firmType == SAFE_FIRM) ? 0x80000 : 0x600000; + for(u32 i = 0, dstModuleSize; i < nbModules; i++, dst += dstModuleSize, maxModuleSize -= dstModuleSize) { if(loadFromStorage) { @@ -335,7 +338,7 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo memcpy(dst, moduleList[i].src, dstModuleSize); } - //4) Patch NATIVE_FIRM if necessary + //4) Patch NATIVE_FIRM/SAFE_FIRM (N3DS) if necessary if(nbModules == 6) { if(patchK11ModuleLoading(firm->section[0].size, dst - firm->section[0].address, (u8 *)firm + firm->section[1].offset, firm->section[1].size) != 0) @@ -350,7 +353,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora if(ISN3DS) { - //Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader + //Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader kernel9Loader((Arm9Bin *)arm9Section); firm->arm9Entry = (u8 *)0x801B01C; } @@ -409,7 +412,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora if(!ISDEVUNIT) ret += patchCheckForDevCommonKey(process9Offset, process9Size); } - //ARM9 exception handlers + //Arm9 exception handlers ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size); ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address); ret += patchKernel9Panic(arm9Section, kernel9Size); @@ -426,7 +429,7 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch) { u8 *arm9Section = (u8 *)firm + firm->section[3].offset; - //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader + //On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader if(ISN3DS) { kernel9Loader((Arm9Bin *)arm9Section); @@ -465,7 +468,7 @@ u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch) { u8 *arm9Section = (u8 *)firm + firm->section[3].offset; - //On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader + //On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader if(ISN3DS) { kernel9Loader((Arm9Bin *)arm9Section); @@ -501,7 +504,7 @@ u32 patch1x2xNativeAndSafeFirm(void) if(ISN3DS) { - //Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader + //Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader kernel9Loader((Arm9Bin *)arm9Section); firm->arm9Entry = (u8 *)0x801B01C; } @@ -518,10 +521,36 @@ u32 patch1x2xNativeAndSafeFirm(void) ret += ISN3DS ? patchSignatureChecks(process9Offset, process9Size) : patchOldSignatureChecks(process9Offset, process9Size); - //ARM9 exception handlers + //Arm9 exception handlers ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size); ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address); + if(ISN3DS && CONFIG(ENABLESAFEFIRMROSALINA)) + { + u8 *arm11Section1 = (u8 *)firm + firm->section[1].offset; + //Find the Kernel11 SVC table and handler, exceptions page and free space locations + u32 baseK11VA; + u8 *freeK11Space; + u32 *arm11SvcHandler, + *arm11ExceptionsPage, + *arm11SvcTable = getKernel11Info(arm11Section1, firm->section[1].size, &baseK11VA, &freeK11Space, &arm11SvcHandler, &arm11ExceptionsPage); + + ret += installK11Extension(arm11Section1, firm->section[1].size, false, baseK11VA, arm11ExceptionsPage, &freeK11Space); + ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage); + + // Add some other patches to the mix, as we can now launch homebrew on SAFE_FIRM: + + //Apply firmlaunch patches + //Or don't, this makes usm not work + //ret += patchFirmlaunches(process9Offset, process9Size, process9MemAddr); + + ret += patchKernel9Panic(arm9Section, kernel9Size); + ret += patchP9AccessChecks(process9Offset, process9Size); + + mergeSection0(NATIVE_FIRM, 0x45, false); // may change in the future + firm->section[0].size = 0; + } + return ret; } diff --git a/arm9/source/firm.h b/arm9/source/firm.h index b60b654..591ec2f 100644 --- a/arm9/source/firm.h +++ b/arm9/source/firm.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/fmt.c b/arm9/source/fmt.c index 4815f1a..bd06bab 100644 --- a/arm9/source/fmt.c +++ b/arm9/source/fmt.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/fmt.h b/arm9/source/fmt.h index d805af9..1311286 100644 --- a/arm9/source/fmt.h +++ b/arm9/source/fmt.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/fs.c b/arm9/source/fs.c index 9bf33ba..460e9ea 100644 --- a/arm9/source/fs.c +++ b/arm9/source/fs.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/fs.h b/arm9/source/fs.h index 7fa82ea..a0e6a8b 100644 --- a/arm9/source/fs.h +++ b/arm9/source/fs.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/large_patches.h b/arm9/source/large_patches.h index 6d99f56..6c99243 100644 --- a/arm9/source/large_patches.h +++ b/arm9/source/large_patches.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2017 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/main.c b/arm9/source/main.c index 5221361..50b6666 100644 --- a/arm9/source/main.c +++ b/arm9/source/main.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -226,11 +226,21 @@ void main(int argc, char **argv, u32 magicWord) } u32 pinMode = MULTICONFIG(PIN); + bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT); bool pinExists = pinMode != 0 && verifyPin(pinMode); - //If no configuration file exists or SELECT is held or if booted from NTRCARD, load configuration menu - bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT); + /* If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo or the configuration menu button + (if not already pressed, for the latter) */ + if(pinExists && !shouldLoadConfigMenu) + { + while(HID_PAD & PIN_BUTTONS); + wait(2000ULL); + //Update pressed buttons + pressed = HID_PAD; + } + + shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT); if(shouldLoadConfigMenu) { configMenu(pinExists, pinMode); @@ -247,13 +257,6 @@ void main(int argc, char **argv, u32 magicWord) isSafeMode = true; needToInitSd = true; - //If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo - if(pinExists && !shouldLoadConfigMenu) - { - while(HID_PAD & PIN_BUTTONS); - wait(2000ULL); - } - goto boot; } @@ -271,7 +274,19 @@ void main(int argc, char **argv, u32 magicWord) else if((((pressed & SINGLE_PAYLOAD_BUTTONS) || (!autoBootEmu && (pressed & DPAD_BUTTONS))) && !(pressed & (BUTTON_L1 | BUTTON_R1))) || (((pressed & L_PAYLOAD_BUTTONS) || (autoBootEmu && (pressed & DPAD_BUTTONS))) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed); - if(splashMode == 2) loadSplash(); + if(splashMode == 2 && loadSplash()) pressed = HID_PAD; + + //Check SAFE_MODE combo again + if(!CFG_BOOTENV && pressed == SAFE_MODE) + { + nandType = FIRMWARE_SYSNAND; + firmSource = FIRMWARE_SYSNAND; + + isSafeMode = true; + needToInitSd = true; + + goto boot; + } //If booting from CTRNAND, always use SysNAND if(!isSdMode) nandType = FIRMWARE_SYSNAND; diff --git a/arm9/source/memory.c b/arm9/source/memory.c index f8ce5d4..ae4aee6 100644 --- a/arm9/source/memory.c +++ b/arm9/source/memory.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/memory.h b/arm9/source/memory.h index eb71259..37813b0 100644 --- a/arm9/source/memory.h +++ b/arm9/source/memory.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/patches.c b/arm9/source/patches.c index b3766f6..f0499d3 100644 --- a/arm9/source/patches.c +++ b/arm9/source/patches.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -42,6 +42,8 @@ #include "arm9_exception_handlers.h" #include "large_patches.h" +#define K11EXT_VA 0x70000000 + u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) { u8 *temp = memsearch(pos, "NCCH", size, 4); @@ -79,8 +81,8 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 * return arm11SvcTable; } -// For ARM prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases) -static inline u32 computeARMFrameSize(const u32 *prolog) +// For Arm prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases) +static inline u32 computeArmFrameSize(const u32 *prolog) { const u32 *off; @@ -108,9 +110,12 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 struct KExtParameters { u32 basePA; + u32 stolenSystemMemRegionSize; void *originalHandlers[4]; u32 L1MMUTableAddrs[4]; + volatile bool done; + struct CfwInfo { char magic[4]; @@ -135,8 +140,9 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 static const u8 patternHook3_4[] = {0x00, 0x00, 0xA0, 0xE1, 0x03, 0xF0, 0x20, 0xE3, 0xFD, 0xFF, 0xFF, 0xEA}; //SGI0 setup code, etc. //Our kernel11 extension is initially loaded in VRAM - u32 kextTotalSize = *(u32 *)0x18000020 - 0x40000000; - u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - kextTotalSize; + u32 kextTotalSize = *(u32 *)0x18000020 - K11EXT_VA; + u32 stolenSystemMemRegionSize = kextTotalSize; // no need to steal any more mem on N3DS. Currently, everything fits in BASE on O3DS too (?) + u32 dstKextPA = (ISN3DS ? 0x2E000000 : 0x26C00000) - stolenSystemMemRegionSize; // start of BASE memregion (note: linear heap ---> <--- the rest) u32 *hookVeneers = (u32 *)*freeK11Space; u32 relocBase = 0xFFFF0000 + (*freeK11Space - (u8 *)arm11ExceptionsPage); @@ -144,11 +150,11 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 hookVeneers[0] = 0xE51FF004; //ldr pc, [pc, #-8+4] hookVeneers[1] = 0x18000004; hookVeneers[2] = 0xE51FF004; - hookVeneers[3] = 0x40000000; + hookVeneers[3] = K11EXT_VA; hookVeneers[4] = 0xE51FF004; - hookVeneers[5] = 0x40000008; + hookVeneers[5] = K11EXT_VA + 8; hookVeneers[6] = 0xE51FF004; - hookVeneers[7] = 0x4000000C; + hookVeneers[7] = K11EXT_VA + 0xC; (*freeK11Space) += 32; @@ -176,14 +182,16 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 off += 4; *off = MAKE_BRANCH_LINK(baseK11VA + ((u8 *)off - pos), relocBase + 24); - struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - 0x40000000 + 0x18000000); + struct KExtParameters *p = (struct KExtParameters *)(*(u32 *)0x18000024 - K11EXT_VA + 0x18000000); p->basePA = dstKextPA; + p->done = false; + p->stolenSystemMemRegionSize = stolenSystemMemRegionSize; for(u32 i = 0; i < 4; i++) { u32 *handlerPos = getKernel11HandlerVAPos(pos, arm11ExceptionsPage, baseK11VA, 1 + i); p->originalHandlers[i] = (void *)*handlerPos; - *handlerPos = 0x40000010 + 4 * i; + *handlerPos = K11EXT_VA + 0x10 + 4 * i; } struct CfwInfo *info = &p->info; @@ -236,7 +244,7 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm */ for(off = (u32 *)ControlMemoryPos; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++); off -= 2; - *off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)] + *off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeArmFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)] //Patch DebugActiveProcess for(off = (u32 *)(pos + (arm11SvcTable[0x60] - baseK11VA)); *off != 0xE3110001; off++); @@ -254,14 +262,14 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm //Redirect enableUserExceptionHandlersForCPUExc (= true) for(off = arm11ExceptionsPage; *off != 0x96007F9; off++); - off[1] = 0x40000028; + off[1] = K11EXT_VA + 0x28; off = (u32 *)memsearch(pos, patternKThreadDebugReschedule, size, sizeof(patternKThreadDebugReschedule)); if(off == NULL) return 1; off[-5] = 0xE51FF004; - off[-4] = 0x4000002C; + off[-4] = K11EXT_VA + 0x2C; return 0; } @@ -318,7 +326,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr) off -= 0x13; - //Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1 + //Firmlaunch function offset - offset in BLX opcode (A4-16 - Arm DDI 0100E) + 1 u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr); //Put the fOpen offset in the right location @@ -440,7 +448,7 @@ u32 patchK11ModuleLoading(u32 section0size, u32 modulesSize, u8 *pos, u32 size) off32 += 2; off32[1] = off32[0] + modulesSize; for(; *off32 != section0size; off32++); - *off32 += ((modulesSize + 0x1FF) >> 9) << 9; + *off32 = ((modulesSize + 0x1FF) >> 9) << 9; off = memsearch(pos, modulePidPattern, size, 4); diff --git a/arm9/source/patches.h b/arm9/source/patches.h index f17bdc7..dae3598 100644 --- a/arm9/source/patches.h +++ b/arm9/source/patches.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/pin.c b/arm9/source/pin.c index 32b78c0..a2cf2e2 100644 --- a/arm9/source/pin.c +++ b/arm9/source/pin.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/pin.h b/arm9/source/pin.h index 6bf4abb..00aee6c 100644 --- a/arm9/source/pin.h +++ b/arm9/source/pin.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/screen.c b/arm9/source/screen.c index a787832..bb01525 100644 --- a/arm9/source/screen.c +++ b/arm9/source/screen.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/screen.h b/arm9/source/screen.h index 79ae987..275ed68 100644 --- a/arm9/source/screen.h +++ b/arm9/source/screen.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/start.s b/arm9/source/start.s index c940516..1290b4a 100644 --- a/arm9/source/start.s +++ b/arm9/source/start.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 @@ -77,7 +77,7 @@ _start: ldr r1, =0xFFF0001B @ fff00000 16k | dtcm ldr r2, =0x01FF801D @ 01ff8000 32k | itcm ldr r3, =0x08000027 @ 08000000 1M | arm9 mem - ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) + ldr r4, =0x10000029 @ 10000000 2M | io mem (Arm9 / first 2MB) ldr r5, =0x20000035 @ 20000000 128M | fcram ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB) @@ -153,11 +153,11 @@ disableMpuAndJumpToEntrypoints: bic r0, #(1<<0) @ - MPU disable mcr p15, 0, r0, c1, c0, 0 @ write control register - @ Set the ARM11 entrypoint + @ Set the Arm11 entrypoint mov r0, #0x20000000 str r7, [r0, #-4] - @ Jump to the ARM9 entrypoint + @ Jump to the Arm9 entrypoint mov r0, r4 mov r1, r5 ldr r2, =0x3BEEF diff --git a/arm9/source/strings.c b/arm9/source/strings.c index 337e815..230fbbb 100644 --- a/arm9/source/strings.c +++ b/arm9/source/strings.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/strings.h b/arm9/source/strings.h index 50925fd..f58cb90 100644 --- a/arm9/source/strings.h +++ b/arm9/source/strings.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/types.h b/arm9/source/types.h index 99468de..20e6938 100644 --- a/arm9/source/types.h +++ b/arm9/source/types.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/utils.c b/arm9/source/utils.c index 38fb640..d789761 100644 --- a/arm9/source/utils.c +++ b/arm9/source/utils.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/arm9/source/utils.h b/arm9/source/utils.h index b71af07..83bf7ea 100644 --- a/arm9/source/utils.h +++ b/arm9/source/utils.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/exception_dump_parser/luma3ds_exception_dump_parser/__main__.py b/exception_dump_parser/luma3ds_exception_dump_parser/__main__.py index 845ed92..d8ae1f8 100755 --- a/exception_dump_parser/luma3ds_exception_dump_parser/__main__.py +++ b/exception_dump_parser/luma3ds_exception_dump_parser/__main__.py @@ -2,7 +2,7 @@ # Requires Python >= 3.2 or >= 2.7 # This file is part of Luma3DS -# Copyright (C) 2016-2019 Aurora Wright, TuxSH +# 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 @@ -22,7 +22,7 @@ # Notices displayed by works containing it. __author__ = "TuxSH" -__copyright__ = "Copyright (c) 2016 TuxSH" +__copyright__ = "Copyright (c) 2016-2020 TuxSH" __license__ = "GPLv3" __version__ = "v1.2" @@ -121,8 +121,8 @@ def main(args=None): addtionalDataOffset = stackOffset + stackDumpSize additionalData = data[addtionalDataOffset : addtionalDataOffset + additionalDataSize] - if processor == 9: print("Processor: ARM9") - else: print("Processor: ARM11 (core {0})".format(processor >> 16)) + if processor == 9: print("Processor: Arm9") + else: print("Processor: Arm11 (core {0})".format(processor >> 16)) typeDetailsStr = "" if exceptionType == 2: diff --git a/k11_extension/include/config.h b/k11_extension/include/config.h index 5193cc2..1970796 100644 --- a/k11_extension/include/config.h +++ b/k11_extension/include/config.h @@ -33,5 +33,6 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHUNITINFO, - DISABLEARM11EXCHANDLERS + DISABLEARM11EXCHANDLERS, + ENABLESAFEFIRMROSALINA, }; diff --git a/k11_extension/include/debug.h b/k11_extension/include/debug.h index 5c2254b..a1e3608 100644 --- a/k11_extension/include/debug.h +++ b/k11_extension/include/debug.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/fatalExceptionHandlers.h b/k11_extension/include/fatalExceptionHandlers.h index cd19e05..b71d29d 100644 --- a/k11_extension/include/fatalExceptionHandlers.h +++ b/k11_extension/include/fatalExceptionHandlers.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/globals.h b/k11_extension/include/globals.h index 81586c2..2959d21 100644 --- a/k11_extension/include/globals.h +++ b/k11_extension/include/globals.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -141,6 +141,8 @@ typedef struct CfwInfo } CfwInfo; extern CfwInfo cfwInfo; +extern u32 kextBasePa; +extern u32 stolenSystemMemRegionSize; extern vu32 rosalinaState; extern bool hasStartedRosalinaNetworkFuncsOnce; diff --git a/k11_extension/include/ipc.h b/k11_extension/include/ipc.h index d809ee3..2ca055a 100644 --- a/k11_extension/include/ipc.h +++ b/k11_extension/include/ipc.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -57,5 +57,4 @@ void SessionInfo_Add(KSession *session, const char *name); void SessionInfo_Remove(KSession *session); bool doLangEmu(Result *res, u32 *cmdbuf); -Result doPublishToProcessHook(Handle handle, u32 *cmdbuf); bool doErrfThrowHook(u32 *cmdbuf); diff --git a/k11_extension/include/kernel.h b/k11_extension/include/kernel.h index 6867eba..af57271 100644 --- a/k11_extension/include/kernel.h +++ b/k11_extension/include/kernel.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -1188,11 +1188,11 @@ typedef union KCacheMaintenanceInterruptEvent typedef struct FcramLayout { - void *applicationAddr; + u32 applicationAddr; u32 applicationSize; - void *systemAddr; + u32 systemAddr; u32 systemSize; - void *baseAddr; + u32 baseAddr; u32 baseSize; } FcramLayout; @@ -1200,15 +1200,15 @@ extern bool isN3DS; extern void *officialSVCs[0x7E]; #define KPROCESSRELATED_OFFSETOFF(classname, field) (isN3DS ? offsetof(classname##N3DS, field) :\ -((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(classname##O3DS8x, field) :\ +((GET_VERSION_MINOR(kernelVersion) >= 44) ? offsetof(classname##O3DS8x, field) :\ offsetof(classname##O3DSPre8x, field))) #define KPROCESSRELATED_GET_PTR(obj, field) (isN3DS ? &(obj)->N3DS.field :\ -((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? &(obj)->O3DS8x.field :\ +((GET_VERSION_MINOR(kernelVersion) >= 44) ? &(obj)->O3DS8x.field :\ &(obj)->O3DSPre8x.field)) #define KPROCESSRELATED_GET_PTR_TYPE(type, obj, field) (isN3DS ? (type *)(&(obj)->N3DS.field) :\ -((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? (type *)(&(obj)->O3DS8x.field) :\ +((GET_VERSION_MINOR(kernelVersion) >= 44) ? (type *)(&(obj)->O3DS8x.field) :\ (type *)(&(obj)->O3DSPre8x.field))) #define KPROCESS_OFFSETOF(field) KPROCESSRELATED_OFFSETOFF(KProcess, field) @@ -1251,7 +1251,7 @@ static inline KDebug *debugOfProcess(KProcess *process) static inline const char *classNameOfAutoObject(KAutoObject *object) { const char *name; - if(kernelVersion >= SYSTEM_VERSION(2, 46, 0)) + if(GET_VERSION_MINOR(kernelVersion) >= 46) { KClassToken tok; object->vtable->GetClassToken(&tok, object); @@ -1267,7 +1267,7 @@ extern Result (*KProcessHandleTable__CreateHandle)(KProcessHandleTable *this, Ha static inline Result createHandleForProcess(Handle *out, KProcess *process, KAutoObject *obj) { u8 token; - if(kernelVersion >= SYSTEM_VERSION(2, 46, 0)) + if(GET_VERSION_MINOR(kernelVersion) >= 46) { KClassToken tok; obj->vtable->GetClassToken(&tok, obj); diff --git a/k11_extension/include/svc.h b/k11_extension/include/svc.h index 665faef..d2cf45b 100644 --- a/k11_extension/include/svc.h +++ b/k11_extension/include/svc.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/Backdoor.h b/k11_extension/include/svc/Backdoor.h index a713d25..fcd0eab 100644 --- a/k11_extension/include/svc/Backdoor.h +++ b/k11_extension/include/svc/Backdoor.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/Break.h b/k11_extension/include/svc/Break.h index 039eeb4..7a6e283 100644 --- a/k11_extension/include/svc/Break.h +++ b/k11_extension/include/svc/Break.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/ConnectToPort.h b/k11_extension/include/svc/ConnectToPort.h index 97c87bb..c47b9a9 100644 --- a/k11_extension/include/svc/ConnectToPort.h +++ b/k11_extension/include/svc/ConnectToPort.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/ControlMemory.h b/k11_extension/include/svc/ControlMemory.h index ee8c4fb..cc3a632 100644 --- a/k11_extension/include/svc/ControlMemory.h +++ b/k11_extension/include/svc/ControlMemory.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/ControlService.h b/k11_extension/include/svc/ControlService.h index abaed13..e6e926b 100644 --- a/k11_extension/include/svc/ControlService.h +++ b/k11_extension/include/svc/ControlService.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/CopyHandle.h b/k11_extension/include/svc/CopyHandle.h index ef01496..c958c57 100644 --- a/k11_extension/include/svc/CopyHandle.h +++ b/k11_extension/include/svc/CopyHandle.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/CustomBackdoor.h b/k11_extension/include/svc/CustomBackdoor.h index 6c6e8a8..734abd7 100644 --- a/k11_extension/include/svc/CustomBackdoor.h +++ b/k11_extension/include/svc/CustomBackdoor.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/GetCFWInfo.h b/k11_extension/include/svc/GetCFWInfo.h index 0c2c584..e695b2f 100644 --- a/k11_extension/include/svc/GetCFWInfo.h +++ b/k11_extension/include/svc/GetCFWInfo.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/GetHandleInfo.h b/k11_extension/include/svc/GetHandleInfo.h index f8f2aa3..6f49ec3 100644 --- a/k11_extension/include/svc/GetHandleInfo.h +++ b/k11_extension/include/svc/GetHandleInfo.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/GetProcessInfo.h b/k11_extension/include/svc/GetProcessInfo.h index 278a233..7a8275d 100644 --- a/k11_extension/include/svc/GetProcessInfo.h +++ b/k11_extension/include/svc/GetProcessInfo.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/GetSystemInfo.h b/k11_extension/include/svc/GetSystemInfo.h index d512e1a..5d6da1b 100644 --- a/k11_extension/include/svc/GetSystemInfo.h +++ b/k11_extension/include/svc/GetSystemInfo.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/GetThreadInfo.h b/k11_extension/include/svc/GetThreadInfo.h index 7ab8876..23c4cd5 100644 --- a/k11_extension/include/svc/GetThreadInfo.h +++ b/k11_extension/include/svc/GetThreadInfo.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/KernelSetState.h b/k11_extension/include/svc/KernelSetState.h index 20d5f18..aae13ae 100644 --- a/k11_extension/include/svc/KernelSetState.h +++ b/k11_extension/include/svc/KernelSetState.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/MapProcessMemoryEx.h b/k11_extension/include/svc/MapProcessMemoryEx.h index c4e1e76..0b357af 100644 --- a/k11_extension/include/svc/MapProcessMemoryEx.h +++ b/k11_extension/include/svc/MapProcessMemoryEx.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/SendSyncRequest.h b/k11_extension/include/svc/SendSyncRequest.h index 550a8a2..cb803bd 100644 --- a/k11_extension/include/svc/SendSyncRequest.h +++ b/k11_extension/include/svc/SendSyncRequest.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/SetGpuProt.h b/k11_extension/include/svc/SetGpuProt.h index ae0f334..d1c39dd 100644 --- a/k11_extension/include/svc/SetGpuProt.h +++ b/k11_extension/include/svc/SetGpuProt.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/SetWifiEnabled.h b/k11_extension/include/svc/SetWifiEnabled.h index 3639095..83da7c5 100644 --- a/k11_extension/include/svc/SetWifiEnabled.h +++ b/k11_extension/include/svc/SetWifiEnabled.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/TranslateHandle.h b/k11_extension/include/svc/TranslateHandle.h index cffacb6..dae82dc 100644 --- a/k11_extension/include/svc/TranslateHandle.h +++ b/k11_extension/include/svc/TranslateHandle.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svc/UnmapProcessMemoryEx.h b/k11_extension/include/svc/UnmapProcessMemoryEx.h index a13576c..08097af 100644 --- a/k11_extension/include/svc/UnmapProcessMemoryEx.h +++ b/k11_extension/include/svc/UnmapProcessMemoryEx.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/svcHandler.h b/k11_extension/include/svcHandler.h index 281dd29..73623f2 100644 --- a/k11_extension/include/svcHandler.h +++ b/k11_extension/include/svcHandler.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/synchronization.h b/k11_extension/include/synchronization.h index dcf5bf5..32635a7 100644 --- a/k11_extension/include/synchronization.h +++ b/k11_extension/include/synchronization.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/include/types.h b/k11_extension/include/types.h index 3b92cd8..2b6c2b0 100644 --- a/k11_extension/include/types.h +++ b/k11_extension/include/types.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -78,6 +78,15 @@ typedef s32 Result; ///< Function result. #define SYSTEM_VERSION(major, minor, revision) \ (((major)<<24)|((minor)<<16)|((revision)<<8)) +/// Retrieves the major version from a packed system version. +#define GET_VERSION_MAJOR(version) ((version) >>24) + +/// Retrieves the minor version from a packed system version. +#define GET_VERSION_MINOR(version) (((version)>>16)&0xFF) + +/// Retrieves the revision version from a packed system version. +#define GET_VERSION_REVISION(version) (((version)>> 8)&0xFF) + #define CUR_THREAD_HANDLE 0xFFFF8000 #define CUR_PROCESS_HANDLE 0xFFFF8001 diff --git a/k11_extension/include/utils.h b/k11_extension/include/utils.h index 1366e29..fbac8c7 100644 --- a/k11_extension/include/utils.h +++ b/k11_extension/include/utils.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,7 +33,7 @@ #define PA_PTR(addr) (void *)((u32)(addr) | 1u << 31) #define PA_FROM_VA_PTR(addr) PA_PTR(convertVAToPA(addr, false)) -static inline u32 makeARMBranch(const void *src, const void *dst, bool link) // the macros for those are ugly and buggy +static inline u32 makeArmBranch(const void *src, const void *dst, bool link) // the macros for those are ugly and buggy { u32 instrBase = link ? 0xEB000000 : 0xEA000000; u32 off = (u32)((const u8 *)dst - ((const u8 *)src + 8)); // the PC is always two instructions ahead of the one being executed @@ -41,7 +41,7 @@ static inline u32 makeARMBranch(const void *src, const void *dst, bool link) // return instrBase | ((off >> 2) & 0xFFFFFF); } -static inline void *decodeARMBranch(const void *src) +static inline void *decodeArmBranch(const void *src) { u32 instr = *(const u32 *)src; s32 off = (instr & 0xFFFFFF) << 2; @@ -50,8 +50,8 @@ static inline void *decodeARMBranch(const void *src) return (void *)((const u8 *)src + 8 + off); } -// For ARM prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases) -static inline u32 computeARMFrameSize(const u32 *prolog) +// For Arm prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases) +static inline u32 computeArmFrameSize(const u32 *prolog) { const u32 *off; diff --git a/k11_extension/linker.ld b/k11_extension/linker.ld index 57d75ba..18c2329 100644 --- a/k11_extension/linker.ld +++ b/k11_extension/linker.ld @@ -5,7 +5,7 @@ ENTRY(_start) MEMORY { vram : ORIGIN = 0x18000000, LENGTH = 0x18180000 - 0x18000000 /* Up to the kernel builtins. */ - main : ORIGIN = 0x40000000, LENGTH = 1M + main : ORIGIN = 0x70000000, LENGTH = 1M } PHDRS @@ -15,7 +15,7 @@ PHDRS SECTIONS { - PROVIDE(__start__ = 0x40000000); + PROVIDE(__start__ = ORIGIN(main)); . = ABSOLUTE(__start__); .text : diff --git a/k11_extension/source/debug.c b/k11_extension/source/debug.c index cf72e40..8f46acb 100644 --- a/k11_extension/source/debug.c +++ b/k11_extension/source/debug.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/fatalExceptionHandlers.s b/k11_extension/source/fatalExceptionHandlers.s index ec4ddec..be97131 100644 --- a/k11_extension/source/fatalExceptionHandlers.s +++ b/k11_extension/source/fatalExceptionHandlers.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/fatalExceptionHandlersMain.c b/k11_extension/source/fatalExceptionHandlersMain.c index 476d52b..1a71746 100644 --- a/k11_extension/source/fatalExceptionHandlersMain.c +++ b/k11_extension/source/fatalExceptionHandlersMain.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/globals.c b/k11_extension/source/globals.c index ad5d2d1..d310171 100644 --- a/k11_extension/source/globals.c +++ b/k11_extension/source/globals.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -110,13 +110,14 @@ u32 nbSection0Modules; Result (*InterruptManager__MapInterrupt)(InterruptManager *manager, KBaseInterruptEvent *iEvent, u32 interruptID, u32 coreID, u32 priority, bool disableUponReceipt, bool levelHighActive); InterruptManager *interruptManager; -KBaseInterruptEvent *customInterruptEvent; void (*initFPU)(void); void (*mcuReboot)(void); void (*coreBarrier)(void); CfwInfo cfwInfo; +u32 kextBasePa; +u32 stolenSystemMemRegionSize; vu32 rosalinaState; bool hasStartedRosalinaNetworkFuncsOnce; diff --git a/k11_extension/source/ipc.c b/k11_extension/source/ipc.c index 656d8a9..74a5d72 100644 --- a/k11_extension/source/ipc.c +++ b/k11_extension/source/ipc.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -235,48 +235,6 @@ bool doLangEmu(Result *res, u32 *cmdbuf) return skip; } -Result doPublishToProcessHook(Handle handle, u32 *cmdbuf) -{ - Result res = 0; - u32 pid; - bool terminateRosalina = cmdbuf[1] == 0x100 && cmdbuf[2] == 0; // cmdbuf[2] to check for well-formed requests - u32 savedCmdbuf[4]; - memcpy(savedCmdbuf, cmdbuf, 16); - - if(!terminateRosalina || GetProcessId(&pid, cmdbuf[3]) != 0) - terminateRosalina = false; - else - { - KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess); - KProcess *process = KProcessHandleTable__ToKProcess(handleTable, cmdbuf[3]); - if((strcmp(codeSetOfProcess(process)->processName, "socket") == 0 && (rosalinaState & 2)) || - strcmp(codeSetOfProcess(process)->processName, "pxi") == 0) - terminateRosalina = true; - else - terminateRosalina = false; - ((KAutoObject *)process)->vtable->DecrementReferenceCount((KAutoObject *)process); - } - - if(terminateRosalina && nbSection0Modules == 6) - { - Handle rosalinaProcessHandle; - res = OpenProcess(&rosalinaProcessHandle, 5); - if(res == 0) - { - cmdbuf[0] = cmdbuf[0]; - cmdbuf[1] = 0x100; - cmdbuf[2] = 0; - cmdbuf[3] = rosalinaProcessHandle; - - res = SendSyncRequest(handle); - CloseHandle(rosalinaProcessHandle); - memcpy(cmdbuf, savedCmdbuf, 16); - } - } - - return SendSyncRequest(handle); -} - bool doErrfThrowHook(u32 *cmdbuf) { // If fatalErrorInfo->type is "card removed" or "logged", returning from ERRF:Throw is a no-op @@ -288,24 +246,24 @@ bool doErrfThrowHook(u32 *cmdbuf) u8 *srcerrbuf = (u8 *)r0_to_r7_r12_usr[(spsr & 0x20) ? 4 : 6]; const char *pname = codeSetOfProcess(currentCoreContext->objectContext.currentProcess)->processName; - static const struct + const struct { const char *name; Result errCode; + bool enabled; } errorCodesToIgnore[] = { /* - If you're getting this error, you have broken your head-tracking hardware, - and should uncomment the following line: + If you're getting this error, you may have broken your head-tracking hardware, + and you need to enable the qtm error bypass below: */ - //{ "qtm", (Result)0xF96183FE }, - - { "", 0 }, // impossible case to ensure the array has at least 1 element + { "qtm", 0xF96183FEu, CONFIG(ENABLESAFEFIRMROSALINA)}, + { "", 0, false}, // impossible case to ensure the array has at least 1 element }; for(u32 i = 0; i < sizeof(errorCodesToIgnore) / sizeof(errorCodesToIgnore[0]); i++) { - if(strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode) + if(errorCodesToIgnore[i].enabled && strcmp(pname, errorCodesToIgnore[i].name) == 0 && (Result)cmdbuf[2] == errorCodesToIgnore[i].errCode) { srcerrbuf[0] = 5; cmdbuf[0] = 0x10040; diff --git a/k11_extension/source/main.c b/k11_extension/source/main.c index 28c503d..7c9053c 100644 --- a/k11_extension/source/main.c +++ b/k11_extension/source/main.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -32,22 +32,27 @@ #include "svc/ConnectToPort.h" #include "svcHandler.h" +#define K11EXT_VA 0x70000000 + struct KExtParameters { u32 basePA; + u32 stolenSystemMemRegionSize; void *originalHandlers[4]; u32 L1MMUTableAddrs[4]; + volatile bool done; + CfwInfo cfwInfo; } kExtParameters = { .basePA = 0x12345678 }; // place this in .data -static ALIGN(1024) u32 L2TableFor0x40000000[256] = {0}; +static ALIGN(1024) u32 g_L2Table[256] = {0}; void relocateAndSetupMMU(u32 coreId, u32 *L1Table) { - struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + 0x18000000); - struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - 0x40000000 + p0->basePA); - u32 *L2Table = (u32 *)((u32)L2TableFor0x40000000 - 0x40000000 + p0->basePA); + struct KExtParameters *p0 = (struct KExtParameters *)((u32)&kExtParameters - K11EXT_VA + 0x18000000); + struct KExtParameters *p = (struct KExtParameters *)((u32)&kExtParameters - K11EXT_VA + p0->basePA); + u32 *L2Table = (u32 *)((u32)g_L2Table - K11EXT_VA + p0->basePA); if(coreId == 0) { @@ -56,16 +61,32 @@ void relocateAndSetupMMU(u32 coreId, u32 *L1Table) memcpy((void *)p0->basePA, (const void *)0x18000000, __bss_start__ - __start__); memset((u32 *)(p0->basePA + (__bss_start__ - __start__)), 0, __bss_end__ - __bss_start__); - // Map the kernel ext to 0x40000000 - // 4KB extended small pages: [SYS:RW USR:-- X TYP:NORMAL SHARED OUTER NOCACHE, INNER CACHED WB WA] + // Map the kernel ext at K11EXT_VA + // 4KB extended small pages: + // Outer Write-Through cached, No Allocate on Write, Buffered + // Inner Cached Write-Back Write-Allocate, Buffered + // This was changed at some point (8.0 maybe?), it was outer noncached before for(u32 offset = 0; offset < (u32)(__end__ - __start__); offset += 0x1000) - L2Table[offset >> 12] = (p0->basePA + offset) | 0x516; + L2Table[offset >> 12] = (p0->basePA + offset) | 0x596; + + p0->done = true; + + // DSB, Flush Prefetch Buffer (more or less "isb") + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory"); + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory"); __asm__ __volatile__ ("sev"); } - else - __asm__ __volatile__ ("wfe"); + else { + do + { + __asm__ __volatile__ ("wfe"); + } while(!p0->done); + // DSB, Flush Prefetch Buffer (more or less "isb") + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory"); + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory"); + } // bit31 idea thanks to SALT // Maps physmem so that, if addr is in physmem(0, 0x30000000), it can be accessed uncached&rwx as addr|(1<<31) u32 attribs = 0x40C02; // supersection (rwx for all) of strongly ordered memory, shared @@ -76,9 +97,13 @@ void relocateAndSetupMMU(u32 coreId, u32 *L1Table) L1Table[i + (VA >> 20)] = PA | attribs; } - L1Table[0x40000000 >> 20] = (u32)L2Table | 1; + L1Table[K11EXT_VA >> 20] = (u32)L2Table | 1; p->L1MMUTableAddrs[coreId] = (u32)L1Table; + + // DSB, Flush Prefetch Buffer (more or less "isb") + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory"); + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory"); } void bindSGI0Hook(void) @@ -158,62 +183,62 @@ static void findUsefulSymbols(void) for(; *off != 0xE3A0A0C2; off++); mcuReboot = (void (*) (void))--off; - coreBarrier = (void (*) (void))decodeARMBranch(off - 4); + coreBarrier = (void (*) (void))decodeArmBranch(off - 4); for(off = (u32 *)originalHandlers[2]; *off != 0xE1A00009; off++); - svcFallbackHandler = (void (*)(u8))decodeARMBranch(off + 1); + svcFallbackHandler = (void (*)(u8))decodeArmBranch(off + 1); for(; *off != 0xE92D000F; off++); - officialPostProcessSvc = (void (*)(void))decodeARMBranch(off + 1); + officialPostProcessSvc = (void (*)(void))decodeArmBranch(off + 1); - KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeARMBranch(5 + (u32 *)officialSVCs[0x76]); + KProcessHandleTable__ToKProcess = (KProcess * (*)(KProcessHandleTable *, Handle))decodeArmBranch(5 + (u32 *)officialSVCs[0x76]); for(off = (u32 *)KProcessHandleTable__ToKProcess; *off != 0xE1A00004; off++); - KAutoObject__AddReference = (void (*)(KAutoObject *))decodeARMBranch(off + 1); + KAutoObject__AddReference = (void (*)(KAutoObject *))decodeArmBranch(off + 1); for(; *off != 0xE320F000; off++); - KProcessHandleTable__ToKAutoObject = (KAutoObject * (*)(KProcessHandleTable *, Handle))decodeARMBranch(off + 1); + KProcessHandleTable__ToKAutoObject = (KAutoObject * (*)(KProcessHandleTable *, Handle))decodeArmBranch(off + 1); - for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[9]); /* KThread::Terminate */ *off != 0xE5D42034; off++); + for(off = (u32 *)decodeArmBranch(3 + (u32 *)officialSVCs[9]); /* KThread::Terminate */ *off != 0xE5D42034; off++); off -= 2; criticalSectionLock = (KRecursiveLock *)off[2 + (off[0] & 0xFF) / 4]; - KRecursiveLock__Lock = (void (*)(KRecursiveLock *))decodeARMBranch(off + 1); + KRecursiveLock__Lock = (void (*)(KRecursiveLock *))decodeArmBranch(off + 1); off += 4; for(; (*off >> 16) != 0xE59F; off++); - KRecursiveLock__Unlock = (void (*)(KRecursiveLock *))decodeARMBranch(off + 1); + KRecursiveLock__Unlock = (void (*)(KRecursiveLock *))decodeArmBranch(off + 1); for(; *off != 0xE5C4007D; off++); - KSynchronizationObject__Signal = (void (*)(KSynchronizationObject *, bool))decodeARMBranch(off + 3); + KSynchronizationObject__Signal = (void (*)(KSynchronizationObject *, bool))decodeArmBranch(off + 3); for(off = (u32 *)officialSVCs[0x19]; *off != 0xE1A04005; off++); - KEvent__Clear = (Result (*)(KEvent *))decodeARMBranch(off + 1); + KEvent__Clear = (Result (*)(KEvent *))decodeArmBranch(off + 1); for(off = (u32 *)KEvent__Clear; *off != 0xE8BD8070; off++); synchronizationMutex = *(KObjectMutex **)(off + 1); for(off = (u32 *)officialSVCs[0x24]; *off != 0xE59F004C; off++); - WaitSynchronization1 = (Result (*)(void *, KThread *, KSynchronizationObject *, s64))decodeARMBranch(off + 6); + WaitSynchronization1 = (Result (*)(void *, KThread *, KSynchronizationObject *, s64))decodeArmBranch(off + 6); - for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x33]) /* OpenProcess */ ; *off != 0xE1A05000; off++); - KProcessHandleTable__CreateHandle = (Result (*)(KProcessHandleTable *, Handle *, KAutoObject *, u8))decodeARMBranch(off - 1); + for(off = (u32 *)decodeArmBranch(3 + (u32 *)officialSVCs[0x33]) /* OpenProcess */ ; *off != 0xE1A05000; off++); + KProcessHandleTable__CreateHandle = (Result (*)(KProcessHandleTable *, Handle *, KAutoObject *, u8))decodeArmBranch(off - 1); - for(off = (u32 *)decodeARMBranch(3 + (u32 *)officialSVCs[0x34]) /* OpenThread */; *off != 0xD9001BF7; off++); + for(off = (u32 *)decodeArmBranch(3 + (u32 *)officialSVCs[0x34]) /* OpenThread */; *off != 0xD9001BF7; off++); threadList = *(KObjectList **)(off + 1); - off = (u32 *)decodeARMBranch((u32 *)officialSVCs[0x37] + 3) + 5; /* GetThreadId */ - KProcessHandleTable__ToKThread = (KThread * (*)(KProcessHandleTable *, Handle))decodeARMBranch((*off >> 16) == 0xEB00 ? off : off + 2); + off = (u32 *)decodeArmBranch((u32 *)officialSVCs[0x37] + 3) + 5; /* GetThreadId */ + KProcessHandleTable__ToKThread = (KThread * (*)(KProcessHandleTable *, Handle))decodeArmBranch((*off >> 16) == 0xEB00 ? off : off + 2); for(off = (u32 *)officialSVCs[0x50]; off[0] != 0xE1A05000 || off[1] != 0xE2100102 || off[2] != 0x5A00000B; off++); - InterruptManager__MapInterrupt = (Result (*)(InterruptManager *, KBaseInterruptEvent *, u32, u32, u32, bool, bool))decodeARMBranch(--off); + InterruptManager__MapInterrupt = (Result (*)(InterruptManager *, KBaseInterruptEvent *, u32, u32, u32, bool, bool))decodeArmBranch(--off); interruptManager = *(InterruptManager **)(off - 4 + (off[-6] & 0xFFF) / 4); for(off = (u32 *)officialSVCs[0x54]; *off != 0xE8BD8008; off++); flushDataCacheRange = (void (*)(void *, u32))(*(u32 **)(off[1]) + 3); for(off = (u32 *)officialSVCs[0x71]; *off != 0xE2101102; off++); - KProcessHwInfo__MapProcessMemory = (Result (*)(KProcessHwInfo *, KProcessHwInfo *, void *, void *, u32))decodeARMBranch(off - 1); + KProcessHwInfo__MapProcessMemory = (Result (*)(KProcessHwInfo *, KProcessHwInfo *, void *, void *, u32))decodeArmBranch(off - 1); // From 4.x to 6.x the pattern will match but the result will be wrong for(off = (u32 *)officialSVCs[0x72]; *off != 0xE2041102; off++); - KProcessHwInfo__UnmapProcessMemory = (Result (*)(KProcessHwInfo *, void *, u32))decodeARMBranch(off - 1); + KProcessHwInfo__UnmapProcessMemory = (Result (*)(KProcessHwInfo *, void *, u32))decodeArmBranch(off - 1); for (off = (u32 *)officialSVCs[0x70]; *off != 0xE8881200 && *off != 0xE8891900; ++off); for (off = (u32 *)decodeARMBranch(off + 1); *off != 0xE2101102; ++off); @@ -228,9 +253,9 @@ static void findUsefulSymbols(void) KLinkedList_KBlockInfo__Clear = (void (*)(KLinkedList *))decodeARMBranch(off - 6); for(off = (u32 *)officialSVCs[0x7C]; *off != 0x03530000; off++); - KObjectMutex__WaitAndAcquire = (void (*)(KObjectMutex *))decodeARMBranch(++off); + KObjectMutex__WaitAndAcquire = (void (*)(KObjectMutex *))decodeArmBranch(++off); for(; *off != 0xE320F000; off++); - KObjectMutex__ErrorOccured = (void (*)(void))decodeARMBranch(off + 1); + KObjectMutex__ErrorOccured = (void (*)(void))decodeArmBranch(off + 1); for(off = (u32 *)originalHandlers[4]; *off != (u32)exceptionStackTop; off++); kernelUsrCopyFuncsStart = (void *)off[1]; @@ -270,28 +295,28 @@ static void findUsefulSymbols(void) // The official prototype of ControlMemory doesn't have that extra param' ControlMemory = (Result (*)(u32 *, u32, u32, u32, MemOp, MemPerm, bool)) - decodeARMBranch((u32 *)officialSVCs[0x01] + 5); + decodeArmBranch((u32 *)officialSVCs[0x01] + 5); SleepThread = (void (*)(s64))officialSVCs[0x0A]; CreateEvent = (Result (*)(Handle *, ResetType))decodeARMBranch((u32 *)officialSVCs[0x17] + 3); CloseHandle = (Result (*)(Handle))officialSVCs[0x23]; - GetHandleInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x29] + 3); - GetSystemInfo = (Result (*)(s64 *, s32, s32))decodeARMBranch((u32 *)officialSVCs[0x2A] + 3); - GetProcessInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2B] + 3); - GetThreadInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2C] + 3); - ConnectToPort = (Result (*)(Handle *, const char*))decodeARMBranch((u32 *)officialSVCs[0x2D] + 3); + GetHandleInfo = (Result (*)(s64 *, Handle, u32))decodeArmBranch((u32 *)officialSVCs[0x29] + 3); + GetSystemInfo = (Result (*)(s64 *, s32, s32))decodeArmBranch((u32 *)officialSVCs[0x2A] + 3); + GetProcessInfo = (Result (*)(s64 *, Handle, u32))decodeArmBranch((u32 *)officialSVCs[0x2B] + 3); + GetThreadInfo = (Result (*)(s64 *, Handle, u32))decodeArmBranch((u32 *)officialSVCs[0x2C] + 3); + ConnectToPort = (Result (*)(Handle *, const char*))decodeArmBranch((u32 *)officialSVCs[0x2D] + 3); SendSyncRequest = (Result (*)(Handle))officialSVCs[0x32]; - OpenProcess = (Result (*)(Handle *, u32))decodeARMBranch((u32 *)officialSVCs[0x33] + 3); - GetProcessId = (Result (*)(u32 *, Handle))decodeARMBranch((u32 *)officialSVCs[0x35] + 3); - DebugActiveProcess = (Result (*)(Handle *, u32))decodeARMBranch((u32 *)officialSVCs[0x60] + 3); + OpenProcess = (Result (*)(Handle *, u32))decodeArmBranch((u32 *)officialSVCs[0x33] + 3); + GetProcessId = (Result (*)(u32 *, Handle))decodeArmBranch((u32 *)officialSVCs[0x35] + 3); + DebugActiveProcess = (Result (*)(Handle *, u32))decodeArmBranch((u32 *)officialSVCs[0x60] + 3); SignalEvent = (Result (*)(Handle event))officialSVCs[0x18]; UnmapProcessMemory = (Result (*)(Handle, void *, u32))officialSVCs[0x72]; KernelSetState = (Result (*)(u32, u32, u32, u32))((u32 *)officialSVCs[0x7C] + 1); for(off = (u32 *)svcFallbackHandler; *off != 0xE8BD4010; off++); - kernelpanic = (void (*)(void))decodeARMBranch(off + 1); + kernelpanic = (void (*)(void))decodeArmBranch(off + 1); for(off = (u32 *)0xFFFF0000; off[0] != 0xE3A01002 || off[1] != 0xE3A00004; off++); - SignalDebugEvent = (Result (*)(DebugEventType type, u32 info, ...))decodeARMBranch(off + 2); + SignalDebugEvent = (Result (*)(DebugEventType type, u32 info, ...))decodeArmBranch(off + 2); for(; *off != 0x96007F9; off++); isDevUnit = *(bool **)(off - 1); @@ -325,7 +350,11 @@ void main(FcramLayout *layout, KCoreContext *ctxs) u32 TTBCR_; s64 nb; - layout->systemSize -= __end__ - __start__; + cfwInfo = p->cfwInfo; + kextBasePa = p->basePA; + stolenSystemMemRegionSize = p->stolenSystemMemRegionSize; + + layout->systemSize -= stolenSystemMemRegionSize; fcramLayout = *layout; coreCtxs = ctxs; @@ -334,7 +363,6 @@ void main(FcramLayout *layout, KCoreContext *ctxs) isN3DS = getNumberOfCores() == 4; memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16); exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20)); - cfwInfo = p->cfwInfo; memcpy(originalHandlers + 1, p->originalHandlers, 16); void **arm11SvcTable = (void**)originalHandlers[2]; @@ -348,4 +376,8 @@ void main(FcramLayout *layout, KCoreContext *ctxs) rosalinaState = 0; hasStartedRosalinaNetworkFuncsOnce = false; + + // DSB, Flush Prefetch Buffer (more or less "isb") + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" :: "r" (0) : "memory"); + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" :: "r" (0) : "memory"); } diff --git a/k11_extension/source/start.s b/k11_extension/source/start.s index 5b581c1..a4e29f2 100644 --- a/k11_extension/source/start.s +++ b/k11_extension/source/start.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/svc.c b/k11_extension/source/svc.c index f967505..5adba80 100644 --- a/k11_extension/source/svc.c +++ b/k11_extension/source/svc.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/Backdoor.s b/k11_extension/source/svc/Backdoor.s index e1e31ea..9f0a29d 100644 --- a/k11_extension/source/svc/Backdoor.s +++ b/k11_extension/source/svc/Backdoor.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/svc/Break.s b/k11_extension/source/svc/Break.s index e0512c1..86de0ad 100644 --- a/k11_extension/source/svc/Break.s +++ b/k11_extension/source/svc/Break.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/svc/ConnectToPort.c b/k11_extension/source/svc/ConnectToPort.c index b87a88b..29eb155 100644 --- a/k11_extension/source/svc/ConnectToPort.c +++ b/k11_extension/source/svc/ConnectToPort.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/ControlMemory.c b/k11_extension/source/svc/ControlMemory.c index ceb667b..a53c858 100644 --- a/k11_extension/source/svc/ControlMemory.c +++ b/k11_extension/source/svc/ControlMemory.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/ControlService.c b/k11_extension/source/svc/ControlService.c index 249ae57..de4349d 100644 --- a/k11_extension/source/svc/ControlService.c +++ b/k11_extension/source/svc/ControlService.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/CopyHandle.c b/k11_extension/source/svc/CopyHandle.c index 1ad3af8..678b1d2 100644 --- a/k11_extension/source/svc/CopyHandle.c +++ b/k11_extension/source/svc/CopyHandle.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/CustomBackdoor.s b/k11_extension/source/svc/CustomBackdoor.s index 6ef15e3..ff6b668 100644 --- a/k11_extension/source/svc/CustomBackdoor.s +++ b/k11_extension/source/svc/CustomBackdoor.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/svc/GetCFWInfo.c b/k11_extension/source/svc/GetCFWInfo.c index 59610b0..fcbb34b 100644 --- a/k11_extension/source/svc/GetCFWInfo.c +++ b/k11_extension/source/svc/GetCFWInfo.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/GetHandleInfo.c b/k11_extension/source/svc/GetHandleInfo.c index 0c8cbe6..d87f3d3 100644 --- a/k11_extension/source/svc/GetHandleInfo.c +++ b/k11_extension/source/svc/GetHandleInfo.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/GetProcessInfo.c b/k11_extension/source/svc/GetProcessInfo.c index d2ae745..58c7176 100644 --- a/k11_extension/source/svc/GetProcessInfo.c +++ b/k11_extension/source/svc/GetProcessInfo.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/GetSystemInfo.c b/k11_extension/source/svc/GetSystemInfo.c index bdb9956..3b97ea7 100644 --- a/k11_extension/source/svc/GetSystemInfo.c +++ b/k11_extension/source/svc/GetSystemInfo.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -82,10 +82,15 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param) break; case 0x300: // K11Ext size - *out = (s64)(__end__ - __start__); + *out = (s64)(((u64)kextBasePa << 32) | (u64)(__end__ - __start__)); + break; + + case 0x301: // stolen SYSTEM memory size + *out = stolenSystemMemRegionSize; break; default: + *out = 0; res = 0xF8C007F4; // not implemented break; } @@ -108,13 +113,16 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param) *out = L2C_CTRL & 1; break; default: + *out = 0; res = 0xF8C007F4; break; } } else + { + *out = 0; res = 0xF8C007F4; - + } break; } @@ -131,7 +139,10 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param) if((u32)param <= getNumberOfCores()) *out = L1MMUTableAddrs[param - 1]; else + { + *out = 0; res = 0xF8C007F4; + } break; } @@ -139,6 +150,13 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param) break; } + + case 0x20000: + { + *out = 0; + return 1; + } + default: GetSystemInfo(out, type, param); break; diff --git a/k11_extension/source/svc/GetThreadInfo.c b/k11_extension/source/svc/GetThreadInfo.c index 53faa11..628f441 100644 --- a/k11_extension/source/svc/GetThreadInfo.c +++ b/k11_extension/source/svc/GetThreadInfo.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/KernelSetState.c b/k11_extension/source/svc/KernelSetState.c index bf38826..7f8679f 100644 --- a/k11_extension/source/svc/KernelSetState.c +++ b/k11_extension/source/svc/KernelSetState.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/MapProcessMemoryEx.c b/k11_extension/source/svc/MapProcessMemoryEx.c index 6bc2367..5d0da16 100644 --- a/k11_extension/source/svc/MapProcessMemoryEx.c +++ b/k11_extension/source/svc/MapProcessMemoryEx.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/SendSyncRequest.c b/k11_extension/source/svc/SendSyncRequest.c index f266cb6..0834254 100644 --- a/k11_extension/source/svc/SendSyncRequest.c +++ b/k11_extension/source/svc/SendSyncRequest.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -47,12 +47,7 @@ Result SendSyncRequestHook(Handle handle) case 0x10042: { SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); - if(info != NULL && kernelVersion >= SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0) - { - res = doPublishToProcessHook(handle, cmdbuf); - skip = true; - } - else if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce) + if(info != NULL && strcmp(info->name, "ndm:u") == 0 && hasStartedRosalinaNetworkFuncsOnce) { cmdbuf[0] = 0x10040; cmdbuf[1] = 0; @@ -105,7 +100,7 @@ Result SendSyncRequestHook(Handle handle) case 0x50100: { SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); - if(info != NULL && (strcmp(info->name, "srv:") == 0 || (kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0))) + if(info != NULL && (strcmp(info->name, "srv:") == 0 || (GET_VERSION_MINOR(kernelVersion) < 39 && strcmp(info->name, "srv:pm") == 0))) { char name[9] = { 0 }; memcpy(name, cmdbuf + 1, 8); @@ -154,18 +149,6 @@ Result SendSyncRequestHook(Handle handle) break; } - case 0x4010042: - { - SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); - if(info != NULL && kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0) - { - res = doPublishToProcessHook(handle, cmdbuf); - skip = true; - } - - break; - } - case 0x4010082: { SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession); diff --git a/k11_extension/source/svc/SetGpuProt.c b/k11_extension/source/svc/SetGpuProt.c index 7fe66ba..9d02a95 100644 --- a/k11_extension/source/svc/SetGpuProt.c +++ b/k11_extension/source/svc/SetGpuProt.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/SetWifiEnabled.c b/k11_extension/source/svc/SetWifiEnabled.c index 0a79686..be0dd97 100644 --- a/k11_extension/source/svc/SetWifiEnabled.c +++ b/k11_extension/source/svc/SetWifiEnabled.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/TranslateHandle.c b/k11_extension/source/svc/TranslateHandle.c index 9bd90dc..ff3392f 100644 --- a/k11_extension/source/svc/TranslateHandle.c +++ b/k11_extension/source/svc/TranslateHandle.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/UnmapProcessMemoryEx.c b/k11_extension/source/svc/UnmapProcessMemoryEx.c index 8e1d19e..9b81d1b 100644 --- a/k11_extension/source/svc/UnmapProcessMemoryEx.c +++ b/k11_extension/source/svc/UnmapProcessMemoryEx.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/k11_extension/source/svc/wrappers.s b/k11_extension/source/svc/wrappers.s index c3708f0..37e4918 100644 --- a/k11_extension/source/svc/wrappers.s +++ b/k11_extension/source/svc/wrappers.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/svcHandler.s b/k11_extension/source/svcHandler.s index 305a501..e44e999 100644 --- a/k11_extension/source/svcHandler.s +++ b/k11_extension/source/svcHandler.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/k11_extension/source/synchronization.c b/k11_extension/source/synchronization.c index cf9eeb6..eb88c6a 100644 --- a/k11_extension/source/synchronization.c +++ b/k11_extension/source/synchronization.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -73,7 +73,7 @@ bool rosalinaThreadLockPredicate(KThread *thread) return false; u64 titleId = codeSetOfProcess(process)->titleId; - u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)titleId; + u32 highTitleId = (u32)(titleId >> 32), lowTitleId = (u32)(titleId & ~0xF0000001); // clear N3DS and SAFE_FIRM bits return ((rosalinaState & 1) && idOfProcess(process) >= nbSection0Modules && (highTitleId != 0x00040130 || (highTitleId == 0x00040130 && (lowTitleId == 0x1A02 || lowTitleId == 0x1C02)))); diff --git a/k11_extension/source/utils.s b/k11_extension/source/utils.s index 0aff7a8..686e7a9 100644 --- a/k11_extension/source/utils.s +++ b/k11_extension/source/utils.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 @@ -151,12 +151,14 @@ _safecpy_end: .section .rodata.safecpy_sz, "a", %progbits .global safecpy_sz +.type safecpy_sz, %object safecpy_sz: .word _safecpy_end - safecpy .section .bss.SGI0Handler, "aw", %nobits .balign 4 .global SGI0Handler +.type safecpy_sz, %object SGI0Handler: .skip 4 @ see synchronization.c .balign 4 @@ -166,4 +168,5 @@ SGI0Handler: .skip 4 @ see synchronization.c _customInterruptEventObj: .word SGI0Handler .global customInterruptEvent +.type safecpy_sz, %object customInterruptEvent: .word _customInterruptEventObj diff --git a/sysmodules/loader/LICENSE b/sysmodules/loader/LICENSE index 5fcfe11..9740558 100644 --- a/sysmodules/loader/LICENSE +++ b/sysmodules/loader/LICENSE @@ -1,6 +1,7 @@ The MIT License (MIT) Copyright (c) 2016 Yifan Lu +Copyright (c) 2016-2020 AuroraWright, TuxSH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/sysmodules/loader/Makefile b/sysmodules/loader/Makefile index 14c390d..7b88dba 100755 --- a/sysmodules/loader/Makefile +++ b/sysmodules/loader/Makefile @@ -28,16 +28,16 @@ INCLUDES := include ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \ +COMMON_FLAGS = -g -Wall -Wextra -Werror -O2 -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections \ - $(ARCH) $(DEFINES) + $(ARCH) $(DEFINES) $(INCLUDE) -CFLAGS += $(INCLUDE) +CFLAGS := -std=gnu11 $(COMMON_FLAGS) -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 +CXXFLAGS := -fno-rtti -fno-exceptions -std=gnu++17 $(COMMON_FLAGS) ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000 +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000 LIBS := -lctru diff --git a/sysmodules/loader/source/bps_patcher.cpp b/sysmodules/loader/source/bps_patcher.cpp new file mode 100644 index 0000000..0c8ca0a --- /dev/null +++ b/sysmodules/loader/source/bps_patcher.cpp @@ -0,0 +1,283 @@ +#include "bps_patcher.h" + +#include +#include +#include +#include +#include + +extern "C" +{ +#include <3ds/os.h> +#include <3ds/result.h> +#include <3ds/services/fs.h> +#include <3ds/svc.h> + +#include "patcher.h" +#include "strings.h" +} + +#include "file_util.h" + +namespace patcher +{ +namespace Bps +{ +// The BPS format uses variable length encoding for all integers. +// Realistically uint32s are more than enough for code patching. +using Number = u32; + +constexpr std::size_t FooterSize = 12; + +// The BPS format uses CRC32 checksums. +[[gnu::optimize("Os")]] static u32 crc32(const u8 *data, std::size_t size) +{ + u32 crc = 0xFFFFFFFF; + for(std::size_t i = 0; i < size; ++i) + { + crc ^= data[i]; + for(std::size_t j = 0; j < 8; ++j) + { + u32 mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + } + return ~crc; +} + +// Utility class to make keeping track of offsets and bound checks less error prone. +template +class Stream +{ +public: + Stream(T *ptr, std::size_t size) : m_ptr{ptr}, m_size{size} {} + + bool Read(void *buffer, std::size_t length) + { + if(m_offset + length > m_size) + return false; + std::memcpy(buffer, m_ptr + m_offset, length); + m_offset += length; + return true; + } + + template + [[gnu::optimize("Os")]] bool CopyFrom(Stream &other, std::size_t length) + { + if(m_offset + length > m_size) + return false; + if(!other.Read(m_ptr + m_offset, length)) + return false; + m_offset += length; + return true; + } + + template + std::optional Read() + { + static_assert(std::is_pod_v); + ValueType val{}; + if(!Read(&val, sizeof(val))) + return std::nullopt; + return val; + } + + [[gnu::optimize("Os")]] Number ReadNumber() + { + Number data = 0, shift = 1; + std::optional x; + while((x = Read())) + { + data += (*x & 0x7f) * shift; + if(*x & 0x80) + break; + shift <<= 7; + data += shift; + } + return data; + } + + auto data() const { return m_ptr; } + std::size_t size() const { return m_size; } + std::size_t Tell() const { return m_offset; } + + bool Seek(size_t offset) + { + m_offset = offset; + return true; + } + +private: + T *m_ptr = nullptr; + std::size_t m_size = 0; + std::size_t m_offset = 0; +}; + +class PatchApplier +{ +public: + PatchApplier(Stream source, Stream target, Stream patch) + : m_source{source}, m_target{target}, m_patch{patch} + { + } + + [[gnu::always_inline]] bool Apply() + { + const auto magic = *m_patch.Read>(); + if(std::string_view(magic.data(), magic.size()) != "BPS1") + return false; + + const Bps::Number source_size = m_patch.ReadNumber(); + const Bps::Number target_size = m_patch.ReadNumber(); + const Bps::Number metadata_size = m_patch.ReadNumber(); + if(source_size > m_source.size() || target_size > m_target.size() || metadata_size != 0) + return false; + + const std::size_t command_start_offset = m_patch.Tell(); + const std::size_t command_end_offset = m_patch.size() - FooterSize; + m_patch.Seek(command_end_offset); + const u32 source_crc32 = *m_patch.Read(); + const u32 target_crc32 = *m_patch.Read(); + m_patch.Seek(command_start_offset); + + if(crc32(m_source.data(), source_size) != source_crc32) + return false; + + // Process all patch commands. + std::memset(m_target.data(), 0, m_target.size()); + while(m_patch.Tell() < command_end_offset) + { + const bool ok = HandleCommand(); + if(!ok) + return false; + } + + return crc32(m_target.data(), target_size) == target_crc32; + } + +private: + bool HandleCommand() + { + const Number data = m_patch.ReadNumber(); + const Number command = data & 3; + const Number length = (data >> 2) + 1; + + switch(command) + { + case 0: + return SourceRead(length); + case 1: + return TargetRead(length); + case 2: + return SourceCopy(length); + case 3: + return TargetCopy(length); + default: + return false; + } + } + + bool SourceRead(Number length) + { + return m_source.Seek(m_target.Tell()) && m_target.CopyFrom(m_source, length); + } + + bool TargetRead(Number length) { return m_target.CopyFrom(m_patch, length); } + + bool SourceCopy(Number length) + { + const Number data = m_patch.ReadNumber(); + m_source_relative_offset += (data & 1 ? -1 : +1) * int(data >> 1); + if(!m_source.Seek(m_source_relative_offset) || !m_target.CopyFrom(m_source, length)) + return false; + m_source_relative_offset += length; + return true; + } + + bool TargetCopy(Number length) + { + const Number data = m_patch.ReadNumber(); + m_target_relative_offset += (data & 1 ? -1 : +1) * int(data >> 1); + if(m_target.Tell() + length > m_target.size()) + return false; + if(m_target_relative_offset + length > m_target.size()) + return false; + // Byte by byte copy. + for(size_t i = 0; i < length; ++i) + m_target.data()[m_target.Tell() + i] = m_target.data()[m_target_relative_offset++]; + m_target.Seek(m_target.Tell() + length); + return true; + } + + std::size_t m_source_relative_offset = 0; + std::size_t m_target_relative_offset = 0; + Stream m_source; + Stream m_target; + Stream m_patch; +}; + +} // namespace Bps + +class ScopedAppHeap +{ +public: + ScopedAppHeap() + { + u32 tmp; + m_size = osGetMemRegionFree(MEMREGION_APPLICATION); + if(!R_SUCCEEDED(svcControlMemory(&tmp, BaseAddress, 0, m_size, + MemOp(MEMOP_ALLOC | MEMOP_REGION_APP), + MemPerm(MEMPERM_READ | MEMPERM_WRITE)))) + { + svcBreak(USERBREAK_PANIC); + } + } + + ~ScopedAppHeap() + { + u32 tmp; + svcControlMemory(&tmp, BaseAddress, 0, m_size, MEMOP_FREE, MemPerm(0)); + } + + static constexpr u32 BaseAddress = 0x08000000; + +private: + u32 m_size; +}; + +static inline bool ApplyCodeBpsPatch(u64 prog_id, u8 *code, u32 size) +{ + char bps_path[] = "/luma/titles/0000000000000000/code.bps"; + progIdToStr(bps_path + 28, prog_id); + util::File patch_file; + if(!patch_file.Open(bps_path, FS_OPEN_READ)) + return true; + const u32 patch_size = u32(patch_file.GetSize().value_or(0)); + + // Temporarily use APPLICATION memory to store the source and patch data. + ScopedAppHeap memory; + + u8 *source_data = reinterpret_cast(memory.BaseAddress); + u8 *patch_data = source_data + size; + std::memcpy(source_data, code, size); + if(!patch_file.Read(patch_data, patch_size, 0)) + return false; + + Bps::Stream source_stream{source_data, size}; + Bps::Stream target_stream{code, size}; + Bps::Stream patch_stream{patch_data, patch_size}; + Bps::PatchApplier applier{source_stream, target_stream, patch_stream}; + if(!applier.Apply()) + svcBreak(USERBREAK_PANIC); + return true; +} + +} // namespace patcher + +extern "C" +{ + bool patcherApplyCodeBpsPatch(u64 progId, u8 *code, u32 size) + { + return patcher::ApplyCodeBpsPatch(progId, code, size); + } +} diff --git a/sysmodules/loader/source/bps_patcher.h b/sysmodules/loader/source/bps_patcher.h new file mode 100644 index 0000000..25e76b0 --- /dev/null +++ b/sysmodules/loader/source/bps_patcher.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif +#include <3ds/types.h> + +bool patcherApplyCodeBpsPatch(u64 progId, u8* code, u32 size); + +#ifdef __cplusplus +} +#endif diff --git a/sysmodules/loader/source/file_util.h b/sysmodules/loader/source/file_util.h new file mode 100644 index 0000000..21aee71 --- /dev/null +++ b/sysmodules/loader/source/file_util.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +extern "C" +{ +#include <3ds/result.h> +#include <3ds/services/fs.h> +#include <3ds/svc.h> +#include <3ds/types.h> +} + +namespace util +{ +inline FS_Path MakePath(const char *path) +{ + return {PATH_ASCII, strnlen(path, 255) + 1, path}; +} + +// A small wrapper to make forgetting to close a file and +// to check read lengths impossible. +class File +{ +public: + File() = default; + File(const File &other) = delete; + File &operator=(const File &) = delete; + File(File &&other) { *this = std::move(other); } + File &operator=(File &&other) + { + std::swap(m_handle, other.m_handle); + return *this; + } + + ~File() { Close(); } + + bool Close() + { + const bool ok = !m_handle || R_SUCCEEDED(FSFILE_Close(*m_handle)); + if(ok) + m_handle = std::nullopt; + return ok; + } + + bool Open(const char *path, int open_flags) + { + const FS_Path archive_path = {PATH_EMPTY, 1, ""}; + Handle handle; + const bool ok = R_SUCCEEDED(FSUSER_OpenFileDirectly(&handle, ARCHIVE_SDMC, archive_path, + MakePath(path), open_flags, 0)); + if(ok) + m_handle = handle; + return ok; + } + + bool Read(void *buffer, u32 size, u64 offset) + { + u32 bytes_read = 0; + const Result res = FSFILE_Read(*m_handle, &bytes_read, offset, buffer, size); + return R_SUCCEEDED(res) && bytes_read == size; + } + + std::optional GetSize() const + { + u64 size; + if(!R_SUCCEEDED(FSFILE_GetSize(*m_handle, &size))) + return std::nullopt; + return size; + } + +private: + std::optional m_handle; +}; + +} // namespace util diff --git a/sysmodules/loader/source/loader.c b/sysmodules/loader/source/loader.c index 73ba487..26aaf4b 100644 --- a/sysmodules/loader/source/loader.c +++ b/sysmodules/loader/source/loader.c @@ -6,7 +6,7 @@ #include "hbldr.h" extern u32 config, multiConfig, bootConfig; -extern bool isN3DS, needToInitSd, isSdMode; +extern bool isN3DS, isSdMode; static u8 g_ret_buf[sizeof(ExHeader_Info)]; static u64 g_cached_programHandle; @@ -187,9 +187,6 @@ static Result GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle) s64 nbSection0Modules; svcGetSystemInfo(&nbSection0Modules, 26, 0); - // Force always having sdmc:/ and nand:/rw permission - exheaderInfo->aci.local_caps.storage_info.fs_access_info |= FSACCESS_NANDRW | FSACCESS_SDMC_RW; - // Tweak 3dsx placeholder title exheaderInfo if (nbSection0Modules == 6 && exheaderInfo->aci.local_caps.title_id == HBLDR_3DSX_TID) { @@ -197,10 +194,12 @@ static Result GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle) HBLDR_PatchExHeaderInfo(exheaderInfo); hbldrExit(); } - - u64 originaltitleId = exheaderInfo->aci.local_caps.title_id; - if(CONFIG(PATCHGAMES) && loadTitleExheaderInfo(exheaderInfo->aci.local_caps.title_id, exheaderInfo)) - exheaderInfo->aci.local_caps.title_id = originaltitleId; + else + { + u64 originaltitleId = exheaderInfo->aci.local_caps.title_id; + if(CONFIG(PATCHGAMES) && loadTitleExheaderInfo(exheaderInfo->aci.local_caps.title_id, exheaderInfo)) + exheaderInfo->aci.local_caps.title_id = originaltitleId; + } return res; } diff --git a/sysmodules/loader/source/main.c b/sysmodules/loader/source/main.c index af1c10c..7b91768 100644 --- a/sysmodules/loader/source/main.c +++ b/sysmodules/loader/source/main.c @@ -7,7 +7,7 @@ #include "service_manager.h" u32 config, multiConfig, bootConfig; -bool isN3DS, needToInitSd, isSdMode; +bool isN3DS, isSdMode; // MAKE SURE fsreg has been init before calling this static Result fsldrPatchPermissions(void) @@ -29,27 +29,38 @@ static inline void loadCFWInfo(void) { s64 out; - assertSuccess(svcGetSystemInfo(&out, 0x10000, 3)); + if(svcGetSystemInfo(&out, 0x20000, 0) != 1) panic(0xDEADCAFE); + + svcGetSystemInfo(&out, 0x10000, 3); config = (u32)out; - assertSuccess(svcGetSystemInfo(&out, 0x10000, 4)); + svcGetSystemInfo(&out, 0x10000, 4); multiConfig = (u32)out; - assertSuccess(svcGetSystemInfo(&out, 0x10000, 5)); + svcGetSystemInfo(&out, 0x10000, 5); bootConfig = (u32)out; - assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x201)); + svcGetSystemInfo(&out, 0x10000, 0x201); isN3DS = (bool)out; - assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x202)); - needToInitSd = (bool)out; - assertSuccess(svcGetSystemInfo(&out, 0x10000, 0x203)); + svcGetSystemInfo(&out, 0x10000, 0x203); isSdMode = (bool)out; - - IFile file; - if(needToInitSd) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted } -// this is called before main -void __appInit() +void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error + +// this is called after main exits +void __wrap_exit(int rc) { + (void)rc; + // Not supposed to terminate... kernel will clean up the handles if it does happen anyway + svcExitProcess(); +} + +void __sync_init(); +void __libc_init_array(void); + +// called before main +void initSystem(void) +{ + __sync_init(); loadCFWInfo(); Result res; @@ -71,42 +82,8 @@ void __appInit() assertSuccess(FSUSER_SetPriority(0)); assertSuccess(pxiPmInit()); -} -// this is called after main exits -void __appExit() -{ - pxiPmExit(); - //fsldrExit(); - svcCloseHandle(*fsGetSessionHandle()); - fsRegExit(); - srvExit(); -} - -// stubs for non-needed pre-main functions -void __sync_init(); -void __sync_fini(); -void __system_initSyscalls(); - -void __ctru_exit() -{ - void __libc_fini_array(void); - - __libc_fini_array(); - __appExit(); - __sync_fini(); - svcExitProcess(); -} - -void initSystem() -{ - void __libc_init_array(void); - - __sync_init(); - __system_initSyscalls(); - __appInit(); - - __libc_init_array(); + //__libc_init_array(); } static const ServiceManagerServiceEntry services[] = { diff --git a/sysmodules/loader/source/patcher.c b/sysmodules/loader/source/patcher.c index 119ee3f..f38e3a4 100644 --- a/sysmodules/loader/source/patcher.c +++ b/sysmodules/loader/source/patcher.c @@ -1,5 +1,6 @@ #include <3ds.h> #include "patcher.h" +#include "bps_patcher.h" #include "memory.h" #include "strings.h" #include "romfsredir.h" @@ -369,7 +370,7 @@ bool loadTitleExheaderInfo(u64 progId, ExHeader_Info *exheaderInfo) u64 fileSize; - if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(ExHeader_Info) || fileSize != sizeof(ExHeader)) goto error; + if(R_FAILED(IFile_GetSize(&file, &fileSize)) || (fileSize != sizeof(ExHeader_Info) && fileSize != sizeof(ExHeader))) goto error; else { u64 total; @@ -469,12 +470,12 @@ static inline bool loadTitleLocaleConfig(u64 progId, u8 *mask, u8 *regionId, u8 ((buf[11] >= '0' && buf[11] <= '9') || (buf[11] >= 'a' && buf[11] <= 'f') || (buf[11] >= 'A' && buf[11] <= 'F'))) { if (buf[10] >= '0' && buf[10] <= '9') *stateId = 16 * (buf[10] - '0'); - else if(buf[10] >= 'a' && buf[10] <= 'f') *stateId = 16 * (buf[10] - 'a'); - else if(buf[10] >= 'A' && buf[10] <= 'F') *stateId = 16 * (buf[10] - 'A'); + else if(buf[10] >= 'a' && buf[10] <= 'f') *stateId = 16 * (buf[10] - 'a' + 10); + else if(buf[10] >= 'A' && buf[10] <= 'F') *stateId = 16 * (buf[10] - 'A' + 10); if (buf[11] >= '0' && buf[11] <= '9') *stateId += buf[11] - '0'; - else if(buf[11] >= 'a' && buf[11] <= 'f') *stateId += buf[11] - 'a'; - else if(buf[11] >= 'A' && buf[11] <= 'F') *stateId += buf[11] - 'A'; + else if(buf[11] >= 'a' && buf[11] <= 'f') *stateId += buf[11] - 'a' + 10; + else if(buf[11] >= 'A' && buf[11] <= 'F') *stateId += buf[11] - 'A' + 10; *mask |= 8; } @@ -503,7 +504,7 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize, fsOpenFileDirectly = 0xFFFFFFFF, payloadOffset = 0, pathOffset = 0, - pathAddress; + pathAddress = 0xDEADCAFE; if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly) || !findLayeredFsPayloadOffset(code, textSize, roSize, dataSize, roAddress, dataAddress, &payloadOffset, &pathOffset, &pathAddress)) return false; @@ -739,7 +740,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro } } - else if(progId == 0x0004013000001702LL) //CFG + else if((progId & ~0xF0000001ULL) == 0x0004013000001702LL) //CFG, SAFE_FIRM CFG { static const u8 pattern[] = { 0x06, 0x46, 0x10, 0x48 @@ -825,7 +826,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro )) goto error; } - else if(progId == 0x0004013000001A02LL) //DSP + else if((progId & ~0xF0000001ULL) == 0x0004013000001A02LL) //DSP, SAFE_FIRM DSP { static const u8 pattern[] = { 0xE3, 0x10, 0x10, 0x80, 0xE2 @@ -845,6 +846,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro if(CONFIG(PATCHGAMES)) { + if(!patcherApplyCodeBpsPatch(progId, code, size)) goto error; if(!applyCodeIpsPatch(progId, code, size)) goto error; if((u32)((progId >> 0x20) & 0xFFFFFFEDULL) == 0x00040000) diff --git a/sysmodules/loader/source/patcher.h b/sysmodules/loader/source/patcher.h index 87762ac..afc1507 100644 --- a/sysmodules/loader/source/patcher.h +++ b/sysmodules/loader/source/patcher.h @@ -35,11 +35,12 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHUNITINFO, - DISABLEARM11EXCHANDLERS + DISABLEARM11EXCHANDLERS, + ENABLESAFEFIRMROSALINA, }; extern u32 config, multiConfig, bootConfig; -extern bool isN3DS, needToInitSd, isSdMode; +extern bool isN3DS, isSdMode; void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress); Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags); diff --git a/sysmodules/loader/source/service_manager.c b/sysmodules/loader/source/service_manager.c index 33cc78e..1244133 100644 --- a/sysmodules/loader/source/service_manager.c +++ b/sysmodules/loader/source/service_manager.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/loader/source/service_manager.h b/sysmodules/loader/source/service_manager.h index 1c2c1fb..dad680c 100644 --- a/sysmodules/loader/source/service_manager.h +++ b/sysmodules/loader/source/service_manager.h @@ -1,3 +1,29 @@ +/* +* 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> diff --git a/sysmodules/pm/LICENSE b/sysmodules/pm/LICENSE index 72cba6d..eabe971 100644 --- a/sysmodules/pm/LICENSE +++ b/sysmodules/pm/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2019 TuxSH +Copyright (c) 2019-2020 TuxSH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/sysmodules/pm/Makefile b/sysmodules/pm/Makefile index b14d489..fa49ced 100644 --- a/sysmodules/pm/Makefile +++ b/sysmodules/pm/Makefile @@ -28,7 +28,7 @@ INCLUDES := include ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \ +CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Os -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections \ $(ARCH) $(DEFINES) @@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit LIBS := -lctru diff --git a/sysmodules/pm/README.md b/sysmodules/pm/README.md index 2f5f6f4..64b7ee4 100644 --- a/sysmodules/pm/README.md +++ b/sysmodules/pm/README.md @@ -1,5 +1,5 @@ # 3ds_pm -Open source replacement of the ARM11 PM system module. +Open source replacement of the Arm11 PM system module. This is licensed under the MIT license. # Usage diff --git a/sysmodules/pm/pm.rsf b/sysmodules/pm/pm.rsf index 389622b..f98f095 100644 --- a/sysmodules/pm/pm.rsf +++ b/sysmodules/pm/pm.rsf @@ -117,7 +117,11 @@ AccessControlInfo: ServiceAccessControl: # Note: pm also uses srv:pm and Loader but doesn't list them here. - fs:REG + # Custom: + - fs:USER FileSystemAccess: + # Custom + - DirectSdmc SystemControlInfo: SaveDataSize: 0KB # It doesn't use any save data. diff --git a/sysmodules/pm/source/info.c b/sysmodules/pm/source/info.c index ed43edf..d8b5a16 100644 --- a/sysmodules/pm/source/info.c +++ b/sysmodules/pm/source/info.c @@ -129,16 +129,21 @@ Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_Syste return res; } -Result GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid) +Result GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags) { ProcessList_Lock(&g_manager.processList); Result res; + + memset(outProgramInfo, 0, sizeof(FS_ProgramInfo)); if (g_manager.runningApplicationData != NULL) { - *outTitleId = g_manager.runningApplicationData->titleId; - *outPid = g_manager.runningApplicationData->pid; + ProcessData *app = g_manager.runningApplicationData; + outProgramInfo->programId = app->titleId; + outProgramInfo->mediaType = app->mediaType; + *outPid = app->pid; + *outLaunchFlags = app->launchFlags; res = 0; } else { - *outTitleId = 0; + *outPid = 0; res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100); } ProcessList_Unlock(&g_manager.processList); diff --git a/sysmodules/pm/source/info.h b/sysmodules/pm/source/info.h index 214af62..bc91ae7 100644 --- a/sysmodules/pm/source/info.h +++ b/sysmodules/pm/source/info.h @@ -12,4 +12,4 @@ Result listMergeUniqueDependencies(ProcessData **procs, u64 *dependencies, u32 * Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_SystemInfoFlags *outSiFlags, const FS_ProgramInfo *programInfo); // Custom -Result GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid); +Result GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags); diff --git a/sysmodules/pm/source/launch.c b/sysmodules/pm/source/launch.c index 56c1c57..be6accf 100644 --- a/sysmodules/pm/source/launch.c +++ b/sysmodules/pm/source/launch.c @@ -56,10 +56,12 @@ static Result loadWithoutDependencies(Handle *outDebug, ProcessData **outProcess process->pid = pid; process->titleId = exheaderInfo->aci.local_caps.title_id;; process->programHandle = programHandle; + process->launchFlags = launchFlags; // not in official PM process->flags = 0; // will be filled later process->terminatedNotificationVariation = (launchFlags & 0xF0) >> 4; process->terminationStatus = TERMSTATUS_RUNNING; process->refcount = 1; + process->mediaType = programInfo->mediaType; // not in official PM ProcessList_Unlock(&g_manager.processList); svcSignalEvent(g_manager.newProcessEvent); @@ -71,7 +73,11 @@ static Result loadWithoutDependencies(Handle *outDebug, ProcessData **outProcess u32 serviceCount; for(serviceCount = 0; serviceCount < 34 && *(u64 *)localcaps->service_access[serviceCount] != 0; serviceCount++); - TRY(FSREG_Register(pid, programHandle, programInfo, &localcaps->storage_info)); + // Not in official PM: patch local caps to give access to everything + ExHeader_Arm11StorageInfo storageInfo = localcaps->storage_info; + storageInfo.fs_access_info = 0xFFFFFFFF; + + TRY(FSREG_Register(pid, programHandle, programInfo, &storageInfo)); TRY(SRVPM_RegisterProcess(pid, serviceCount, localcaps->service_access)); if (localcaps->reslimit_category <= RESLIMIT_CATEGORY_OTHER) { @@ -135,6 +141,11 @@ static Result loadWithDependencies(Handle *outDebug, ProcessData **outProcessDat process->flags |= PROCESSFLAG_DEPENDENCIES_LOADED; } + if (launchFlags & PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING) { + // See no evil + numUnique = 0; + } + /* Official pm does this: for each dependency: @@ -208,7 +219,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const TRY(registerProgram(&programHandle, programInfo, programInfoUpdate)); res = LOADER_GetProgramInfo(exheaderInfo, programHandle); - res = R_SUCCEEDED(res) && exheaderInfo->aci.local_caps.core_info.core_version != SYSCOREVER ? (Result)0xC8A05800 : res; + res = R_SUCCEEDED(res) && SYSCOREVER == 2 && exheaderInfo->aci.local_caps.core_info.core_version != SYSCOREVER ? (Result)0xC8A05800 : res; if (R_FAILED(res)) { LOADER_UnregisterProgram(programHandle); @@ -219,18 +230,18 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const if (IS_N3DS && APPMEMTYPE == 6 && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) { u32 limitMb; SystemMode n3dsSystemMode = exheaderInfo->aci.local_caps.core_info.n3ds_system_mode; - if ((launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM) || n3dsSystemMode == SYSMODE_O3DS_PROD) { - if ((launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM) & PMLAUNCHFLAG_FORCE_USE_O3DS_MAX_APP_MEM) { - limitMb = 96; - } else { - switch (exheaderInfo->aci.local_caps.core_info.o3ds_system_mode) { - case SYSMODE_O3DS_PROD: limitMb = 64; break; - case SYSMODE_DEV1: limitMb = 96; break; - case SYSMODE_DEV2: limitMb = 80; break; - default: limitMb = 0; break; - } + bool forceO3dsAppMem = (launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM) != 0; + if (forceO3dsAppMem && (launchFlags & PMLAUNCHFLAG_FORCE_USE_O3DS_MAX_APP_MEM) != 0) { + setAppMemLimit(96 << 20); + } else if (forceO3dsAppMem || n3dsSystemMode == SYSMODE_O3DS_PROD) { + switch (exheaderInfo->aci.local_caps.core_info.o3ds_system_mode) { + case SYSMODE_O3DS_PROD: limitMb = 64; break; + case SYSMODE_DEV1: limitMb = 96; break; + case SYSMODE_DEV2: limitMb = 80; break; + default: limitMb = 0; break; } + // Can be 0: setAppMemLimit(limitMb << 20); } } diff --git a/sysmodules/pm/source/launch.h b/sysmodules/pm/source/launch.h index add0abb..e0ff125 100644 --- a/sysmodules/pm/source/launch.h +++ b/sysmodules/pm/source/launch.h @@ -4,6 +4,11 @@ #include <3ds/services/fs.h> #include "process_data.h" +/// Custom launch flags for PM launch commands. +enum { + PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING = BIT(24), +}; + Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags); Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags); Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags); diff --git a/sysmodules/pm/source/luma.c b/sysmodules/pm/source/luma.c index 45d1735..eb14d26 100644 --- a/sysmodules/pm/source/luma.c +++ b/sysmodules/pm/source/luma.c @@ -3,11 +3,24 @@ #include "luma.h" #include "util.h" +bool hasKExt(void) +{ + s64 val; + return svcGetSystemInfo(&val, 0x20000, 0) == 1; +} + u32 getKExtSize(void) { s64 val; - Result res = svcGetSystemInfo(&val, 0x10000, 0x300); - return R_FAILED(res) ? 0 : (u32)val; + svcGetSystemInfo(&val, 0x10000, 0x300); + return (u32)val; +} + +u32 getStolenSystemMemRegionSize(void) +{ + s64 val; + svcGetSystemInfo(&val, 0x10000, 0x301); + return (u32)val; } bool isTitleLaunchPrevented(u64 titleId) @@ -15,5 +28,5 @@ bool isTitleLaunchPrevented(u64 titleId) s64 numKips = 0; svcGetSystemInfo(&numKips, 26, 0); - return numKips >= 6 && (titleId & ~N3DS_TID_BIT) == 0x0004003000008A02ULL; // ErrDisp -} \ No newline at end of file + return numKips >= 6 && (titleId & ~(N3DS_TID_MASK | 1)) == 0x0004003000008A02ULL; // ErrDisp +} diff --git a/sysmodules/pm/source/luma.h b/sysmodules/pm/source/luma.h index db486d6..80b80ef 100644 --- a/sysmodules/pm/source/luma.h +++ b/sysmodules/pm/source/luma.h @@ -2,5 +2,7 @@ #include <3ds/types.h> +bool hasKExt(void); u32 getKExtSize(void); -bool isTitleLaunchPrevented(u64 titleId); \ No newline at end of file +u32 getStolenSystemMemRegionSize(void); +bool isTitleLaunchPrevented(u64 titleId); diff --git a/sysmodules/pm/source/main.c b/sysmodules/pm/source/main.c index 5ba8515..187d7ca 100644 --- a/sysmodules/pm/source/main.c +++ b/sysmodules/pm/source/main.c @@ -14,10 +14,27 @@ #include "service_manager.h" static MyThread processMonitorThread, taskRunnerThread; +static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0}; +static u8 ALIGN(8) exheaderInfoBuffer[6 * sizeof(ExHeader_Info)] = {0}; +static u8 ALIGN(8) threadStacks[2][THREAD_STACK_SIZE] = {0}; -// this is called before main -void __appInit() +// this is called after main exits +void __wrap_exit(int rc) { + (void)rc; + // Not supposed to terminate... kernel will clean up the handles if it does happen anyway + svcExitProcess(); +} + +Result __sync_init(void); +//void __libc_init_array(void); + +// Called before main +void initSystem() +{ + __sync_init(); + //__libc_init_array(); + // Wait for sm for(Result res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) { res = srvPmInit(); @@ -28,14 +45,27 @@ void __appInit() loaderInit(); fsRegInit(); - static u8 ALIGN(8) processDataBuffer[0x40 * sizeof(ProcessData)] = {0}; - static u8 ALIGN(8) exheaderInfoBuffer[6 * sizeof(ExHeader_Info)] = {0}; - static u8 ALIGN(8) threadStacks[2][THREAD_STACK_SIZE] = {0}; - // Init objects Manager_Init(processDataBuffer, 0x40); ExHeaderInfoHeap_Init(exheaderInfoBuffer, 6); TaskRunner_Init(); +} + +static const ServiceManagerServiceEntry services[] = { + { "pm:app", 4, pmAppHandleCommands, false }, + { "pm:dbg", 2, pmDbgHandleCommands, false }, + { NULL }, +}; + +static const ServiceManagerNotificationEntry notifications[] = { + { 0x000, NULL }, +}; + +void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error + +int main(void) +{ + Result res = 0; // Init the reslimits, register the KIPs and map the firmlaunch parameters initializeReslimits(); @@ -48,51 +78,7 @@ void __appInit() // Launch NS, etc. autolaunchSysmodules(); -} -// this is called after main exits -void __appExit() -{ - // We don't clean up g_manager's handles because it could hang the process monitor thread, etc. - fsRegExit(); - loaderExit(); - srvPmExit(); -} - - -Result __sync_init(void); -Result __sync_fini(void); -void __libc_init_array(void); -void __libc_fini_array(void); - -void __ctru_exit() -{ - __libc_fini_array(); - __appExit(); - __sync_fini(); - svcExitProcess(); -} - -void initSystem() -{ - __sync_init(); - __appInit(); - __libc_init_array(); -} - -static const ServiceManagerServiceEntry services[] = { - { "pm:app", 3, pmAppHandleCommands, false }, - { "pm:dbg", 2, pmDbgHandleCommands, false }, - { NULL }, -}; - -static const ServiceManagerNotificationEntry notifications[] = { - { 0x000, NULL }, -}; - -int main(void) -{ - Result res = 0; if (R_FAILED(res = ServiceManager_Run(services, notifications, NULL))) { panic(res); } diff --git a/sysmodules/pm/source/manager.c b/sysmodules/pm/source/manager.c index 8cd07cb..b527db6 100644 --- a/sysmodules/pm/source/manager.c +++ b/sysmodules/pm/source/manager.c @@ -7,6 +7,21 @@ Manager g_manager; +static void giveAllFsArchiveAccessToKip(u32 pid, u64 tid) +{ + static const ExHeader_Arm11StorageInfo storageInfo = { + .fs_access_info = 0xFFFFFFFF, + }; + static const u64 programHandle = 0xFFFF000000000000LL; + + FS_ProgramInfo info = { + .programId = tid, + .mediaType = MEDIATYPE_NAND, + }; + + assertSuccess(FSREG_Register(pid, programHandle, &info, &storageInfo)); +} + void Manager_Init(void *procBuf, size_t numProc) { memset(&g_manager, 0, sizeof(Manager)); @@ -34,14 +49,23 @@ void Manager_RegisterKips(void) process->handle = processHandle; process->pid = i; process->refcount = 1; - process->titleId = 0x0004000100001000ULL; // note: same TID for all builtins + process->titleId = 0x0004000100001000ULL; // note: same internal TID for all builtins process->flags = PROCESSFLAG_KIP; process->terminationStatus = TERMSTATUS_RUNNING; - assertSuccess(svcSetProcessResourceLimits(processHandle, g_manager.reslimits[RESLIMIT_CATEGORY_OTHER])); + if (i < 5) { + // Exempt rosalina from being resource-limited at all + assertSuccess(svcSetProcessResourceLimits(processHandle, g_manager.reslimits[RESLIMIT_CATEGORY_OTHER])); + } } - ProcessList_Unlock(&g_manager.processList); + + // Give full archive access to us (PM) and Rosalina (real PIDs don't matter, they just have to be unique (?)) + // Loader doesn't depend on PM and has its own fs:REG handle so it must do it itself. + giveAllFsArchiveAccessToKip(2, 0x0004013000001202LL); // PM + if (numKips > 5) { + giveAllFsArchiveAccessToKip(5, 0x0004013000006902LL); // Rosalina + } } Result UnregisterProcess(u64 titleId) @@ -66,3 +90,27 @@ Result UnregisterProcess(u64 titleId) ProcessList_Unlock(&g_manager.processList); return 0; } + +Result PrepareToChainloadHomebrew(u64 titleId) +{ + // Note: I'm allowing this command to be called for non-applications, maybe that'll be useful + // in the future... + + ProcessData *foundProcess = NULL; + Result res; + ProcessList_Lock(&g_manager.processList); + foundProcess = ProcessList_FindProcessByTitleId(&g_manager.processList, titleId & ~N3DS_TID_MASK); + if (foundProcess != NULL) { + // Clear the "notify on termination, don't cleanup" flag, so that for ex. APT isn't notified & no need for UnregisterProcess, + // and the "dependencies loaded" flag, so that the dependencies aren't killed (for ex. when + // booting hbmenu instead of Home Menu, in which case the same title is going to be launched...) + + foundProcess->flags &= ~(PROCESSFLAG_DEPENDENCIES_LOADED | PROCESSFLAG_NOTIFY_TERMINATION); + res = 0; + } else { + res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100); + } + + ProcessList_Unlock(&g_manager.processList); + return res; +} diff --git a/sysmodules/pm/source/manager.h b/sysmodules/pm/source/manager.h index 82346dd..ca71db4 100644 --- a/sysmodules/pm/source/manager.h +++ b/sysmodules/pm/source/manager.h @@ -21,3 +21,4 @@ extern Manager g_manager; void Manager_Init(void *procBuf, size_t numProc); void Manager_RegisterKips(void); Result UnregisterProcess(u64 titleId); +Result PrepareToChainloadHomebrew(u64 titleId); diff --git a/sysmodules/pm/source/pmdbg.c b/sysmodules/pm/source/pmdbg.c index fc49a23..6e88ded 100644 --- a/sysmodules/pm/source/pmdbg.c +++ b/sysmodules/pm/source/pmdbg.c @@ -3,6 +3,7 @@ #include "launch.h" #include "info.h" #include "util.h" +#include "manager.h" void pmDbgHandleCommands(void *ctx) { @@ -11,10 +12,10 @@ void pmDbgHandleCommands(void *ctx) u32 cmdhdr = cmdbuf[0]; FS_ProgramInfo programInfo; - Handle debug; - u64 titleId; + Handle debug; u32 pid; + u32 launchFlags; switch (cmdhdr >> 16) { case 1: @@ -40,12 +41,11 @@ void pmDbgHandleCommands(void *ctx) // Custom case 0x100: - titleId = 0; - pid = 0xFFFFFFFF; - cmdbuf[1] = GetCurrentAppTitleIdAndPid(&titleId, &pid); - cmdbuf[0] = IPC_MakeHeader(0x100, 4, 0); - memcpy(cmdbuf + 2, &titleId, 8); - cmdbuf[4] = pid; + cmdbuf[1] = GetCurrentAppInfo(&programInfo, &pid, &launchFlags); + cmdbuf[0] = IPC_MakeHeader(0x100, 7, 0); + memcpy(cmdbuf + 2, &programInfo, sizeof(FS_ProgramInfo)); + cmdbuf[6] = pid; + cmdbuf[7] = launchFlags; break; case 0x101: cmdbuf[1] = DebugNextApplicationByForce(cmdbuf[1] != 0); @@ -59,7 +59,11 @@ void pmDbgHandleCommands(void *ctx) cmdbuf[2] = IPC_Desc_MoveHandles(1); cmdbuf[3] = debug; break; - + case 0x103: + memcpy(&titleId, cmdbuf + 1, 8); + cmdbuf[1] = PrepareToChainloadHomebrew(titleId); + cmdbuf[0] = IPC_MakeHeader(0x103, 1, 0); + break; default: cmdbuf[0] = IPC_MakeHeader(0, 1, 0); cmdbuf[1] = 0xD900182F; diff --git a/sysmodules/pm/source/process_data.h b/sysmodules/pm/source/process_data.h index e13dd4f..933c71b 100644 --- a/sysmodules/pm/source/process_data.h +++ b/sysmodules/pm/source/process_data.h @@ -29,10 +29,12 @@ typedef struct ProcessData { u32 pid; u64 titleId; u64 programHandle; + u32 launchFlags; u8 flags; u8 terminatedNotificationVariation; TerminationStatus terminationStatus; u8 refcount; + FS_MediaType mediaType; } ProcessData; typedef struct ProcessList { diff --git a/sysmodules/pm/source/reslimit.c b/sysmodules/pm/source/reslimit.c index b3bc0d9..824c1aa 100644 --- a/sysmodules/pm/source/reslimit.c +++ b/sysmodules/pm/source/reslimit.c @@ -4,6 +4,9 @@ #include "manager.h" #include "luma.h" +#define CPUTIME_MULTI_MASK BIT(7) +#define CPUTIME_SINGLE_MASK 0 + typedef s64 ReslimitValues[10]; static const ResourceLimitType g_reslimitInitOrder[10] = { @@ -189,20 +192,23 @@ static ReslimitValues g_n3dsReslimitValues[4] = { Both modes pause threads they don't want to run in thread selection, and unpause them when needed. If the threads that are intended to be paused is running an SVC, the pause will happen *after* SVC return. - Mode0 (unsure) + Mode0 "multi" Starting by "sysmodule" threads, alternatively allow (if preemptible) only sysmodule threads, and then only application threads to run. - The latter has an exception; if "sysmodule" threads have run for less than 2usec, they + The latter has an exception; if "sysmodule" threads have run for less than 8usec (value is a kernel bug), they are unpaused an allowed to run instead. - This happens at a rate of 1ms * (cpuTime/100). + This happens at a rate of 2ms * (cpuTime/100). - Mode1 + + Mode1 "single" + + This mode is half-broken due to a kernel bug (when "current thread" is the priority 0 kernel thread). When this mode is enabled, only one application thread is allowed to be created on core1. - This divides the core1 time into slices of 12.5ms. + This divides the core1 time into slices of 25ms. The "application" thread is given cpuTime% of the slice. The "sysmodules" threads are given a total of (90 - cpuTime)% of the slice. @@ -243,7 +249,10 @@ static ReslimitValues *fixupReslimitValues(void) { // In order: APPLICATION, SYS_APPLET, LIB_APPLET, OTHER // Fixup "commit" reslimit - u32 sysmemalloc = SYSMEMALLOC + getKExtSize(); + + // Note: we lie in the reslimit and make as if neither KExt nor Roslina existed, to avoid breakage + + u32 sysmemalloc = SYSMEMALLOC + (hasKExt() ? getStolenSystemMemRegionSize() : 0); ReslimitValues *values = !IS_N3DS ? g_o3dsReslimitValues : g_n3dsReslimitValues; static const u32 minAppletMemAmount = 0x1200000; @@ -315,22 +324,23 @@ void setAppCpuTimeLimitAndSchedModeFromDescriptor(u64 titleId, u16 descriptor) - app has a non-0 cputime descriptor in exhdr: maximum core1 cputime reslimit and scheduling mode are set according to it. Current reslimit is set to 0. SetAppResourceLimit *is* needed to use core1. - - app has a 0 cputime descriptor: maximum is set to 80. - Current reslimit is set to 0, and SetAppResourceLimit *is* needed + - app has a 0 cputime descriptor: maximum is set to 80, scheduling mode to "single" (broken). + Current reslimit is set to 0, and SetAppResourceLimit *is* also needed to use core1, **EXCEPT** for an hardcoded set of titles. */ u8 cpuTime = (u8)descriptor; assertSuccess(setAppCpuTimeLimit(0)); // remove preemption first. g_manager.cpuTimeBase = 0; + u32 currentValueToSet = g_manager.cpuTimeBase; // 0 - if (cpuTime != 0) { - // Set core1 scheduling mode - g_manager.maxAppCpuTime = cpuTime & 0x7F; - assertSuccess(svcKernelSetState(6, 3, (cpuTime & 0x80) ? 0LL : 1LL)); - } else { + if (cpuTime == 0) { + // 2.0 apps have this exheader field correctly filled, very often to 0x9E (1.0 titles don't). u32 titleUid = ((u32)titleId >> 8) & 0xFFFFF; - g_manager.maxAppCpuTime = 80; + + // Default setting is 80% max "single", with a current value of 0 + cpuTime = CPUTIME_SINGLE_MASK | 80; + static const u32 numOverrides = sizeof(g_startCpuTimeOverrides) / sizeof(g_startCpuTimeOverrides[0]); if (titleUid >= g_startCpuTimeOverrides[0].titleUid && titleUid <= g_startCpuTimeOverrides[numOverrides - 1].titleUid) { @@ -338,15 +348,26 @@ void setAppCpuTimeLimitAndSchedModeFromDescriptor(u64 titleId, u16 descriptor) for (u32 i = 0; i < numOverrides && titleUid < g_startCpuTimeOverrides[i].titleUid; i++); if (i < numOverrides) { if (g_startCpuTimeOverrides[i].value > 100 && g_startCpuTimeOverrides[i].value < 200) { - assertSuccess(svcKernelSetState(6, 3, 0LL)); - assertSuccess(setAppCpuTimeLimit(g_startCpuTimeOverrides[i].value - 100)); + cpuTime = CPUTIME_MULTI_MASK | 80; // "multi", max 80% + currentValueToSet = g_startCpuTimeOverrides[i].value - 100; } else { - assertSuccess(svcKernelSetState(6, 3, 1LL)); - assertSuccess(setAppCpuTimeLimit(g_startCpuTimeOverrides[i].value)); + cpuTime = CPUTIME_SINGLE_MASK | 80; // "single", max 80% + currentValueToSet = g_startCpuTimeOverrides[i].value; } } } } + + // Set core1 scheduling mode + assertSuccess(svcKernelSetState(6, 3, (cpuTime & CPUTIME_MULTI_MASK) ? 0LL : 1LL)); + + // Set max value (limit) + g_manager.maxAppCpuTime = cpuTime & 0x7F; + + // Set current value (for 1.0 apps) + if (currentValueToSet != 0) { + assertSuccess(setAppCpuTimeLimit(currentValueToSet)); + } } Result SetAppResourceLimit(u32 mbz, ResourceLimitType category, u32 value, u64 mbz2) diff --git a/sysmodules/pm/source/service_manager.c b/sysmodules/pm/source/service_manager.c index 33cc78e..1244133 100644 --- a/sysmodules/pm/source/service_manager.c +++ b/sysmodules/pm/source/service_manager.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/pm/source/task_runner.c b/sysmodules/pm/source/task_runner.c index 79cbf02..4c76d52 100644 --- a/sysmodules/pm/source/task_runner.c +++ b/sysmodules/pm/source/task_runner.c @@ -4,6 +4,11 @@ TaskRunner g_taskRunner; +static void taskRunnerNoOpFunction(void *args) +{ + (void)args; +} + void TaskRunner_Init(void) { memset(&g_taskRunner, 0, sizeof(TaskRunner)); @@ -20,12 +25,23 @@ void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsi LightEvent_Signal(&g_taskRunner.parametersSetEvent); } +void TaskRunner_Terminate(void) +{ + g_taskRunner.shouldTerminate = true; + TaskRunner_RunTask(taskRunnerNoOpFunction, NULL, 0); +} + void TaskRunner_HandleTasks(void *p) { (void)p; - for (;;) { + while (!g_taskRunner.shouldTerminate) { LightEvent_Signal(&g_taskRunner.readyEvent); LightEvent_Wait(&g_taskRunner.parametersSetEvent); g_taskRunner.task(g_taskRunner.argStorage); } } + +void TaskRunner_WaitReady(void) +{ + LightEvent_Wait(&g_taskRunner.readyEvent); +} diff --git a/sysmodules/pm/source/task_runner.h b/sysmodules/pm/source/task_runner.h index de277cb..ac445cf 100644 --- a/sysmodules/pm/source/task_runner.h +++ b/sysmodules/pm/source/task_runner.h @@ -8,11 +8,15 @@ typedef struct TaskRunner { LightEvent parametersSetEvent; void (*task)(void *argdata); u8 argStorage[0x40]; + bool shouldTerminate; } TaskRunner; extern TaskRunner g_taskRunner; void TaskRunner_Init(void); void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize); +void TaskRunner_Terminate(void); + /// Thread function void TaskRunner_HandleTasks(void *p); +void TaskRunner_WaitReady(void); diff --git a/sysmodules/pm/source/termination.c b/sysmodules/pm/source/termination.c index 6b9d027..156109c 100644 --- a/sysmodules/pm/source/termination.c +++ b/sysmodules/pm/source/termination.c @@ -6,6 +6,15 @@ #include "exheader_info_heap.h" #include "task_runner.h" +void forceMountSdCard(void) +{ + FS_Archive sdmcArchive; + + assertSuccess(fsInit()); + assertSuccess(FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""))); + // No need to clean up things as we will firmlaunch straight away +} + static Result terminateUnusedDependencies(const u64 *dependencies, u32 numDeps) { ProcessData *process; @@ -65,6 +74,16 @@ static Result terminateProcessImpl(ProcessData *process, ExHeader_Info *exheader } } +static void terminateProcessByIdChecked(u32 pid) +{ + ProcessData *process = ProcessList_FindProcessById(&g_manager.processList, pid); + if (process != NULL) { + ProcessData_SendTerminationNotification(process); + } else { + panic(0LL); + } +} + static Result commitPendingTerminations(s64 timeout) { // Wait for all of the processes that have received notification 0x100 to terminate @@ -247,6 +266,8 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout) u64 dependencies[48]; u32 numDeps = 0; + s64 numKips = 0; + svcGetSystemInfo(&numKips, 26, 0); ExHeader_Info *exheaderInfo = ExHeaderInfoHeap_New(); @@ -269,6 +290,12 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout) } ProcessList_Lock(&g_manager.processList); + + // Send custom notification to at least Rosalina to make it relinquish some non-KIP services handles, stop the debugger, etc. + if (numKips >= 6) { + notifySubscribers(0x2000); + } + // Send notification 0x100 to the currently running application if (g_manager.runningApplicationData != NULL) { g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED; @@ -302,20 +329,29 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout) commitPendingTerminations(timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL); g_manager.waitingForTermination = false; - // Now, send termination notification to PXI (PID 4) + if (callerPid == (u32)-1) { + // On firmlaunch, try to force Process9 to mount the SD card to allow the Process9 firmlaunch patch to load boot.firm if needed + // Need to do that before we tell PXI to terminate + s64 out; + if(R_SUCCEEDED(svcGetSystemInfo(&out, 0x10000, 0x203)) && out != 0) { + // If boot.firm is on the SD card, then... + forceMountSdCard(); + } + } + + // Now, send termination notification to PXI (PID 4). Also do the same for Rosalina. assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent)); g_manager.waitingForTermination = true; - ProcessList_Lock(&g_manager.processList); - process = ProcessList_FindProcessById(&g_manager.processList, 4); - if (process != NULL) { - ProcessData_SendTerminationNotification(process); - } else { - panic(0LL); + + if (numKips >= 6) { + terminateProcessByIdChecked(5); // Rosalina } + terminateProcessByIdChecked(4); // PXI + ProcessList_Unlock(&g_manager.processList); - // Allow 1.5 extra seconds for PXI (approx 402167783 ticks) + // Allow 1.5 extra seconds for PXI and Rosalina (approx 402167783 ticks) timeoutTicks = dstTimePoint - svcGetSystemTick(); commitPendingTerminations(1500 * 1000 * 1000LL + (timeoutTicks >= 0 ? ticksToNs(timeoutTicks) : 0LL)); g_manager.waitingForTermination = false; diff --git a/sysmodules/pxi/LICENSE b/sysmodules/pxi/LICENSE index d4607d1..c7f6447 100644 --- a/sysmodules/pxi/LICENSE +++ b/sysmodules/pxi/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 TuxSH +Copyright (c) 2015-2020 TuxSH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/sysmodules/pxi/Makefile b/sysmodules/pxi/Makefile index b14d489..b729039 100644 --- a/sysmodules/pxi/Makefile +++ b/sysmodules/pxi/Makefile @@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit LIBS := -lctru diff --git a/sysmodules/pxi/README.md b/sysmodules/pxi/README.md index 7a22126..2687003 100644 --- a/sysmodules/pxi/README.md +++ b/sysmodules/pxi/README.md @@ -1,5 +1,5 @@ # 3ds_pxi -Open source replacement of the ARM11 PXI system module. +Open source replacement of the Arm11 PXI system module. This is licensed under the MIT license. # Usage diff --git a/sysmodules/pxi/source/MyThread.c b/sysmodules/pxi/source/MyThread.c index 78f034a..7a05e6e 100644 --- a/sysmodules/pxi/source/MyThread.c +++ b/sysmodules/pxi/source/MyThread.c @@ -2,7 +2,7 @@ MyThread.c: Small threading library, based off ctrulib. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/MyThread.h b/sysmodules/pxi/source/MyThread.h index 4ea68bf..72f5189 100644 --- a/sysmodules/pxi/source/MyThread.h +++ b/sysmodules/pxi/source/MyThread.h @@ -2,7 +2,7 @@ MyThread.h: Small threading library, based off ctrulib. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/PXI.c b/sysmodules/pxi/source/PXI.c index 62c850f..af6b9dd 100644 --- a/sysmodules/pxi/source/PXI.c +++ b/sysmodules/pxi/source/PXI.c @@ -2,7 +2,7 @@ PXI.c: PXI I/O functions. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/PXI.h b/sysmodules/pxi/source/PXI.h index 90ff467..df0633f 100644 --- a/sysmodules/pxi/source/PXI.h +++ b/sysmodules/pxi/source/PXI.h @@ -2,7 +2,7 @@ PXI.h: PXI I/O functions. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/common.h b/sysmodules/pxi/source/common.h index 130a744..d536f72 100644 --- a/sysmodules/pxi/source/common.h +++ b/sysmodules/pxi/source/common.h @@ -2,7 +2,7 @@ common.h: Common types and global variables. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/main.c b/sysmodules/pxi/source/main.c index bac4160..7a9141b 100644 --- a/sysmodules/pxi/source/main.c +++ b/sysmodules/pxi/source/main.c @@ -2,12 +2,11 @@ main.c (De)initialization stuff. It's also here where sessions are being accepted. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ #include - #include "PXI.h" #include "common.h" #include "MyThread.h" @@ -99,10 +98,40 @@ static inline void exitPXI(void) static u8 ALIGN(8) receiverStack[THREAD_STACK_SIZE]; static u8 ALIGN(8) senderStack[THREAD_STACK_SIZE]; static u8 ALIGN(8) PXISRV11HandlerStack[THREAD_STACK_SIZE]; +static MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0}; + +Result __sync_init(void); +Result __sync_fini(void); +void __libc_fini_array(void); +void __libc_init_array(void); + +void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error + +// this is called after main exits +void __wrap_exit(int rc) +{ + (void)rc; + + srvExit(); + exitPXI(); + + svcCloseHandle(terminationRequestedEvent); + svcCloseHandle(sessionManager.sendAllBuffersToArm9Event); + svcCloseHandle(sessionManager.replySemaphore); + svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent); + svcCloseHandle(sessionManager.PXISRV11ReplySentEvent); + + //__libc_fini_array(); + __sync_fini(); + svcExitProcess(); +} // this is called before main -void __appInit() + +void initSystem(void) { + __sync_init(); + assertSuccess(svcCreateEvent(&terminationRequestedEvent, RESET_STICKY)); assertSuccess(svcCreateEvent(&sessionManager.sendAllBuffersToArm9Event, RESET_ONESHOT)); @@ -117,52 +146,13 @@ void __appInit() if(R_FAILED(res) && res != (Result)0xD88007FA) svcBreak(USERBREAK_PANIC); } -} -// this is called after main exits -void __appExit() -{ - srvExit(); - exitPXI(); - - svcCloseHandle(terminationRequestedEvent); - svcCloseHandle(sessionManager.sendAllBuffersToArm9Event); - svcCloseHandle(sessionManager.replySemaphore); - svcCloseHandle(sessionManager.PXISRV11CommandReceivedEvent); - svcCloseHandle(sessionManager.PXISRV11ReplySentEvent); -} - -// stubs for non-needed pre-main functions -void __system_initSyscalls(){} - - -Result __sync_init(void); -Result __sync_fini(void); - -void __ctru_exit() -{ - void __libc_fini_array(void); - - __libc_fini_array(); - __appExit(); - __sync_fini(); - svcExitProcess(); -} - -void initSystem() -{ - void __libc_init_array(void); - - __sync_init(); - __system_initSyscalls(); - __appInit(); - __libc_init_array(); + //__libc_init_array(); } int main(void) { Handle handles[10] = {0}; //notification handle + service handles - MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0}; for(u32 i = 0; i < 9; i++) assertSuccess(srvRegisterService(handles + 1 + i, serviceNames[i], 1)); diff --git a/sysmodules/pxi/source/receiver.c b/sysmodules/pxi/source/receiver.c index a4dc972..613a768 100644 --- a/sysmodules/pxi/source/receiver.c +++ b/sysmodules/pxi/source/receiver.c @@ -2,7 +2,7 @@ receiver.c: Fetches replies coming from Process9, writing them in the appropriate buffer. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/receiver.h b/sysmodules/pxi/source/receiver.h index 820f636..f237667 100644 --- a/sysmodules/pxi/source/receiver.h +++ b/sysmodules/pxi/source/receiver.h @@ -2,7 +2,7 @@ receiver.h: Fetches replies coming from Process9, writing them in the appropriate buffer. -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/sender.c b/sysmodules/pxi/source/sender.c index 9441044..8ece6cf 100644 --- a/sysmodules/pxi/source/sender.c +++ b/sysmodules/pxi/source/sender.c @@ -3,7 +3,7 @@ sender.c Handles commands from arm11 processes, then sends them to Process9, and replies to arm11 processes the replies received from Process9 (=> receiver.c). (except for PXISRV11) -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/pxi/source/sender.h b/sysmodules/pxi/source/sender.h index 3f70cce..f7b76c6 100644 --- a/sysmodules/pxi/source/sender.h +++ b/sysmodules/pxi/source/sender.h @@ -2,7 +2,7 @@ sender.h Handles commands from arm11 processes, then sends them to Process9, and replies to arm11 processes the replies received from Process9 (=> receiver.c) (except for PXISRV11). -(c) TuxSH, 2016-2017 +(c) TuxSH, 2016-2020 This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/rosalina/Makefile b/sysmodules/rosalina/Makefile index 33c8d48..254219a 100644 --- a/sysmodules/rosalina/Makefile +++ b/sysmodules/rosalina/Makefile @@ -38,9 +38,9 @@ CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),--section-start,.text=0x14000000 +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000 -LIBS := -lctru -lm +LIBS := -lctru #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing @@ -131,6 +131,8 @@ $(OUTPUT).elf : $(OFILES) @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ @$(NM) -CSn $@ > $(notdir $*.lst) +draw.o: CFLAGS += -O3 + $(OFILES_SRC) : $(HFILES_BIN) #--------------------------------------------------------------------------------- diff --git a/sysmodules/rosalina/include/3dsx.h b/sysmodules/rosalina/include/3dsx.h index 24ec6e2..6eb8e30 100644 --- a/sysmodules/rosalina/include/3dsx.h +++ b/sysmodules/rosalina/include/3dsx.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/MyThread.h b/sysmodules/rosalina/include/MyThread.h index 0cfd502..2af7f6b 100644 --- a/sysmodules/rosalina/include/MyThread.h +++ b/sysmodules/rosalina/include/MyThread.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/draw.h b/sysmodules/rosalina/include/draw.h index 00953f9..78e908b 100644 --- a/sysmodules/rosalina/include/draw.h +++ b/sysmodules/rosalina/include/draw.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -54,9 +54,14 @@ #define GPU_TRANSFER_CNT REG32(0x10400C18) #define GPU_CMDLIST_CNT REG32(0x104018F0) +#define LCD_TOP_BRIGHTNESS REG32(0x10202240) +#define LCD_BOT_BRIGHTNESS REG32(0x10202A40) + #define FB_BOTTOM_VRAM_ADDR ((void *)0x1F48F000) // cached #define FB_BOTTOM_VRAM_PA 0x1848F000 #define FB_BOTTOM_SIZE (320 * 240 * 2) +#define FB_SCREENSHOT_SIZE (52 + 400 * 240 * 3) + #define SCREEN_BOT_WIDTH 320 #define SCREEN_BOT_HEIGHT 240 @@ -73,19 +78,27 @@ #define DRAW_MAX_FORMATTED_STRING_SIZE 512 +void Draw_Init(void); + void Draw_Lock(void); void Draw_Unlock(void); void Draw_DrawCharacter(u32 posX, u32 posY, u32 color, char character); u32 Draw_DrawString(u32 posX, u32 posY, u32 color, const char *string); + +__attribute__((format(printf,4,5))) u32 Draw_DrawFormattedString(u32 posX, u32 posY, u32 color, const char *fmt, ...); void Draw_FillFramebuffer(u32 value); void Draw_ClearFramebuffer(void); -void Draw_SetupFramebuffer(void); +u32 Draw_AllocateFramebufferCache(void); +void Draw_FreeFramebufferCache(void); +void *Draw_GetFramebufferCache(void); +u32 Draw_GetFramebufferCacheSize(void); +u32 Draw_SetupFramebuffer(void); void Draw_RestoreFramebuffer(void); void Draw_FlushFramebuffer(void); u32 Draw_GetCurrentFramebufferAddress(bool top, bool left); void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth); -void Draw_ConvertFrameBufferLine(u8 *line, bool top, bool left, u32 y); +void Draw_ConvertFrameBufferLines(u8 *buf, u32 startingLine, u32 numLines, bool top, bool left); diff --git a/sysmodules/rosalina/include/errdisp.h b/sysmodules/rosalina/include/errdisp.h index 33e69bc..f37819c 100644 --- a/sysmodules/rosalina/include/errdisp.h +++ b/sysmodules/rosalina/include/errdisp.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -27,5 +27,8 @@ #pragma once #include <3ds/types.h> +#include "MyThread.h" -void ERRF_HandleCommands(void *ctx); +MyThread *errDispCreateThread(void); +void ERRF_HandleCommands(void); +void errDispThreadMain(void); diff --git a/sysmodules/rosalina/include/fmt.h b/sysmodules/rosalina/include/fmt.h index d805af9..1311286 100644 --- a/sysmodules/rosalina/include/fmt.h +++ b/sysmodules/rosalina/include/fmt.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/gdb.h b/sysmodules/rosalina/include/gdb.h index aa1499f..4a27047 100644 --- a/sysmodules/rosalina/include/gdb.h +++ b/sysmodules/rosalina/include/gdb.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -18,14 +18,14 @@ #define MAX_DEBUG 3 #define MAX_DEBUG_THREAD 127 -#define MAX_BREAKPOINT 256 +#define MAX_BREAKPOINT 64 #define MAX_TIO_OPEN_FILE 32 // 512+24 is the ideal size as IDA will try to read exactly 0x100 bytes at a time. Add 4 to this, for $#, see below. // IDA seems to want additional bytes as well. // 1024 is fine enough to put all regs in the 'T' stop reply packets -#define GDB_BUF_LEN 2048 +#define GDB_BUF_LEN 1024 #define GDB_HANDLER(name) GDB_Handle##name #define GDB_QUERY_HANDLER(name) GDB_HANDLER(Query##name) diff --git a/sysmodules/rosalina/include/gdb/breakpoints.h b/sysmodules/rosalina/include/gdb/breakpoints.h index c625511..22ad56c 100644 --- a/sysmodules/rosalina/include/gdb/breakpoints.h +++ b/sysmodules/rosalina/include/gdb/breakpoints.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/debug.h b/sysmodules/rosalina/include/gdb/debug.h index 95f65c4..0bf01a9 100644 --- a/sysmodules/rosalina/include/gdb/debug.h +++ b/sysmodules/rosalina/include/gdb/debug.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/hio.h b/sysmodules/rosalina/include/gdb/hio.h index 123ba56..0c6015f 100644 --- a/sysmodules/rosalina/include/gdb/hio.h +++ b/sysmodules/rosalina/include/gdb/hio.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -13,4 +13,4 @@ bool GDB_FetchPackedHioRequest(GDBContext *ctx, u32 addr); bool GDB_IsHioInProgress(GDBContext *ctx); int GDB_SendCurrentHioRequest(GDBContext *ctx); -GDB_DECLARE_HANDLER(HioReply); \ No newline at end of file +GDB_DECLARE_HANDLER(HioReply); diff --git a/sysmodules/rosalina/include/gdb/mem.h b/sysmodules/rosalina/include/gdb/mem.h index 90ba332..569e96d 100644 --- a/sysmodules/rosalina/include/gdb/mem.h +++ b/sysmodules/rosalina/include/gdb/mem.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/monitor.h b/sysmodules/rosalina/include/gdb/monitor.h index a9fa790..d584351 100644 --- a/sysmodules/rosalina/include/gdb/monitor.h +++ b/sysmodules/rosalina/include/gdb/monitor.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/net.h b/sysmodules/rosalina/include/gdb/net.h index c4676a5..b1b33ad 100644 --- a/sysmodules/rosalina/include/gdb/net.h +++ b/sysmodules/rosalina/include/gdb/net.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/query.h b/sysmodules/rosalina/include/gdb/query.h index 93ee5e8..a33c92d 100644 --- a/sysmodules/rosalina/include/gdb/query.h +++ b/sysmodules/rosalina/include/gdb/query.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/regs.h b/sysmodules/rosalina/include/gdb/regs.h index dcbff60..03809ab 100644 --- a/sysmodules/rosalina/include/gdb/regs.h +++ b/sysmodules/rosalina/include/gdb/regs.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/remote_command.h b/sysmodules/rosalina/include/gdb/remote_command.h index c696695..0bf4168 100644 --- a/sysmodules/rosalina/include/gdb/remote_command.h +++ b/sysmodules/rosalina/include/gdb/remote_command.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/server.h b/sysmodules/rosalina/include/gdb/server.h index 5e2354c..bb63976 100644 --- a/sysmodules/rosalina/include/gdb/server.h +++ b/sysmodules/rosalina/include/gdb/server.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/stop_point.h b/sysmodules/rosalina/include/gdb/stop_point.h index 7b38072..ba74abf 100644 --- a/sysmodules/rosalina/include/gdb/stop_point.h +++ b/sysmodules/rosalina/include/gdb/stop_point.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/thread.h b/sysmodules/rosalina/include/gdb/thread.h index 5e1a060..4986933 100644 --- a/sysmodules/rosalina/include/gdb/thread.h +++ b/sysmodules/rosalina/include/gdb/thread.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/tio.h b/sysmodules/rosalina/include/gdb/tio.h index d1cb8c7..7aa3194 100644 --- a/sysmodules/rosalina/include/gdb/tio.h +++ b/sysmodules/rosalina/include/gdb/tio.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/verbose.h b/sysmodules/rosalina/include/gdb/verbose.h index 2ae67ca..bc33622 100644 --- a/sysmodules/rosalina/include/gdb/verbose.h +++ b/sysmodules/rosalina/include/gdb/verbose.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/watchpoints.h b/sysmodules/rosalina/include/gdb/watchpoints.h index 0e304db..58ba140 100644 --- a/sysmodules/rosalina/include/gdb/watchpoints.h +++ b/sysmodules/rosalina/include/gdb/watchpoints.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/gdb/xfer.h b/sysmodules/rosalina/include/gdb/xfer.h index 68556a2..087f3ef 100644 --- a/sysmodules/rosalina/include/gdb/xfer.h +++ b/sysmodules/rosalina/include/gdb/xfer.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/include/hbloader.h b/sysmodules/rosalina/include/hbloader.h index 18af0a6..a6fb94d 100644 --- a/sysmodules/rosalina/include/hbloader.h +++ b/sysmodules/rosalina/include/hbloader.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,4 +33,5 @@ #define HBLDR_DEFAULT_3DSX_TID 0x000400000D921E00ULL #define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100) +void HBLDR_RestartHbApplication(void *p); void HBLDR_HandleCommands(void *ctx); diff --git a/sysmodules/rosalina/include/ifile.h b/sysmodules/rosalina/include/ifile.h index 718257d..4683a12 100644 --- a/sysmodules/rosalina/include/ifile.h +++ b/sysmodules/rosalina/include/ifile.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/input_redirection.h b/sysmodules/rosalina/include/input_redirection.h index 3ceef5f..253c2bf 100644 --- a/sysmodules/rosalina/include/input_redirection.h +++ b/sysmodules/rosalina/include/input_redirection.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -36,4 +36,5 @@ extern int inputRedirectionStartResult; MyThread *inputRedirectionCreateThread(void); void inputRedirectionThreadMain(void); +Result InputRedirection_Disable(s64 timeout); Result InputRedirection_DoOrUndoPatches(void); diff --git a/sysmodules/rosalina/include/memory.h b/sysmodules/rosalina/include/memory.h index 4c10a71..df938d5 100644 --- a/sysmodules/rosalina/include/memory.h +++ b/sysmodules/rosalina/include/memory.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/menu.h b/sysmodules/rosalina/include/menu.h index 1212a1e..34388da 100644 --- a/sysmodules/rosalina/include/menu.h +++ b/sysmodules/rosalina/include/menu.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -27,33 +27,25 @@ #pragma once #include <3ds/types.h> +#include <3ds/services/hid.h> #include "MyThread.h" #include "utils.h" #define HID_PAD (REG32(0x10146000) ^ 0xFFF) -#define BUTTON_A (1 << 0) -#define BUTTON_B (1 << 1) -#define BUTTON_SELECT (1 << 2) -#define BUTTON_START (1 << 3) -#define BUTTON_RIGHT (1 << 4) -#define BUTTON_LEFT (1 << 5) -#define BUTTON_UP (1 << 6) -#define BUTTON_DOWN (1 << 7) -#define BUTTON_R1 (1 << 8) -#define BUTTON_L1 (1 << 9) -#define BUTTON_X (1 << 10) -#define BUTTON_Y (1 << 11) -#define DEFAULT_MENU_COMBO (BUTTON_L1 | BUTTON_DOWN | BUTTON_SELECT) +#define DEFAULT_MENU_COMBO (KEY_L | KEY_DDOWN | KEY_SELECT) +#define DIRECTIONAL_KEYS (KEY_DOWN | KEY_UP | KEY_LEFT | KEY_RIGHT) #define CORE_APPLICATION 0 #define CORE_SYSTEM 1 typedef enum MenuItemAction { - METHOD, - MENU + MENU_END = 0, + METHOD = 1, + MENU = 2, } MenuItemAction; + typedef struct MenuItem { const char *title; @@ -62,16 +54,20 @@ typedef struct MenuItem { struct Menu *menu; void (*method)(void); }; + + bool (*visibility)(void); } MenuItem; + typedef struct Menu { const char *title; - u32 nbItems; - MenuItem items[0x40]; + MenuItem items[16]; } Menu; -extern bool terminationRequest; -extern Handle terminationRequestEvent; +extern bool isN3DS; +extern bool menuShouldExit; +extern bool preTerminationRequested; +extern Handle preTerminationEvent; extern u32 menuCombo; @@ -81,6 +77,9 @@ u32 waitInput(void); u32 waitComboWithTimeout(u32 msec); u32 waitCombo(void); +bool menuCheckN3ds(void); +u32 menuCountItems(const Menu *menu); + MyThread *menuCreateThread(void); void menuEnter(void); void menuLeave(void); diff --git a/sysmodules/rosalina/include/menus.h b/sysmodules/rosalina/include/menus.h index 5dc3ca3..88fede1 100644 --- a/sysmodules/rosalina/include/menus.h +++ b/sysmodules/rosalina/include/menus.h @@ -1,7 +1,7 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,8 +33,12 @@ extern Menu rosalinaMenu; void RosalinaMenu_TakeScreenshot(void); +void RosalinaMenu_ChangeScreenBrightness(void); void RosalinaMenu_ShowCredits(void); void RosalinaMenu_ProcessList(void); void RosalinaMenu_PowerOff(void); void RosalinaMenu_Reboot(void); void RosalinaMenu_Cheats(void); + +bool rosalinaMenuShouldShowDebugInfo(void); +void RosalinaMenu_ShowDebugInfo(void); diff --git a/sysmodules/rosalina/include/menus/cheats.h b/sysmodules/rosalina/include/menus/cheats.h index dc0562c..9ce7f22 100644 --- a/sysmodules/rosalina/include/menus/cheats.h +++ b/sysmodules/rosalina/include/menus/cheats.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,4 +33,5 @@ #define CHEATS_PER_MENU_PAGE 18 void RosalinaMenu_Cheats(void); -void Cheat_ApplyCheats(); +void Cheat_SeedRng(u64 seed); +void Cheat_ApplyCheats(void); diff --git a/sysmodules/rosalina/include/menus/debugger.h b/sysmodules/rosalina/include/menus/debugger.h index c24d813..4dec5fe 100644 --- a/sysmodules/rosalina/include/menus/debugger.h +++ b/sysmodules/rosalina/include/menus/debugger.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -32,6 +32,8 @@ 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/miscellaneous.h b/sysmodules/rosalina/include/menus/miscellaneous.h index 638d660..c715ef6 100644 --- a/sysmodules/rosalina/include/menus/miscellaneous.h +++ b/sysmodules/rosalina/include/menus/miscellaneous.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -35,4 +35,4 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void); void MiscellaneousMenu_ChangeMenuCombo(void); void MiscellaneousMenu_SaveSettings(void); void MiscellaneousMenu_InputRedirection(void); -void MiscellaneousMenu_SyncTimeDate(void); \ No newline at end of file +void MiscellaneousMenu_SyncTimeDate(void); diff --git a/sysmodules/rosalina/include/menus/n3ds.h b/sysmodules/rosalina/include/menus/n3ds.h index c1cb2a1..13c8116 100644 --- a/sysmodules/rosalina/include/menus/n3ds.h +++ b/sysmodules/rosalina/include/menus/n3ds.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/menus/process_list.h b/sysmodules/rosalina/include/menus/process_list.h index 2dcade7..ace7c26 100644 --- a/sysmodules/rosalina/include/menus/process_list.h +++ b/sysmodules/rosalina/include/menus/process_list.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/menus/screen_filters.h b/sysmodules/rosalina/include/menus/screen_filters.h index fa273e8..3ba6d09 100644 --- a/sysmodules/rosalina/include/menus/screen_filters.h +++ b/sysmodules/rosalina/include/menus/screen_filters.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -30,7 +30,7 @@ extern Menu screenFiltersMenu; -int screenFiltersCurrentTemperature; +extern int screenFiltersCurrentTemperature; void screenFiltersSetDisabled(void); void screenFiltersReduceBlueLevel1(void); diff --git a/sysmodules/rosalina/include/menus/sysconfig.h b/sysmodules/rosalina/include/menus/sysconfig.h index fcae0a4..a4188fa 100644 --- a/sysmodules/rosalina/include/menus/sysconfig.h +++ b/sysmodules/rosalina/include/menus/sysconfig.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -30,6 +30,12 @@ #include "menu.h" extern Menu sysconfigMenu; +extern bool isConnectionForced; + +void SysConfigMenu_UpdateStatus(bool control); void SysConfigMenu_ToggleLEDs(void); void SysConfigMenu_ToggleWireless(void); +void SysConfigMenu_TogglePowerButton(void); +void SysConfigMenu_ControlWifi(void); +void SysConfigMenu_DisableForcedWifiConnection(void); diff --git a/sysmodules/rosalina/include/minisoc.h b/sysmodules/rosalina/include/minisoc.h index 2d006b6..6040bc8 100644 --- a/sysmodules/rosalina/include/minisoc.h +++ b/sysmodules/rosalina/include/minisoc.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -18,13 +18,10 @@ #include #define SYNC_ERROR ENODEV - -extern Handle SOCU_handle; -extern Handle socMemhandle; - extern bool miniSocEnabled; -Result miniSocInit(); +Result miniSocInit(void); +Result miniSocExitDirect(void); Result miniSocExit(void); s32 _net_convert_error(s32 sock_retval); @@ -37,10 +34,17 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int socPoll(struct pollfd *fds, nfds_t nfds, int timeout); int socSetsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); int socClose(int sockfd); +long socGethostid(void); -ssize_t soc_recv(int sockfd, void *buf, size_t len, int flags); -ssize_t soc_send(int sockfd, const void *buf, size_t len, int flags); +ssize_t socRecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); +ssize_t socSendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); -// actually provided by ctrulib -ssize_t soc_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); -ssize_t soc_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); +static inline ssize_t socRecv(int sockfd, void *buf, size_t len, int flags) +{ + return socRecvfrom(sockfd, buf, len, flags, NULL, 0); +} + +static inline ssize_t socSend(int sockfd, const void *buf, size_t len, int flags) +{ + return socSendto(sockfd, buf, len, flags, NULL, 0); +} diff --git a/sysmodules/rosalina/include/ntp.h b/sysmodules/rosalina/include/ntp.h index 8780d0d..89cff94 100644 --- a/sysmodules/rosalina/include/ntp.h +++ b/sysmodules/rosalina/include/ntp.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -30,4 +30,4 @@ #include Result ntpGetTimeStamp(time_t *outTimestamp); -Result ntpSetTimeDate(const struct tm *localt); \ No newline at end of file +Result ntpSetTimeDate(time_t timestamp); diff --git a/sysmodules/rosalina/include/pmdbgext.h b/sysmodules/rosalina/include/pmdbgext.h index b8cf9e8..64491e8 100644 --- a/sysmodules/rosalina/include/pmdbgext.h +++ b/sysmodules/rosalina/include/pmdbgext.h @@ -1,11 +1,17 @@ // License for this file: ctrulib's license -// Copyright AuroraWright, TuxSH 2019 +// Copyright AuroraWright, TuxSH 2019-2020 #pragma once #include <3ds/services/pmapp.h> #include <3ds/services/pmdbg.h> -Result PMDBG_GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid); +/// Custom launch flags for PM launch commands. +enum { + PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING = BIT(24), +}; + +Result PMDBG_GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags); Result PMDBG_DebugNextApplicationByForce(bool debug); Result PMDBG_LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags); +Result PMDBG_PrepareToChainloadHomebrew(u64 titleId); diff --git a/sysmodules/rosalina/include/menus/process_patches.h b/sysmodules/rosalina/include/process_patches.h similarity index 87% rename from sysmodules/rosalina/include/menus/process_patches.h rename to sysmodules/rosalina/include/process_patches.h index 0501a84..4ecec3c 100644 --- a/sysmodules/rosalina/include/menus/process_patches.h +++ b/sysmodules/rosalina/include/process_patches.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -29,4 +29,5 @@ #include <3ds/types.h> #include "menu.h" -void ProcessPatchesMenu_PatchUnpatchFSDirectly(void); +Result OpenProcessByName(const char *name, Handle *h); +Result PatchProcessByName(const char *name, Result (*func)(u32 size)); diff --git a/sysmodules/rosalina/include/service_manager.h b/sysmodules/rosalina/include/service_manager.h index fca20c1..dad680c 100644 --- a/sysmodules/rosalina/include/service_manager.h +++ b/sysmodules/rosalina/include/service_manager.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/include/sock_util.h b/sysmodules/rosalina/include/sock_util.h index f1c255d..9a129dc 100644 --- a/sysmodules/rosalina/include/sock_util.h +++ b/sysmodules/rosalina/include/sock_util.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -68,10 +68,11 @@ typedef struct sock_server sock_free_func free; Handle shall_terminate_event; + Result init_result; } sock_server; Result server_init(struct sock_server *serv); -void server_bind(struct sock_server *serv, u16 port); +Result server_bind(struct sock_server *serv, u16 port); void server_run(struct sock_server *serv); void server_kill_connections(struct sock_server *serv); void server_set_should_close_all(struct sock_server *serv); diff --git a/sysmodules/rosalina/include/task_runner.h b/sysmodules/rosalina/include/task_runner.h index 9e924d8..dbab322 100644 --- a/sysmodules/rosalina/include/task_runner.h +++ b/sysmodules/rosalina/include/task_runner.h @@ -9,6 +9,7 @@ typedef struct TaskRunner { LightEvent parametersSetEvent; void (*task)(void *argdata); u8 argStorage[0x40]; + bool shouldTerminate; } TaskRunner; extern TaskRunner g_taskRunner; @@ -17,6 +18,8 @@ MyThread *taskRunnerCreateThread(void); void TaskRunner_Init(void); void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize); +void TaskRunner_Terminate(void); + /// Thread function void TaskRunner_HandleTasks(void); -void TaskRunner_WaitReady(void); \ No newline at end of file +void TaskRunner_WaitReady(void); diff --git a/sysmodules/rosalina/include/utils.h b/sysmodules/rosalina/include/utils.h index d702fe3..bb84620 100644 --- a/sysmodules/rosalina/include/utils.h +++ b/sysmodules/rosalina/include/utils.h @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -27,6 +27,7 @@ #pragma once #include <3ds/svc.h> +#include <3ds/srv.h> #include <3ds/result.h> #include <3ds/ipc.h> #include "csvc.h" @@ -40,7 +41,7 @@ #define REG32(addr) (*(vu32 *)(PA_PTR(addr))) -static inline u32 makeARMBranch(const void *src, const void *dst, bool link) // the macros for those are ugly and buggy +static inline u32 makeArmBranch(const void *src, const void *dst, bool link) // the macros for those are ugly and buggy { u32 instrBase = link ? 0xEB000000 : 0xEA000000; u32 off = (u32)((const u8 *)dst - ((const u8 *)src + 8)); // the PC is always two instructions ahead of the one being executed @@ -48,7 +49,7 @@ static inline u32 makeARMBranch(const void *src, const void *dst, bool link) // return instrBase | ((off >> 2) & 0xFFFFFF); } -static inline void *decodeARMBranch(const void *src) +static inline void *decodeArmBranch(const void *src) { u32 instr = *(const u32 *)src; s32 off = (instr & 0xFFFFFF) << 2; @@ -73,3 +74,12 @@ extern bool isN3DS; Result OpenProcessByName(const char *name, Handle *h); Result SaveSettings(void); +static inline bool isServiceUsable(const char *name) +{ + bool r; + return R_SUCCEEDED(srvIsServiceRegistered(&r, name)) && r; +} + +void formatMemoryPermission(char *outbuf, MemPerm perm); +void formatUserMemoryState(char *outbuf, MemState state); +u32 formatMemoryMapOfProcess(char *outbuf, u32 bufLen, Handle handle); diff --git a/sysmodules/rosalina/rosalina.rsf b/sysmodules/rosalina/rosalina.rsf index d9f09fb..a6c826e 100644 --- a/sysmodules/rosalina/rosalina.rsf +++ b/sysmodules/rosalina/rosalina.rsf @@ -21,7 +21,7 @@ AccessControlInfo: IdealProcessor : 1 AffinityMask : 3 - Priority : 20 + Priority : 25 # 55 DisableDebug : false EnableForceDebug : true @@ -37,7 +37,7 @@ AccessControlInfo: CoreVersion : 2 DescVersion : 2 - MemoryType : System # Application / System / Base + MemoryType : Base # Application / System / Base HandleTableSize: 150 MemoryMapping: diff --git a/sysmodules/rosalina/source/3dsx.c b/sysmodules/rosalina/source/3dsx.c index 12869d1..663c0e1 100644 --- a/sysmodules/rosalina/source/3dsx.c +++ b/sysmodules/rosalina/source/3dsx.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/source/MyThread.c b/sysmodules/rosalina/source/MyThread.c index ec227ac..b7554a3 100644 --- a/sysmodules/rosalina/source/MyThread.c +++ b/sysmodules/rosalina/source/MyThread.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/source/draw.c b/sysmodules/rosalina/source/draw.c index 44e278f..6becdac 100644 --- a/sysmodules/rosalina/source/draw.c +++ b/sysmodules/rosalina/source/draw.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -32,22 +32,22 @@ #include "memory.h" #include "menu.h" #include "utils.h" +#include "csvc.h" -u8 framebufferCache[FB_BOTTOM_SIZE]; +#define KERNPA2VA(a) ((a) + (GET_VERSION_MINOR(osGetKernelVersion()) < 44 ? 0xD0000000 : 0xC0000000)) static u32 gpuSavedFramebufferAddr1, gpuSavedFramebufferAddr2, gpuSavedFramebufferFormat, gpuSavedFramebufferStride; - +static u32 framebufferCacheSize; +static void *framebufferCache; static RecursiveLock lock; +void Draw_Init(void) +{ + RecursiveLock_Init(&lock); +} + void Draw_Lock(void) { - static bool lockInitialized = false; - if(!lockInitialized) - { - RecursiveLock_Init(&lock); - lockInitialized = true; - } - RecursiveLock_Lock(&lock); } @@ -58,7 +58,7 @@ void Draw_Unlock(void) void Draw_DrawCharacter(u32 posX, u32 posY, u32 color, char character) { - volatile u16 *const fb = (volatile u16 *const)FB_BOTTOM_VRAM_ADDR; + u16 *const fb = (u16 *)FB_BOTTOM_VRAM_ADDR; s32 y; for(y = 0; y < 10; y++) @@ -129,34 +129,78 @@ void Draw_ClearFramebuffer(void) Draw_FillFramebuffer(0); } -void Draw_SetupFramebuffer(void) +u32 Draw_AllocateFramebufferCache(void) +{ + // Try to see how much we can allocate... + // Can't use fbs in FCRAM when Home Menu is active (AXI config related maybe?) + u32 addr = 0x0D000000; + u32 tmp; + u32 minSize = (FB_BOTTOM_SIZE + 0xFFF) & ~0xFFF; + u32 maxSize = (FB_SCREENSHOT_SIZE + 0xFFF) & ~0xFFF; + u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM); + u32 size = remaining < maxSize ? remaining : maxSize; + + if (size < minSize || R_FAILED(svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READ | MEMPERM_WRITE, true))) + { + framebufferCache = NULL; + framebufferCacheSize = 0; + } + else + { + framebufferCache = (u32 *)addr; + framebufferCacheSize = size; + } + + return framebufferCacheSize; +} + +void Draw_FreeFramebufferCache(void) +{ + u32 tmp; + svcControlMemory(&tmp, (u32)framebufferCache, 0, framebufferCacheSize, MEMOP_FREE, 0); + framebufferCacheSize = 0; + framebufferCache = NULL; +} + +void *Draw_GetFramebufferCache(void) +{ + return framebufferCache; +} + +u32 Draw_GetFramebufferCacheSize(void) +{ + return framebufferCacheSize; +} + +u32 Draw_SetupFramebuffer(void) { while((GPU_PSC0_CNT | GPU_PSC1_CNT | GPU_TRANSFER_CNT | GPU_CMDLIST_CNT) & 1); - svcFlushEntireDataCache(); + Draw_FlushFramebuffer(); memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1; gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2; gpuSavedFramebufferFormat = GPU_FB_BOTTOM_FMT; gpuSavedFramebufferStride = GPU_FB_BOTTOM_STRIDE; GPU_FB_BOTTOM_ADDR_1 = GPU_FB_BOTTOM_ADDR_2 = FB_BOTTOM_VRAM_PA; - GPU_FB_BOTTOM_FMT = (GPU_FB_BOTTOM_FMT & ~7) | 2; + GPU_FB_BOTTOM_FMT = (GPU_FB_BOTTOM_FMT & ~7) | GSP_RGB565_OES; GPU_FB_BOTTOM_STRIDE = 240 * 2; - Draw_FlushFramebuffer(); + return framebufferCacheSize; } void Draw_RestoreFramebuffer(void) { memcpy(FB_BOTTOM_VRAM_ADDR, framebufferCache, FB_BOTTOM_SIZE); + Draw_FlushFramebuffer(); GPU_FB_BOTTOM_ADDR_1 = gpuSavedFramebufferAddr1; GPU_FB_BOTTOM_ADDR_2 = gpuSavedFramebufferAddr2; GPU_FB_BOTTOM_FMT = gpuSavedFramebufferFormat; GPU_FB_BOTTOM_STRIDE = gpuSavedFramebufferStride; - - Draw_FlushFramebuffer(); } void Draw_FlushFramebuffer(void) @@ -203,7 +247,7 @@ void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth) Draw_WriteUnaligned(dst + 0x22, 3 * width * heigth, 4); } -static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_FramebufferFormats srcFormat) +static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_FramebufferFormat srcFormat) { u8 red, green, blue; switch(srcFormat) @@ -267,16 +311,37 @@ static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_Frameb } } -void Draw_ConvertFrameBufferLine(u8 *line, bool top, bool left, u32 y) +typedef struct FrameBufferConvertArgs { + u8 *buf; + u8 startingLine; + u8 numLines; + bool top; + bool left; +} FrameBufferConvertArgs; + +static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *args) { - GSPGPU_FramebufferFormats fmt = top ? (GSPGPU_FramebufferFormats)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormats)(GPU_FB_BOTTOM_FMT & 7); - u32 width = top ? 400 : 320; - u8 formatSizes[] = { 4, 3, 2, 2, 2 }; - u32 stride = top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE; + static const u8 formatSizes[] = { 4, 3, 2, 2, 2 }; - u32 pa = Draw_GetCurrentFramebufferAddress(top, left); - u8 *addr = (u8 *)PA_PTR(pa); + GSPGPU_FramebufferFormat fmt = args->top ? (GSPGPU_FramebufferFormat)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormat)(GPU_FB_BOTTOM_FMT & 7); + u32 width = args->top ? 400 : 320; + u32 stride = args->top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE; - for(u32 x = 0; x < width; x++) - Draw_ConvertPixelToBGR8(line + x * 3 , addr + x * stride + y * formatSizes[(u8)fmt], fmt); + u32 pa = Draw_GetCurrentFramebufferAddress(args->top, args->left); + u8 *addr = (u8 *)KERNPA2VA(pa); + + for (u32 y = args->startingLine; y < args->startingLine + args->numLines; y++) + { + for(u32 x = 0; x < width; x++) + { + __builtin_prefetch(addr + x * stride + y * formatSizes[fmt], 0, 3); + Draw_ConvertPixelToBGR8(args->buf + (x + width * y) * 3 , addr + x * stride + y * formatSizes[fmt], fmt); + } + } +} + +void Draw_ConvertFrameBufferLines(u8 *buf, u32 startingLine, u32 numLines, bool top, bool left) +{ + FrameBufferConvertArgs args = { buf, (u8)startingLine, (u8)numLines, top, left }; + svcCustomBackdoor(Draw_ConvertFrameBufferLinesKernel, &args); } diff --git a/sysmodules/rosalina/source/errdisp.c b/sysmodules/rosalina/source/errdisp.c index 1947357..6f9777c 100644 --- a/sysmodules/rosalina/source/errdisp.c +++ b/sysmodules/rosalina/source/errdisp.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -32,7 +32,19 @@ #include "fmt.h" #include "ifile.h" +extern Handle preTerminationEvent; +static MyThread errDispThread; +static u8 ALIGN(8) errDispThreadStack[0xD00]; + static char userString[0x100 + 1] = {0}; +static char staticBuf[0x100 + 1] = {0}; + +MyThread *errDispCreateThread(void) +{ + if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0xD00, 55, CORE_SYSTEM))) + svcBreak(USERBREAK_PANIC); + return &errDispThread; +} static inline u32 ERRF_DisplayRegisterValue(u32 posX, u32 posY, const char *name, u32 value) { @@ -44,6 +56,11 @@ static inline int ERRF_FormatRegisterValue(char *out, const char *name, u32 valu return sprintf(out, "%-9s %08lx", name, value); } +static inline void ERRF_GetErrInfo(ERRF_FatalErrInfo* info, u32* in, u32 size) +{ + memcpy(info, in, size); +} + static int ERRF_FormatError(char *out, ERRF_FatalErrInfo *info) { char *outStart = out; @@ -148,7 +165,7 @@ static int ERRF_FormatError(char *out, ERRF_FatalErrInfo *info) desc = "The System Memory has been damaged."; break; case ERRF_ERRTYPE_FAILURE: - info->data.failure_mesg[0x60] = 0; // make sure the last byte in the IPC buffer is NULL + info->data.failure_mesg[0x5F] = 0; // make sure the last byte in the IPC buffer is NULL desc = info->data.failure_mesg; break; default: @@ -219,18 +236,18 @@ static Result ERRF_SaveErrorToFile(ERRF_FatalErrInfo *info) return res; } -void ERRF_HandleCommands(void *ctx) +void ERRF_HandleCommands(void) { - (void)ctx; u32 *cmdbuf = getThreadCommandBuffer(); + ERRF_FatalErrInfo info; switch(cmdbuf[0] >> 16) { case 1: // Throw { - ERRF_FatalErrInfo *info = (ERRF_FatalErrInfo *)(cmdbuf + 1); - ERRF_SaveErrorToFile(info); - if(info->type != ERRF_ERRTYPE_LOGGED || info->procId == 0) + ERRF_GetErrInfo(&info, (cmdbuf + 1), sizeof(ERRF_FatalErrInfo)); + ERRF_SaveErrorToFile(&info); + if(!menuShouldExit && (info.type != ERRF_ERRTYPE_LOGGED || info.procId == 0)) { menuEnter(); @@ -238,7 +255,7 @@ void ERRF_HandleCommands(void *ctx) Draw_ClearFramebuffer(); Draw_FlushFramebuffer(); - ERRF_DisplayError(info); + ERRF_DisplayError(&info); /* If we ever wanted to return: @@ -252,26 +269,98 @@ void ERRF_HandleCommands(void *ctx) __builtin_unreachable(); } - cmdbuf[0] = 0x10040; + cmdbuf[0] = IPC_MakeHeader(1, 1, 0); cmdbuf[1] = 0; break; } case 2: // SetUserString { - if(cmdbuf[0] != 0x20042 || (cmdbuf[2] & 0x3C0F) != 2) + if(cmdbuf[0] != IPC_MakeHeader(2, 1, 2) || (cmdbuf[2] & 0x3C0F) != 2) { - cmdbuf[0] = 0x40; + cmdbuf[0] = IPC_MakeHeader(0, 1, 0); cmdbuf[1] = 0xD9001830; } else { - cmdbuf[0] = 0x20040; - u32 sz = cmdbuf[1] <= 0x100 ? sz : 0x100; + u32 sz = cmdbuf[1] <= 0x100 ? cmdbuf[1] : 0x100; memcpy(userString, cmdbuf + 3, sz); userString[sz] = 0; + + cmdbuf[0] = IPC_MakeHeader(2, 1, 0); + cmdbuf[1] = 0; } break; } } } + +void errDispThreadMain(void) +{ + Handle handles[3]; + Handle serverHandle, clientHandle, sessionHandle = 0; + + u32 replyTarget = 0; + s32 index; + + Result res; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *sbuf = getThreadStaticBuffers(); + + sbuf[0] = IPC_Desc_StaticBuffer(0x100, 0); + sbuf[1] = (u32)staticBuf; + + assertSuccess(svcCreatePort(&serverHandle, &clientHandle, "err:f", 1)); + + do + { + handles[0] = preTerminationEvent; + handles[1] = serverHandle; + handles[2] = sessionHandle; + + if(replyTarget == 0) // k11 + cmdbuf[0] = 0xFFFF0000; + res = svcReplyAndReceive(&index, handles, 1 + (sessionHandle == 0 ? 1 : 2), replyTarget); + + if(R_FAILED(res)) + { + if((u32)res == 0xC920181A) // session closed by remote + { + svcCloseHandle(sessionHandle); + sessionHandle = 0; + replyTarget = 0; + } + + else + svcBreak(USERBREAK_PANIC); + } + + else + { + if (index == 0) + { + break; + } + else if(index == 1) + { + Handle session; + assertSuccess(svcAcceptSession(&session, serverHandle)); + + if(sessionHandle == 0) + sessionHandle = session; + else + svcCloseHandle(session); + } + else + { + ERRF_HandleCommands(); + replyTarget = sessionHandle; + } + } + } + while(!preTerminationRequested); + + svcCloseHandle(sessionHandle); + svcCloseHandle(clientHandle); + svcCloseHandle(serverHandle); +} diff --git a/sysmodules/rosalina/source/fmt.c b/sysmodules/rosalina/source/fmt.c index c7a56fe..c9185b4 100644 --- a/sysmodules/rosalina/source/fmt.c +++ b/sysmodules/rosalina/source/fmt.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/source/gdb.c b/sysmodules/rosalina/source/gdb.c index 68f6d64..7c10e11 100644 --- a/sysmodules/rosalina/source/gdb.c +++ b/sysmodules/rosalina/source/gdb.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/breakpoints.c b/sysmodules/rosalina/source/gdb/breakpoints.c index 75d24b6..ae3281e 100644 --- a/sysmodules/rosalina/source/gdb/breakpoints.c +++ b/sysmodules/rosalina/source/gdb/breakpoints.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/debug.c b/sysmodules/rosalina/source/gdb/debug.c index 47d8477..6e2ef3f 100644 --- a/sysmodules/rosalina/source/gdb/debug.c +++ b/sysmodules/rosalina/source/gdb/debug.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/hio.c b/sysmodules/rosalina/source/gdb/hio.c index 31b1f89..7e61323 100644 --- a/sysmodules/rosalina/source/gdb/hio.c +++ b/sysmodules/rosalina/source/gdb/hio.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/mem.c b/sysmodules/rosalina/source/gdb/mem.c index 8366403..658ded8 100644 --- a/sysmodules/rosalina/source/gdb/mem.c +++ b/sysmodules/rosalina/source/gdb/mem.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/monitor.c b/sysmodules/rosalina/source/gdb/monitor.c index 30114be..0fa81a4 100644 --- a/sysmodules/rosalina/source/gdb/monitor.c +++ b/sysmodules/rosalina/source/gdb/monitor.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -9,15 +9,15 @@ #include "gdb/net.h" #include "gdb/debug.h" -extern Handle terminationRequestEvent; -extern bool terminationRequest; +extern Handle preTerminationEvent; +extern bool preTerminationRequested; void GDB_RunMonitor(GDBServer *server) { Handle handles[3 + MAX_DEBUG]; Result r = 0; - handles[0] = terminationRequestEvent; + handles[0] = preTerminationEvent; handles[1] = server->super.shall_terminate_event; handles[2] = server->statusUpdated; @@ -81,5 +81,5 @@ void GDB_RunMonitor(GDBServer *server) RecursiveLock_Unlock(&ctx->lock); } } - while(!terminationRequest && server->super.running); + while(!preTerminationRequested && server->super.running); } diff --git a/sysmodules/rosalina/source/gdb/net.c b/sysmodules/rosalina/source/gdb/net.c index b328b4b..85ff466 100644 --- a/sysmodules/rosalina/source/gdb/net.c +++ b/sysmodules/rosalina/source/gdb/net.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -177,7 +177,7 @@ int GDB_ReceivePacket(GDBContext *ctx) memcpy(backupbuf, ctx->buffer, ctx->latestSentPacketSize); memset(ctx->buffer, 0, sizeof(ctx->buffer)); - int r = soc_recv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK); + int r = socRecv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK); if(r < 1) return -1; if(ctx->buffer[0] == '+') // GDB sometimes acknowleges TCP acknowledgment packets (yes...). IDA does it properly @@ -186,20 +186,20 @@ int GDB_ReceivePacket(GDBContext *ctx) return -1; // Consume it - r = soc_recv(ctx->super.sockfd, ctx->buffer, 1, 0); + r = socRecv(ctx->super.sockfd, ctx->buffer, 1, 0); if(r != 1) return -1; ctx->buffer[0] = 0; - r = soc_recv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK); + r = socRecv(ctx->super.sockfd, ctx->buffer, sizeof(ctx->buffer), MSG_PEEK); if(r == -1) goto packet_error; } else if(ctx->buffer[0] == '-') { - soc_send(ctx->super.sockfd, backupbuf, ctx->latestSentPacketSize, 0); + socSend(ctx->super.sockfd, backupbuf, ctx->latestSentPacketSize, 0); return 0; } int maxlen = r > (int)sizeof(ctx->buffer) ? (int)sizeof(ctx->buffer) : r; @@ -215,7 +215,7 @@ int GDB_ReceivePacket(GDBContext *ctx) else { u8 checksum; - r = soc_recv(ctx->super.sockfd, ctx->buffer, 3 + pos - ctx->buffer, 0); + r = socRecv(ctx->super.sockfd, ctx->buffer, 3 + pos - ctx->buffer, 0); if(r != 3 + pos - ctx->buffer || GDB_DecodeHex(&checksum, pos + 1, 1) != 1) goto packet_error; else if(GDB_ComputeChecksum(ctx->buffer + 1, pos - ctx->buffer - 1) != checksum) @@ -227,7 +227,7 @@ int GDB_ReceivePacket(GDBContext *ctx) } else if(ctx->buffer[0] == '\x03') { - r = soc_recv(ctx->super.sockfd, ctx->buffer, 1, 0); + r = socRecv(ctx->super.sockfd, ctx->buffer, 1, 0); if(r != 1) goto packet_error; @@ -236,7 +236,7 @@ int GDB_ReceivePacket(GDBContext *ctx) if(!(ctx->flags & GDB_FLAG_NOACK)) { - int r2 = soc_send(ctx->super.sockfd, "+", 1, 0); + int r2 = socSend(ctx->super.sockfd, "+", 1, 0); if(r2 != 1) return -1; } @@ -252,7 +252,7 @@ int GDB_ReceivePacket(GDBContext *ctx) packet_error: if(!(ctx->flags & GDB_FLAG_NOACK)) { - r = soc_send(ctx->super.sockfd, "-", 1, 0); + r = socSend(ctx->super.sockfd, "-", 1, 0); if(r != 1) return -1; else @@ -264,7 +264,7 @@ packet_error: static int GDB_DoSendPacket(GDBContext *ctx, u32 len) { - int r = soc_send(ctx->super.sockfd, ctx->buffer, len, 0); + int r = socSend(ctx->super.sockfd, ctx->buffer, len, 0); if(r > 0) ctx->latestSentPacketSize = r; diff --git a/sysmodules/rosalina/source/gdb/query.c b/sysmodules/rosalina/source/gdb/query.c index 4c39b04..f070170 100644 --- a/sysmodules/rosalina/source/gdb/query.c +++ b/sysmodules/rosalina/source/gdb/query.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/regs.c b/sysmodules/rosalina/source/gdb/regs.c index 9eb5dbb..78d8226 100644 --- a/sysmodules/rosalina/source/gdb/regs.c +++ b/sysmodules/rosalina/source/gdb/regs.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/remote_command.c b/sysmodules/rosalina/source/gdb/remote_command.c index 68bc7e6..c986990 100644 --- a/sysmodules/rosalina/source/gdb/remote_command.c +++ b/sysmodules/rosalina/source/gdb/remote_command.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -12,6 +12,8 @@ #include "gdb/breakpoints.h" #include "utils.h" +#include "../utils.h" + struct { const char *name; @@ -359,81 +361,19 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMmuConfig) return GDB_SendHexPacket(ctx, outbuf, n); } -static const char *FormatMemPerm(u32 perm) -{ - if (perm == MEMPERM_DONTCARE) - return "???"; - - static char buf[4] = {0}; - - buf[0] = perm & MEMPERM_READ ? 'r' : '-'; - buf[1] = perm & MEMPERM_WRITE ? 'w' : '-'; - buf[2] = perm & MEMPERM_EXECUTE ? 'x' : '-'; - - return buf; -} - -static const char *FormatMemState(u32 state) -{ - if (state > 11) - return "Unknown"; - - static const char *states[12] = - { - "Free", - "Reserved", - "IO", - "Static", - "Code", - "Private", - "Shared", - "Continuous", - "Aliased", - "Alias", - "AliasCode", - "Locked" - }; - - return states[state]; -} - GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions) { - u32 address = 0; u32 posInBuffer = 0; - u32 maxPosInBuffer = GDB_BUF_LEN / 2 - 35; ///< 35 is the maximum length of a formatted region Handle handle; - MemInfo memi; - PageInfo pagei; char outbuf[GDB_BUF_LEN / 2 + 1]; if(R_FAILED(svcOpenProcess(&handle, ctx->pid))) { posInBuffer = sprintf(outbuf, "Invalid process (wtf?)\n"); - goto end; + return GDB_SendHexPacket(ctx, outbuf, posInBuffer); } - while (address < 0x40000000 ///< Limit to check for regions - && posInBuffer < maxPosInBuffer - && R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address))) - { - // Update the address for next region - address = memi.base_addr + memi.size; - - // If region isn't FREE then add it to the list - if (memi.state != MEMSTATE_FREE) - { - const char *perm = FormatMemPerm(memi.perm); - const char *state = FormatMemState(memi.state); - - posInBuffer += sprintf(outbuf + posInBuffer, "%08lx - %08lx %s %s\n", - memi.base_addr, address, perm, state); - } - } - - svcCloseHandle(handle); - -end: + posInBuffer = formatMemoryMapOfProcess(outbuf, GDB_BUF_LEN / 2, handle); return GDB_SendHexPacket(ctx, outbuf, posInBuffer); } diff --git a/sysmodules/rosalina/source/gdb/server.c b/sysmodules/rosalina/source/gdb/server.c index 5be53d5..847040a 100644 --- a/sysmodules/rosalina/source/gdb/server.c +++ b/sysmodules/rosalina/source/gdb/server.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -74,13 +74,14 @@ void GDB_DecrementServerReferenceCount(GDBServer *server) void GDB_RunServer(GDBServer *server) { - server_bind(&server->super, GDB_PORT_BASE); - server_bind(&server->super, GDB_PORT_BASE + 1); - server_bind(&server->super, GDB_PORT_BASE + 2); + Result res = server_bind(&server->super, GDB_PORT_BASE); + if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 1); + if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 2); - server_bind(&server->super, GDB_PORT_BASE + 3); // next application + if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 3); // next application - server_run(&server->super); + if(R_SUCCEEDED(res)) + server_run(&server->super); } void GDB_LockAllContexts(GDBServer *server) @@ -136,9 +137,9 @@ GDBContext *GDB_SelectAvailableContext(GDBServer *server, u16 minPort, u16 maxPo { ctx->flags |= GDB_FLAG_SELECTED; ctx->localPort = port; + ctx->parent = server; } - ctx->parent = server; GDB_UnlockAllContexts(server); return ctx; } diff --git a/sysmodules/rosalina/source/gdb/stop_point.c b/sysmodules/rosalina/source/gdb/stop_point.c index 64f8b1f..d5164be 100644 --- a/sysmodules/rosalina/source/gdb/stop_point.c +++ b/sysmodules/rosalina/source/gdb/stop_point.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/thread.c b/sysmodules/rosalina/source/gdb/thread.c index 20f655f..985a9c1 100644 --- a/sysmodules/rosalina/source/gdb/thread.c +++ b/sysmodules/rosalina/source/gdb/thread.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/tio.c b/sysmodules/rosalina/source/gdb/tio.c index 31d5702..358b103 100644 --- a/sysmodules/rosalina/source/gdb/tio.c +++ b/sysmodules/rosalina/source/gdb/tio.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -85,38 +85,38 @@ typedef u32 gdbhio_time_t; typedef int gdbhio_mode_t; -struct gdbhio_stat { - unsigned int st_dev; /* device */ - unsigned int st_ino; /* inode */ - gdbhio_mode_t st_mode; /* protection */ - unsigned int st_nlink; /* number of hard links */ - unsigned int st_uid; /* user ID of owner */ - unsigned int st_gid; /* group ID of owner */ - unsigned int st_rdev; /* device type (if inode device) */ - u64 st_size; /* total size, in bytes */ - u64 st_blksize; /* blocksize for filesystem I/O */ - u64 st_blocks; /* number of blocks allocated */ - gdbhio_time_t st_atime; /* time of last access */ - gdbhio_time_t st_mtime; /* time of last modification */ - gdbhio_time_t st_ctime; /* time of last change */ +struct PACKED ALIGN(4) gdbhio_stat { + u32 gst_dev; /* device */ + u32 gst_ino; /* inode */ + gdbhio_mode_t gst_mode; /* protection */ + u32 gst_nlink; /* number of hard links */ + u32 gst_uid; /* user ID of owner */ + u32 gst_gid; /* group ID of owner */ + u32 gst_rdev; /* device type (if inode device) */ + u64 gst_size; /* total size, in bytes */ + u64 gst_blksize; /* blocksize for filesystem I/O */ + u64 gst_blocks; /* number of blocks allocated */ + gdbhio_time_t gst_atime; /* time of last access */ + gdbhio_time_t gst_mtime; /* time of last modification */ + gdbhio_time_t gst_ctime; /* time of last change */ }; static void GDB_TioMakeStructStat(struct gdbhio_stat *out, const struct gdbhio_stat *in) { memset(out, 0, sizeof(struct gdbhio_stat)); - out->st_dev = __builtin_bswap32(in->st_dev); - out->st_ino = __builtin_bswap32(in->st_ino); - out->st_mode = __builtin_bswap32(in->st_dev); - out->st_nlink = __builtin_bswap32(in->st_nlink); - out->st_uid = __builtin_bswap32(in->st_uid); - out->st_gid = __builtin_bswap32(in->st_gid); - out->st_rdev = __builtin_bswap32(in->st_rdev); - out->st_size = __builtin_bswap64(in->st_size); - out->st_blksize = __builtin_bswap64(in->st_blksize); - out->st_blocks = __builtin_bswap64(in->st_blocks); - out->st_atime = __builtin_bswap32(in->st_atime); - out->st_mtime = __builtin_bswap32(in->st_mtime); - out->st_ctime = __builtin_bswap32(in->st_ctime); + out->gst_dev = __builtin_bswap32(in->gst_dev); + out->gst_ino = __builtin_bswap32(in->gst_ino); + out->gst_mode = __builtin_bswap32(in->gst_dev); + out->gst_nlink = __builtin_bswap32(in->gst_nlink); + out->gst_uid = __builtin_bswap32(in->gst_uid); + out->gst_gid = __builtin_bswap32(in->gst_gid); + out->gst_rdev = __builtin_bswap32(in->gst_rdev); + out->gst_size = __builtin_bswap64(in->gst_size); + out->gst_blksize = __builtin_bswap64(in->gst_blksize); + out->gst_blocks = __builtin_bswap64(in->gst_blocks); + out->gst_atime = __builtin_bswap32(in->gst_atime); + out->gst_mtime = __builtin_bswap32(in->gst_mtime); + out->gst_ctime = __builtin_bswap32(in->gst_ctime); } // Inspired from https://github.com/smealum/ctrulib/blob/master/libctru/source/sdmc_dev.c @@ -408,8 +408,8 @@ GDB_DECLARE_TIO_HANDLER(Stat) if (err == 0) { - gdbSt.st_nlink = 1; - gdbSt.st_mode = GDBHIO_S_IFREG | GDBHIO_S_IRUSR | GDBHIO_S_IWUSR | + gdbSt.gst_nlink = 1; + gdbSt.gst_mode = GDBHIO_S_IFREG | GDBHIO_S_IRUSR | GDBHIO_S_IWUSR | GDBHIO_S_IRGRP | GDBHIO_S_IWGRP | GDBHIO_S_IROTH | GDBHIO_S_IWOTH; } } @@ -419,8 +419,8 @@ GDB_DECLARE_TIO_HANDLER(Stat) if (err == 0) { FSDIR_Close(dirHandle); - gdbSt.st_nlink = 1; - gdbSt.st_mode = GDBHIO_S_IFDIR | GDBHIO_S_IRWXU | GDBHIO_S_IRWXG | GDBHIO_S_IRWXO; + gdbSt.gst_nlink = 1; + gdbSt.gst_mode = GDBHIO_S_IFDIR | GDBHIO_S_IRWXU | GDBHIO_S_IRWXG | GDBHIO_S_IRWXO; } } @@ -524,4 +524,4 @@ GDB_DECLARE_VERBOSE_HANDLER(File) } return GDB_HandleUnsupported(ctx); // No handler found! -} \ No newline at end of file +} diff --git a/sysmodules/rosalina/source/gdb/verbose.c b/sysmodules/rosalina/source/gdb/verbose.c index c95066d..a4a3edb 100644 --- a/sysmodules/rosalina/source/gdb/verbose.c +++ b/sysmodules/rosalina/source/gdb/verbose.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/gdb/watchpoints.c b/sysmodules/rosalina/source/gdb/watchpoints.c index 54762f6..8a3bc71 100644 --- a/sysmodules/rosalina/source/gdb/watchpoints.c +++ b/sysmodules/rosalina/source/gdb/watchpoints.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -12,7 +12,7 @@ #include /* - There are only 2 Watchpoint Register Pairs on MPCORE ARM11 CPUs, + There are only 2 Watchpoint Register Pairs on MPCORE Arm11 CPUs, and only 2 Breakpoint Register Pairs with context ID capabilities (BRP4-5) as well. We'll reserve and use all 4 of them diff --git a/sysmodules/rosalina/source/gdb/xfer.c b/sysmodules/rosalina/source/gdb/xfer.c index e6a1fcd..2c3102d 100644 --- a/sysmodules/rosalina/source/gdb/xfer.c +++ b/sysmodules/rosalina/source/gdb/xfer.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ diff --git a/sysmodules/rosalina/source/hbloader.c b/sysmodules/rosalina/source/hbloader.c index 2c325bb..d3f2775 100644 --- a/sysmodules/rosalina/source/hbloader.c +++ b/sysmodules/rosalina/source/hbloader.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -36,7 +36,8 @@ #include "gdb/server.h" #include "pmdbgext.h" -#define MAP_BASE 0x10000000 +#define SYSCOREVER (*(vu32 *)0x1FF80010) +#define APPMEMTYPE (*(vu32 *)0x1FF80030) extern GDBContext *nextApplicationGdbCtx; extern GDBServer gdbServer; @@ -77,16 +78,13 @@ static const char serviceList[32][8] = "y2r:u", }; -static const u64 dependencyList[] = +static const u64 dependencyListNativeFirm[] = { 0x0004013000002402LL, //ac 0x0004013000001502LL, //am - 0x0004013000003402LL, //boss - 0x0004013000001602LL, //camera 0x0004013000001702LL, //cfg 0x0004013000001802LL, //codec 0x0004013000002702LL, //csnd - 0x0004013000002802LL, //dlp 0x0004013000001A02LL, //dsp 0x0004013000001B02LL, //gpio 0x0004013000001C02LL, //gsp @@ -95,23 +93,55 @@ static const u64 dependencyList[] = 0x0004013000001E02LL, //i2c 0x0004013000003302LL, //ir 0x0004013000001F02LL, //mcu - 0x0004013000002002LL, //mic - 0x0004013000002B02LL, //ndm - 0x0004013000003502LL, //news 0x0004013000002C02LL, //nim 0x0004013000002D02LL, //nwm 0x0004013000002102LL, //pdn 0x0004013000003102LL, //ps 0x0004013000002202LL, //ptm - 0x0004013000003702LL, //ro 0x0004013000002E02LL, //socket 0x0004013000002302LL, //spi 0x0004013000002F02LL, //ssl + + // Not present on SAFE_FIRM: + 0x0004013000003402LL, //boss + 0x0004013000001602LL, //camera + 0x0004013000002802LL, //dlp + 0x0004013000002002LL, //mic + 0x0004013000002B02LL, //ndm + 0x0004013000003502LL, //news + 0x0004013000003702LL, //ro +}; + +static const u64 dependencyListSafeFirm[] = +{ + 0x0004013000002403LL, //ac + 0x0004013000001503LL, //am + 0x0004013000001703LL, //cfg + 0x0004013000001803LL, //codec + 0x0004013000002703LL, //csnd + 0x0004013000001A03LL, //dsp + 0x0004013000001B03LL, //gpio + 0x0004013000001C03LL, //gsp + 0x0004013000001D03LL, //hid + 0x0004013000002903LL, //http + 0x0004013000001E03LL, //i2c + 0x0004013000003303LL, //ir + 0x0004013000001F03LL, //mcu + 0x0004013000002C03LL, //nim + 0x0004013000002D03LL, //nwm + 0x0004013000002103LL, //pdn + 0x0004013000003103LL, //ps + 0x0004013000002203LL, //ptm + 0x0004013000002E03LL, //socket + 0x0004013000002303LL, //spi + 0x0004013000002F03LL, //ssl + + 0x0004013000003203LL, //friends (wouldn't be launched otherwise) }; static const u32 kernelCaps[] = { - 0xFC00022C, // Kernel release version: 8.0 (necessary for using the new linear mapping) + 0xFC00022C, // Kernel release version 8.0 is necessary for using the new linear mapping. Modified below. 0xFF81FF50, // RW static mapping: 0x1FF50000 0xFF81FF58, // RW static mapping: 0x1FF58000 0xFF81FF70, // RW static mapping: 0x1FF70000 @@ -135,6 +165,31 @@ static u16 *u16_strncpy(u16 *dest, const u16 *src, u32 size) return dest; } +void HBLDR_RestartHbApplication(void *p) +{ + (void)p; + // Don't crash if we fail + + FS_ProgramInfo programInfo; + u32 pid; + u32 launchFlags; + + Result res = PMDBG_GetCurrentAppInfo(&programInfo, &pid, &launchFlags); + if (R_FAILED(res)) return; + res = PMDBG_PrepareToChainloadHomebrew(programInfo.programId); + if (R_FAILED(res)) return; + res = PMAPP_TerminateCurrentApplication(3 * 1000 * 1000 *1000LL); // 3s, like what NS uses + if (R_FAILED(res)) return; + if (R_SUCCEEDED(res)) + { + do + { + svcSleepThread(100 * 1000 * 1000LL); + res = PMAPP_LaunchTitle(&programInfo, PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING | launchFlags); + } while (res == (Result)0xC8A05BF0); + } +} + void HBLDR_HandleCommands(void *ctx) { (void)ctx; @@ -181,8 +236,10 @@ void HBLDR_HandleCommands(void *ctx) break; } + // note: mappableFree doesn't do anything u32 tmp = 0; - res = svcControlMemoryEx(&tmp, MAP_BASE, 0, totalSize, MEMOP_ALLOC | flags, MEMPERM_READ | MEMPERM_WRITE, true); + u32 *addr = mappableAlloc(totalSize); + res = svcControlMemoryEx(&tmp, (u32)addr, 0, totalSize, MEMOP_ALLOC | flags, MEMPERM_READ | MEMPERM_WRITE, true); if (R_FAILED(res)) { IFile_Close(&file); @@ -190,12 +247,12 @@ void HBLDR_HandleCommands(void *ctx) break; } - Handle hCodeset = Ldr_CodesetFrom3dsx(name, (u32*)MAP_BASE, baseAddr, &file, tid); + Handle hCodeset = Ldr_CodesetFrom3dsx(name, addr, baseAddr, &file, tid); IFile_Close(&file); if (!hCodeset) { - svcControlMemory(&tmp, MAP_BASE, 0, totalSize, MEMOP_FREE, 0); + svcControlMemory(&tmp, (u32)addr, 0, totalSize, MEMOP_FREE, 0); error(cmdbuf, MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_LDR, RD_NOT_FOUND)); break; } @@ -252,28 +309,36 @@ void HBLDR_HandleCommands(void *ctx) memcpy(exhi->sci.codeset_info.name, "3dsx_app", 8); memcpy(&exhi->sci.codeset_info.stack_size, &stacksize, 4); memset(&exhi->sci.dependencies, 0, sizeof(exhi->sci.dependencies)); - memcpy(exhi->sci.dependencies, dependencyList, sizeof(dependencyList)); + + if (SYSCOREVER == 2) + memcpy(exhi->sci.dependencies, dependencyListNativeFirm, sizeof(dependencyListNativeFirm)); + else if (SYSCOREVER == 3) + memcpy(exhi->sci.dependencies, dependencyListSafeFirm, sizeof(dependencyListSafeFirm)); ExHeader_Arm11SystemLocalCapabilities* localcaps0 = &exhi->aci.local_caps; - localcaps0->core_info.core_version = 2; + localcaps0->core_info.core_version = SYSCOREVER; localcaps0->core_info.use_cpu_clockrate_804MHz = false; localcaps0->core_info.enable_l2c = false; - localcaps0->core_info.n3ds_system_mode = SYSMODE_N3DS_PROD; localcaps0->core_info.ideal_processor = 0; localcaps0->core_info.affinity_mask = BIT(0); - localcaps0->core_info.o3ds_system_mode = SYSMODE_O3DS_PROD; localcaps0->core_info.priority = 0x30; + u32 appmemtype = APPMEMTYPE; + localcaps0->core_info.o3ds_system_mode = appmemtype < 6 ? (SystemMode)appmemtype : SYSMODE_O3DS_PROD; + localcaps0->core_info.n3ds_system_mode = appmemtype >= 6 ? (SystemMode)(appmemtype - 6 + 1) : SYSMODE_N3DS_PROD; + memset(localcaps0->reslimits, 0, sizeof(localcaps0->reslimits)); - localcaps0->reslimits[0] = 0x9E; // Stuff needed to run stuff on core1 + // Set mode1 preemption mode for core1, max. 89% of CPU time (default 0, requires a APT_SetAppCpuTimeLimit call) + // See the big comment in sysmodules/pm/source/reslimit.c for technical details. + localcaps0->reslimits[0] = BIT(7) | 89; - localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything + //localcaps0->storage_info.fs_access_info = 0xFFFFFFFF; // Give access to everything localcaps0->storage_info.no_romfs = true; localcaps0->storage_info.use_extended_savedata_access = true; // Whatever - /* We have a patched SM, so whatever... */ + // We have a patched SM, so whatever... memset(localcaps0->service_access, 0, sizeof(localcaps0->service_access)); memcpy(localcaps0->service_access, serviceList, sizeof(serviceList)); @@ -283,9 +348,12 @@ void HBLDR_HandleCommands(void *ctx) memset(kcaps0->descriptors, 0xFF, sizeof(kcaps0->descriptors)); memcpy(kcaps0->descriptors, kernelCaps, sizeof(kernelCaps)); - u64 lastdep = sizeof(dependencyList)/8; - if (osGetFirmVersion() >= SYSTEM_VERSION(2,50,0)) // 9.6+ FIRM + // Set kernel release version to the current kernel version + kcaps0->descriptors[0] = 0xFC000000 | (osGetKernelVersion() >> 16); + + if (GET_VERSION_MINOR(osGetKernelVersion()) >= 50 && SYSCOREVER == 2) // 9.6+ NFIRM { + u64 lastdep = sizeof(dependencyListNativeFirm)/8; exhi->sci.dependencies[lastdep++] = 0x0004013000004002ULL; // nfc strncpy((char*)&localcaps0->service_access[0x20], "nfc:u", 8); s64 dummy = 0; diff --git a/sysmodules/rosalina/source/ifile.c b/sysmodules/rosalina/source/ifile.c index 5c4cb12..7ede5c4 100644 --- a/sysmodules/rosalina/source/ifile.c +++ b/sysmodules/rosalina/source/ifile.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/source/input_redirection.c b/sysmodules/rosalina/source/input_redirection.c index 6f4235a..811235b 100644 --- a/sysmodules/rosalina/source/input_redirection.c +++ b/sysmodules/rosalina/source/input_redirection.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -26,9 +26,10 @@ #include <3ds.h> #include -#include "utils.h" // for makeARMBranch +#include "utils.h" // for makeArmBranch #include "minisoc.h" #include "input_redirection.h" +#include "process_patches.h" #include "menus.h" #include "memory.h" #include "sleep.h" @@ -57,27 +58,51 @@ int inputRedirectionStartResult; void inputRedirectionThreadMain(void) { Result res = 0; + inputRedirectionStartResult = 0; + res = miniSocInit(); if(R_FAILED(res)) + { + // Socket services broken + inputRedirectionStartResult = res; + + miniSocExit(); + // Still signal the event + svcSignalEvent(inputRedirectionThreadStartedEvent); return; + } int sock = socSocket(AF_INET, SOCK_DGRAM, 0); - while(sock == -1) + u32 tries = 15; + while(sock == -1 && --tries > 0) { - svcSleepThread(1000 * 0000 * 0000LL); + svcSleepThread(100 * 1000 * 1000LL); sock = socSocket(AF_INET, SOCK_DGRAM, 0); } + if (sock < -10000 || tries == 0) { + // Socket services broken + inputRedirectionStartResult = -1; + + miniSocExit(); + // Still signal the event + svcSignalEvent(inputRedirectionThreadStartedEvent); + return; + } + struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(4950); - saddr.sin_addr.s_addr = gethostid(); + saddr.sin_addr.s_addr = socGethostid(); res = socBind(sock, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); if(res != 0) { socClose(sock); miniSocExit(); inputRedirectionStartResult = res; + + // Still signal the event + svcSignalEvent(inputRedirectionThreadStartedEvent); return; } @@ -91,7 +116,7 @@ void inputRedirectionThreadMain(void) char buf[20]; u32 oldSpecialButtons = 0, specialButtons = 0; - while(inputRedirectionEnabled && !terminationRequest) + while(inputRedirectionEnabled && !preTerminationRequested) { struct pollfd pfd; pfd.fd = sock; @@ -108,7 +133,7 @@ void inputRedirectionThreadMain(void) int pollres = socPoll(&pfd, 1, 10); if(pollres > 0 && (pfd.revents & POLLIN)) { - int n = soc_recvfrom(sock, buf, 20, 0, NULL, 0); + int n = socRecvfrom(sock, buf, 20, 0, NULL, 0); if(n < 0) break; else if(n < 12) @@ -134,21 +159,40 @@ void inputRedirectionThreadMain(void) srvPublishToSubscriber(0x203, 0); } } + else if(pollres < -10000) + break; } + inputRedirectionEnabled = false; struct linger linger; linger.l_onoff = 1; linger.l_linger = 0; socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)); - socClose(sock); + miniSocExit(); } void hidCodePatchFunc(void); void irCodePatchFunc(void); +Result InputRedirection_Disable(s64 timeout) +{ + if(!inputRedirectionEnabled) + return 0; + + Result res = InputRedirection_DoOrUndoPatches(); + if(R_FAILED(res)) + return res; + + inputRedirectionEnabled = false; + res = MyThread_Join(&inputRedirectionThread, timeout); + svcCloseHandle(inputRedirectionThreadStartedEvent); + + return res; +} + Result InputRedirection_DoOrUndoPatches(void) { s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize; @@ -156,6 +200,8 @@ Result InputRedirection_DoOrUndoPatches(void) Handle processHandle; Result res = OpenProcessByName("hid", &processHandle); + static bool hidPatched = false; + static bool irPatched = false; if(R_SUCCEEDED(res)) { @@ -182,11 +228,12 @@ Result InputRedirection_DoOrUndoPatches(void) static u32 *hidRegPatchOffsets[2]; static u32 *hidPatchJumpLoc; - if(inputRedirectionEnabled) + if(hidPatched) { memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode)); + hidPatched = false; } else { @@ -227,6 +274,7 @@ Result InputRedirection_DoOrUndoPatches(void) *off = *off2 = hidDataPhys; memcpy(off3, &hidHook, sizeof(hidHook)); + hidPatched = true; } } @@ -235,7 +283,7 @@ Result InputRedirection_DoOrUndoPatches(void) svcCloseHandle(processHandle); res = OpenProcessByName("ir", &processHandle); - if(R_SUCCEEDED(res) && osGetKernelVersion() >= SYSTEM_VERSION(2, 44, 6)) + if(R_SUCCEEDED(res) && GET_VERSION_MINOR(osGetKernelVersion()) >= 44) { svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); // only patch .text + .data svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003); @@ -273,7 +321,7 @@ Result InputRedirection_DoOrUndoPatches(void) static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc; - if(inputRedirectionEnabled) + if(irPatched) { memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode)); if(useOldSyncCode) @@ -281,6 +329,8 @@ Result InputRedirection_DoOrUndoPatches(void) else memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode)); memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode)); + + irPatched = false; } else { @@ -324,7 +374,7 @@ Result InputRedirection_DoOrUndoPatches(void) return -6; } - *(void **)(irCodePhys + 8) = decodeARMBranch(off + 4); + *(void **)(irCodePhys + 8) = decodeArmBranch(off + 4); *(void **)(irCodePhys + 12) = (void*)irDataPhys; irHookLoc = off; @@ -340,6 +390,8 @@ Result InputRedirection_DoOrUndoPatches(void) // This NOPs out a flag check in ir:user's CPP emulation *irCppFlagLoc = 0xE3150000; // tst r5, #0 + + irPatched = true; } } diff --git a/sysmodules/rosalina/source/input_redirection_hooks.s b/sysmodules/rosalina/source/input_redirection_hooks.s index 4ab487c..9cf6bea 100644 --- a/sysmodules/rosalina/source/input_redirection_hooks.s +++ b/sysmodules/rosalina/source/input_redirection_hooks.s @@ -1,5 +1,5 @@ @ This file is part of Luma3DS -@ Copyright (C) 2016-2019 Aurora Wright, TuxSH +@ 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 diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index 4775ba5..dbb2664 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,93 +33,53 @@ #include "3dsx.h" #include "utils.h" #include "MyThread.h" -#include "menus/process_patches.h" #include "menus/miscellaneous.h" #include "plgloader.h" #include "menus/debugger.h" #include "menus/screen_filters.h" +#include "menus/cheats.h" +#include "menus/sysconfig.h" +#include "input_redirection.h" +#include "minisoc.h" +#include "draw.h" #include "task_runner.h" -static Result stealFsReg(void) -{ - Result ret = 0; - - ret = svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, fsRegGetSessionHandle(), "fs:REG"); - while(ret == 0x9401BFE) - { - svcSleepThread(500 * 1000LL); - ret = svcControlService(SERVICEOP_STEAL_CLIENT_SESSION, fsRegGetSessionHandle(), "fs:REG"); - } - - return ret; -} - -static Result fsRegSetupPermissions(void) -{ - u32 pid; - Result res; - FS_ProgramInfo info; - - ExHeader_Arm11StorageInfo storageInfo = { - .fs_access_info = FSACCESS_NANDRO_RW | FSACCESS_NANDRW | FSACCESS_SDMC_RW, - }; - - info.programId = 0x0004013000006902LL; // Rosalina TID - info.mediaType = MEDIATYPE_NAND; - - if(R_SUCCEEDED(res = svcGetProcessId(&pid, CUR_PROCESS_HANDLE))) - res = FSREG_Register(pid, 0xFFFF000000000000LL, &info, &storageInfo); - - return res; -} - -// this is called before main bool isN3DS; -void __appInit() -{ - Result res; - for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) - { - res = srvInit(); - if(R_FAILED(res) && res != (Result)0xD88007FA) - svcBreak(USERBREAK_PANIC); - } - - if (R_FAILED(stealFsReg()) || R_FAILED(fsRegSetupPermissions()) || R_FAILED(fsInit())) - svcBreak(USERBREAK_PANIC); - - if (R_FAILED(pmDbgInit())) - svcBreak(USERBREAK_PANIC); -} - -// this is called after main exits -void __appExit() -{ - pmDbgExit(); - fsExit(); - svcCloseHandle(*fsRegGetSessionHandle()); - srvExit(); -} - Result __sync_init(void); Result __sync_fini(void); void __libc_init_array(void); void __libc_fini_array(void); -void __ctru_exit() +void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error + +// this is called after main exits +void __wrap_exit(int rc) { + (void)rc; + // TODO: make pm terminate rosalina __libc_fini_array(); - __appExit(); - __sync_fini(); + + // Kernel will take care of it all + /* + pmDbgExit(); + fsExit(); + svcCloseHandle(*fsRegGetSessionHandle()); + srvExit(); + __sync_fini();*/ + svcExitProcess(); } - -void initSystem() +// this is called before main +void initSystem(void) { s64 out; + Result res; + __sync_init(); + mappableInit(0x10000000, 0x14000000); + isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0; svcGetSystemInfo(&out, 0x10000, 0x100); @@ -131,50 +91,100 @@ void initSystem() miscellaneousMenu.items[0].title = HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID ? "Switch the hb. title to the current app." : "Switch the hb. title to hblauncher_loader"; - ProcessPatchesMenu_PatchUnpatchFSDirectly(); - __sync_init(); - __appInit(); + for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) + { + res = srvInit(); + if(R_FAILED(res) && res != (Result)0xD88007FA) + svcBreak(USERBREAK_PANIC); + } + + if (R_FAILED(pmAppInit()) || R_FAILED(pmDbgInit())) + svcBreak(USERBREAK_PANIC); + + if (R_FAILED(fsInit())) + svcBreak(USERBREAK_PANIC); + + // **** DO NOT init services that don't come from KIPs here **** + // Instead, init the service only where it's actually init (then deinit it). + __libc_init_array(); - // ROSALINA HACKJOB BEGIN - // NORMAL APPS SHOULD NOT DO THIS, EVER - u32 *tls = (u32 *)getThreadLocalStorage(); - memset(tls, 0, 0x80); - tls[0] = 0x21545624; // ROSALINA HACKJOB END // Rosalina specific: + u32 *tls = (u32 *)getThreadLocalStorage(); + memset(tls, 0, 0x80); + tls[0] = 0x21545624; + + // ROSALINA HACKJOB BEGIN + // NORMAL APPS SHOULD NOT DO THIS, EVER srvSetBlockingPolicy(true); // GetServiceHandle nonblocking if service port is full } -bool terminationRequest = false; -Handle terminationRequestEvent; +bool menuShouldExit = false; +bool preTerminationRequested = false; +Handle preTerminationEvent; +extern bool isHidInitialized; static void handleTermNotification(u32 notificationId) { (void)notificationId; +} + +static void handlePreTermNotification(u32 notificationId) +{ + (void)notificationId; + // Might be subject to a race condition, but heh. + + // Disable input redirection + InputRedirection_Disable(100 * 1000 * 1000LL); + + // Ask the debugger to terminate in approx 2 * 100ms + debuggerDisable(100 * 1000 * 1000LL); + + // Kill the ac session if needed + if(isConnectionForced) + { + acExit(); + isConnectionForced = false; + SysConfigMenu_UpdateStatus(true); + } + + Draw_Lock(); + if (isHidInitialized) + hidExit(); + // Termination request - terminationRequest = true; - svcSignalEvent(terminationRequestEvent); + menuShouldExit = true; + preTerminationRequested = true; + svcSignalEvent(preTerminationEvent); + Draw_Unlock(); } static void handleNextApplicationDebuggedByForce(u32 notificationId) { - int dummy; (void)notificationId; // Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread. - TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, &dummy, 0); + TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, NULL, 0); +} + +static void handleRestartHbAppNotification(u32 notificationId) +{ + (void)notificationId; + TaskRunner_RunTask(HBLDR_RestartHbApplication, NULL, 0); } static const ServiceManagerServiceEntry services[] = { - { "err:f", 1, ERRF_HandleCommands, true }, { "hb:ldr", 2, HBLDR_HandleCommands, true }, { NULL }, }; static const ServiceManagerNotificationEntry notifications[] = { { 0x100 , handleTermNotification }, + //{ 0x103 , handlePreTermNotification }, // Sleep mode entry <=== causes issues { 0x1000, handleNextApplicationDebuggedByForce }, + { 0x2000, handlePreTermNotification }, + { 0x3000, handleRestartHbAppNotification }, { 0x000, NULL }, }; @@ -190,9 +200,12 @@ int main(void) bufPtrs[2] = IPC_Desc_StaticBuffer(sizeof(ldrArgvBuf), 1); bufPtrs[3] = (u32)ldrArgvBuf; - if(R_FAILED(svcCreateEvent(&terminationRequestEvent, RESET_STICKY))) + if(R_FAILED(svcCreateEvent(&preTerminationEvent, RESET_STICKY))) svcBreak(USERBREAK_ASSERT); + Draw_Init(); + Cheat_SeedRng(svcGetSystemTick()); + MyThread *menuThread = menuCreateThread(); MyThread *taskRunnerThread = taskRunnerCreateThread(); MyThread *plgloaderThread = PluginLoader__CreateThread(); diff --git a/sysmodules/rosalina/source/memory.c b/sysmodules/rosalina/source/memory.c index aa96d76..834899a 100644 --- a/sysmodules/rosalina/source/memory.c +++ b/sysmodules/rosalina/source/memory.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index 163afae..8159955 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -37,66 +37,85 @@ #include "menus/cheats.h" #include "minisoc.h" -u32 waitInputWithTimeout(u32 msec) +bool isHidInitialized = false; + +// libctru redefinition: + +bool hidShouldUseIrrst(void) { - bool pressedKey = false; - u32 key = 0; - u32 n = 0; + // ir:rst exposes only two sessions :( + return false; +} - //Wait for no keys to be pressed - while(HID_PAD && !terminationRequest && (msec == 0 || n < msec)) - { - svcSleepThread(1 * 1000 * 1000LL); - n++; - } +static inline u32 convertHidKeys(u32 keys) +{ + // Nothing to do yet + return keys; +} - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; +u32 waitInputWithTimeout(s32 msec) +{ + s32 n = 0; + u32 keys; do { - //Wait for a key to be pressed - while(!HID_PAD && !terminationRequest && (msec == 0 || n < msec)) + svcSleepThread(1 * 1000 * 1000LL); + Draw_Lock(); + if (!isHidInitialized || menuShouldExit) { - svcSleepThread(1 * 1000 * 1000LL); - n++; + keys = 0; + Draw_Unlock(); + break; } + n++; - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; + hidScanInput(); + keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS); + Draw_Unlock(); + } while (keys == 0 && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec)); - key = HID_PAD; - //Make sure it's pressed - for(u32 i = 0x26000; i > 0; i --) - { - if(key != HID_PAD) break; - if(i == 1) pressedKey = true; - } - } - while(!pressedKey); - - return key; + return keys; } u32 waitInput(void) { - return waitInputWithTimeout(0); + return waitInputWithTimeout(-1); } -u32 waitComboWithTimeout(u32 msec) +static u32 scanHeldKeys(void) { - u32 key = 0; - u32 n = 0; + u32 keys; - //Wait for no keys to be pressed - while(HID_PAD && !terminationRequest && (msec == 0 || n < msec)) + Draw_Lock(); + + if (!isHidInitialized || menuShouldExit) + keys = 0; + else + { + hidScanInput(); + keys = convertHidKeys(hidKeysHeld()); + } + + Draw_Unlock(); + return keys; +} + +u32 waitComboWithTimeout(s32 msec) +{ + s32 n = 0; + u32 keys = 0; + u32 tempKeys = 0; + + // Wait for nothing to be pressed + while (scanHeldKeys() != 0 && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec)) { svcSleepThread(1 * 1000 * 1000LL); n++; } - if(terminationRequest || (msec != 0 && n >= msec)) + if (menuShouldExit || !isHidInitialized || !(msec < 0 || n < msec)) return 0; do @@ -104,32 +123,51 @@ u32 waitComboWithTimeout(u32 msec) svcSleepThread(1 * 1000 * 1000LL); n++; - u32 tempKey = HID_PAD; + tempKeys = scanHeldKeys(); - for(u32 i = 0x26000; i > 0; i--) + for (u32 i = 0x10000; i > 0; i--) { - if(tempKey != HID_PAD) break; - if(i == 1) key = tempKey; + if (tempKeys != scanHeldKeys()) break; + if (i == 1) keys = tempKeys; } } - while((!key || HID_PAD) && !terminationRequest && (msec == 0 || n < msec)); + while((keys == 0 || scanHeldKeys() != 0) && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec)); - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; - - return key; + return keys; } u32 waitCombo(void) { - return waitComboWithTimeout(0); + return waitComboWithTimeout(-1); } static MyThread menuThread; -static u8 ALIGN(8) menuThreadStack[0x3000]; +static u8 ALIGN(8) menuThreadStack[0x1000]; static u8 batteryLevel = 255; static u32 homeBtnPressed = 0; +static inline u32 menuAdvanceCursor(u32 pos, u32 numItems, s32 displ) +{ + return (pos + numItems + displ) % numItems; +} + +static inline bool menuItemIsHidden(const MenuItem *item) +{ + return item->visibility != NULL && !item->visibility(); +} + +bool menuCheckN3ds(void) +{ + return isN3DS; +} + +u32 menuCountItems(const Menu *menu) +{ + u32 n; + for (n = 0; menu->items[n].action_type != MENU_END; n++); + return n; +} + MyThread *menuCreateThread(void) { svcKernelSetState(0x10007, &homeBtnPressed); @@ -138,31 +176,25 @@ MyThread *menuCreateThread(void) return &menuThread; } -extern bool isN3DS; u32 menuCombo; u32 DispWarningOnHome(void); void menuThreadMain(void) { - if(!isN3DS) - { - rosalinaMenu.nbItems--; - for(u32 i = 0; i <= rosalinaMenu.nbItems; i++) - rosalinaMenu.items[i] = rosalinaMenu.items[i+1]; - } - else + if(isN3DS) N3DSMenu_UpdateStatus(); - bool isAcURegistered = false; + while (!isServiceUsable("ac:u") || !isServiceUsable("hid:USER")) + svcSleepThread(500 * 1000 * 1000LL); - while(!terminationRequest) + hidInit(); // assume this doesn't fail + isHidInitialized = true; + + while(!preTerminationRequested) { - if((HID_PAD & menuCombo) == menuCombo) - { - if (!isAcURegistered) - isAcURegistered = R_SUCCEEDED(srvIsServiceRegistered(&isAcURegistered, "ac:u")) - && isAcURegistered; + if (menuShouldExit) + continue; else { @@ -175,7 +207,10 @@ void menuThreadMain(void) } else { - Cheat_ApplyCheats(); + menuEnter(); + if(isN3DS) N3DSMenu_UpdateStatus(); + menuShow(&rosalinaMenu); + menuLeave(); } // Check for home button on O3DS Mode3 with plugin loaded @@ -194,27 +229,37 @@ void menuThreadMain(void) static s32 menuRefCount = 0; void menuEnter(void) { - if(AtomicPostIncrement(&menuRefCount) == 0) + Draw_Lock(); + if(!menuShouldExit && menuRefCount == 0) { + menuRefCount++; svcKernelSetState(0x10000, 1); svcSleepThread(5 * 1000 * 100LL); + if (Draw_AllocateFramebufferCache() == 0) + { + // Oops + menuRefCount = 0; + svcKernelSetState(0x10000, 1); + svcSleepThread(5 * 1000 * 100LL); + } + Draw_SetupFramebuffer(); - Draw_ClearFramebuffer(); } + Draw_Unlock(); } void menuLeave(void) { svcSleepThread(50 * 1000 * 1000); - if(AtomicDecrement(&menuRefCount) == 0) + Draw_Lock(); + if(--menuRefCount == 0) { - Draw_Lock(); - Draw_FlushFramebuffer(); Draw_RestoreFramebuffer(); - Draw_Unlock(); + Draw_FreeFramebufferCache(); svcKernelSetState(0x10000, 1); } + Draw_Unlock(); } static void menuDraw(Menu *menu, u32 selected) @@ -249,19 +294,23 @@ static void menuDraw(Menu *menu, u32 selected) sprintf(versionString, "v%lu.%lu.%lu", GET_VERSION_MAJOR(version), GET_VERSION_MINOR(version), GET_VERSION_REVISION(version)); Draw_DrawString(10, 10, COLOR_TITLE, menu->title); + u32 numItems = menuCountItems(menu); + u32 dispY = 0; - for(u32 i = 0; i < 15; i++) + for(u32 i = 0; i < numItems; i++) { - if(i >= menu->nbItems) - break; - Draw_DrawString(30, 30 + i * SPACING_Y, COLOR_WHITE, menu->items[i].title); - Draw_DrawCharacter(10, 30 + i * SPACING_Y, COLOR_TITLE, i == selected ? '>' : ' '); + if (menuItemIsHidden(&menu->items[i])) + continue; + + Draw_DrawString(30, 30 + dispY, COLOR_WHITE, menu->items[i].title); + Draw_DrawCharacter(10, 30 + dispY, COLOR_TITLE, i == selected ? '>' : ' '); + dispY += SPACING_Y; } if(miniSocEnabled) { char ipBuffer[17]; - u32 ip = gethostid(); + u32 ip = socGethostid(); u8 *addr = (u8 *)&ip; int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]); Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer); @@ -290,17 +339,33 @@ void menuShow(Menu *root) Menu *previousMenus[0x80]; u32 previousSelectedItems[0x80]; + u32 numItems = menuCountItems(currentMenu); + if (menuItemIsHidden(¤tMenu->items[selectedItem])) + selectedItem = menuAdvanceCursor(selectedItem, numItems, 1); + Draw_Lock(); Draw_ClearFramebuffer(); Draw_FlushFramebuffer(); + hidSetRepeatParameters(0, 0); menuDraw(currentMenu, selectedItem); Draw_Unlock(); + bool menuComboReleased = false; + do { u32 pressed = waitInputWithTimeout(1000); + numItems = menuCountItems(currentMenu); - if(pressed & BUTTON_A) + if(!menuComboReleased && (scanHeldKeys() & menuCombo) != menuCombo) + { + menuComboReleased = true; + Draw_Lock(); + hidSetRepeatParameters(200, 100); + Draw_Unlock(); + } + + if(pressed & KEY_A) { Draw_Lock(); Draw_ClearFramebuffer(); @@ -319,6 +384,9 @@ void menuShow(Menu *root) currentMenu = currentMenu->items[selectedItem].menu; selectedItem = 0; break; + default: + __builtin_trap(); // oops + break; } Draw_Lock(); @@ -326,7 +394,7 @@ void menuShow(Menu *root) Draw_FlushFramebuffer(); Draw_Unlock(); } - else if(pressed & BUTTON_B) + else if(pressed & KEY_B) { Draw_Lock(); Draw_ClearFramebuffer(); @@ -341,22 +409,24 @@ void menuShow(Menu *root) else break; } - else if(pressed & BUTTON_DOWN) + else if(pressed & KEY_DOWN) { - if(++selectedItem >= currentMenu->nbItems) - selectedItem = 0; + selectedItem = menuAdvanceCursor(selectedItem, numItems, 1); + if (menuItemIsHidden(¤tMenu->items[selectedItem])) + selectedItem = menuAdvanceCursor(selectedItem, numItems, 1); } - else if(pressed & BUTTON_UP) + else if(pressed & KEY_UP) { - if(selectedItem-- <= 0) - selectedItem = currentMenu->nbItems - 1; + selectedItem = menuAdvanceCursor(selectedItem, numItems, -1); + if (menuItemIsHidden(¤tMenu->items[selectedItem])) + selectedItem = menuAdvanceCursor(selectedItem, numItems, -1); } Draw_Lock(); menuDraw(currentMenu, selectedItem); Draw_Unlock(); } - while(!terminationRequest); + while(!menuShouldExit); } static const char *__press_b_to_close = "Press [B] to close"; diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index 394bc52..5e28143 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -30,7 +30,6 @@ #include "menu.h" #include "draw.h" #include "menus/process_list.h" -#include "menus/process_patches.h" #include "menus/n3ds.h" #include "menus/debugger.h" #include "menus/miscellaneous.h" @@ -40,19 +39,20 @@ #include "ifile.h" #include "memory.h" #include "fmt.h" +#include "process_patches.h" Menu rosalinaMenu = { "Rosalina menu", - .nbItems = 11, { - { "New 3DS menu...", MENU, .menu = &N3DSMenu }, + { "Take screenshot", METHOD, .method = &RosalinaMenu_TakeScreenshot }, + { "Change screen brightness", METHOD, .method = &RosalinaMenu_ChangeScreenBrightness }, { "Cheats...", METHOD, .method = &RosalinaMenu_Cheats }, { "", METHOD, .method = PluginLoader__MenuCallback}, { "Process list", METHOD, .method = &RosalinaMenu_ProcessList }, - { "Take screenshot (slow!)", METHOD, .method = &RosalinaMenu_TakeScreenshot }, { "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 }, { "Power off", METHOD, .method = &RosalinaMenu_PowerOff }, { "Reboot", METHOD, .method = &RosalinaMenu_Reboot }, @@ -60,6 +60,39 @@ Menu rosalinaMenu = { } }; +bool rosalinaMenuShouldShowDebugInfo(void) +{ + return true; +} + +void RosalinaMenu_ShowDebugInfo(void) +{ + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + char memoryMap[512]; + formatMemoryMapOfProcess(memoryMap, 511, CUR_PROCESS_HANDLE); + + s64 kextAddrSize; + svcGetSystemInfo(&kextAddrSize, 0x10000, 0x300); + u32 kextPa = (u32)((u64)kextAddrSize >> 32); + u32 kextSize = (u32)kextAddrSize; + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina -- Debug info"); + + u32 posY = Draw_DrawString(10, 30, COLOR_WHITE, memoryMap); + Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Kernel ext PA: %08lx - %08lx\n", kextPa, kextPa + kextSize); + Draw_FlushFramebuffer(); + Draw_Unlock(); + } + while(!(waitInput() & KEY_B) && !menuShouldExit); +} + void RosalinaMenu_ShowCredits(void) { Draw_Lock(); @@ -72,7 +105,7 @@ void RosalinaMenu_ShowCredits(void) Draw_Lock(); Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina -- Luma3DS credits"); - u32 posY = Draw_DrawString(10, 30, COLOR_WHITE, "Luma3DS (c) 2016-2019 AuroraWright, TuxSH") + SPACING_Y; + u32 posY = Draw_DrawString(10, 30, COLOR_WHITE, "Luma3DS (c) 2016-2020 AuroraWright, TuxSH") + SPACING_Y; posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "3DSX loading code by fincs"); posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "Networking code & basic GDB functionality by Stary"); @@ -91,7 +124,7 @@ void RosalinaMenu_ShowCredits(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } void RosalinaMenu_Reboot(void) @@ -111,14 +144,118 @@ void RosalinaMenu_Reboot(void) u32 pressed = waitInputWithTimeout(1000); - if(pressed & BUTTON_A) + if(pressed & KEY_A) { - APT_HardwareResetAsync(); menuLeave(); - } else if(pressed & BUTTON_B) + APT_HardwareResetAsync(); + return; + } else if(pressed & KEY_B) return; } - while(!terminationRequest); + while(!menuShouldExit); +} + +static u32 gspPatchAddrN3ds, gspPatchValuesN3ds[2]; +static bool gspPatchDoneN3ds; + +static Result RosalinaMenu_PatchN3dsGspForBrightness(u32 size) +{ + u32 *off = (u32 *)0x00100000; + u32 *end = (u32 *)(0x00100000 + size); + + for (; off < end && (off[0] != 0xE92D4030 || off[1] != 0xE1A04000 || off[2] != 0xE2805C01 || off[3] != 0xE5D0018C); off++); + + if (off >= end) { + return -1; + } + + gspPatchAddrN3ds = (u32)off; + gspPatchValuesN3ds[0] = off[26]; + gspPatchValuesN3ds[1] = off[50]; + + // NOP brightness changing in GSP + off[26] = 0xE1A00000; + off[50] = 0xE1A00000; + + return 0; +} +static Result RosalinaMenu_RevertN3dsGspPatch(u32 size) +{ + (void)size; + + u32 *off = (u32 *)gspPatchAddrN3ds; + off[26] = gspPatchValuesN3ds[0]; + off[50] = gspPatchValuesN3ds[1]; + + return 0; +} + +void RosalinaMenu_ChangeScreenBrightness(void) +{ + Result patchResult = 0; + if (isN3DS && !gspPatchDoneN3ds) + { + patchResult = PatchProcessByName("gsp", RosalinaMenu_PatchN3dsGspForBrightness); + gspPatchDoneN3ds = R_SUCCEEDED(patchResult); + } + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + // Assume the current brightness for both screens are the same. + s32 brightness = (s32)(LCD_TOP_BRIGHTNESS & 0xFF); + + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu"); + u32 posY = 30; + posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Current brightness (0..255): %3lu\n\n", brightness); + if (R_SUCCEEDED(patchResult)) + { + posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Up/Down for +-1, Right/Left for +-10.\n"); + posY = Draw_DrawString(10, posY, COLOR_WHITE, "Press Y to revert the GSP patch and exit.\n\n"); + + posY = Draw_DrawString(10, posY, COLOR_RED, "WARNING: \n"); + posY = Draw_DrawString(10, posY, COLOR_WHITE, " * avoid using values far higher than the presets.\n"); + posY = Draw_DrawString(10, posY, COLOR_WHITE, " * normal brightness mngmt. is now broken on N3DS.\nYou'll need to press Y to revert"); + } + else + Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Failed to patch GSP (0x%08lx).", (u32)patchResult); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if ((pressed & DIRECTIONAL_KEYS) && R_SUCCEEDED(patchResult)) + { + if (pressed & KEY_UP) + brightness += 1; + else if (pressed & KEY_DOWN) + brightness -= 1; + else if (pressed & KEY_RIGHT) + brightness += 10; + else if (pressed & KEY_LEFT) + brightness -= 10; + + brightness = brightness < 0 ? 0 : brightness; + brightness = brightness > 255 ? 255 : brightness; + LCD_TOP_BRIGHTNESS = (u32)brightness; + LCD_BOT_BRIGHTNESS = (u32)brightness; + } + else if ((pressed & KEY_Y) && gspPatchDoneN3ds) + { + patchResult = PatchProcessByName("gsp", RosalinaMenu_RevertN3dsGspPatch); + gspPatchDoneN3ds = !R_SUCCEEDED(patchResult); + return; + } + else if (pressed & KEY_B) + return; + } + while (!menuShouldExit); } void RosalinaMenu_PowerOff(void) // Soft shutdown. @@ -138,25 +275,64 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown. u32 pressed = waitInputWithTimeout(1000); - if(pressed & BUTTON_A) + if(pressed & KEY_A) { menuLeave(); srvPublishToSubscriber(0x203, 0); + return; } - else if(pressed & BUTTON_B) + else if(pressed & KEY_B) return; } - while(!terminationRequest); + while(!menuShouldExit); } -extern u8 framebufferCache[FB_BOTTOM_SIZE]; -void RosalinaMenu_TakeScreenshot(void) -{ + #define TRY(expr) if(R_FAILED(res = (expr))) goto end; +static s64 timeSpentConvertingScreenshot = 0; +static s64 timeSpentWritingScreenshot = 0; + +static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left) +{ u64 total; + Result res = 0; + u32 dimX = top ? 400 : 320; + u32 lineSize = 3 * dimX; + u32 remaining = lineSize * 240; + u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); + u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize(); + + u8 *buf = framebufferCache; + Draw_CreateBitmapHeader(framebufferCache, dimX, 240); + buf += 54; + + u32 y = 0; + // Our buffer might be smaller than the size of the screenshot... + while (remaining != 0) + { + s64 t0 = svcGetSystemTick(); + u32 available = (u32)(framebufferCacheEnd - buf); + u32 size = available < remaining ? available : remaining; + u32 nlines = size / lineSize; + Draw_ConvertFrameBufferLines(buf, y, nlines, top, left); + + s64 t1 = svcGetSystemTick(); + timeSpentConvertingScreenshot += t1 - t0; + TRY(IFile_Write(file, &total, framebufferCache, (y == 0 ? 54 : 0) + lineSize * nlines, 0)); // don't forget to write the header + timeSpentWritingScreenshot += svcGetSystemTick() - t1; + + y += nlines; + remaining -= lineSize * nlines; + buf = framebufferCache; + } + end: return res; +} + +void RosalinaMenu_TakeScreenshot(void) +{ IFile file; - Result res; + Result res = 0; char filename[64]; @@ -165,6 +341,9 @@ void RosalinaMenu_TakeScreenshot(void) s64 out; bool isSdMode; + timeSpentConvertingScreenshot = 0; + timeSpentWritingScreenshot = 0; + if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT); isSdMode = (bool)out; @@ -228,49 +407,19 @@ void RosalinaMenu_TakeScreenshot(void) sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top.bmp", year, month, days, hours, minutes, seconds, milliseconds); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); - Draw_CreateBitmapHeader(framebufferCache, 400, 240); - - for(u32 y = 0; y < 120; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 400 * y, true, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 400 * 120, 0)); - - for(u32 y = 120; y < 240; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 3 * 400 * (y - 120), true, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 3 * 400 * 120, 0)); + TRY(RosalinaMenu_WriteScreenshot(&file, true, true)); TRY(IFile_Close(&file)); sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_bot.bmp", year, month, days, hours, minutes, seconds, milliseconds); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); - Draw_CreateBitmapHeader(framebufferCache, 320, 240); - - for(u32 y = 0; y < 120; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 320 * y, false, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 320 * 120, 0)); - - for(u32 y = 120; y < 240; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 3 * 320 * (y - 120), false, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 3 * 320 * 120, 0)); + TRY(RosalinaMenu_WriteScreenshot(&file, false, true)); TRY(IFile_Close(&file)); if((GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false))) { sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top_right.bmp", year, month, days, hours, minutes, seconds, milliseconds); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); - Draw_CreateBitmapHeader(framebufferCache, 400, 240); - - for(u32 y = 0; y < 120; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 400 * y, true, false, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 400 * 120, 0)); - - for(u32 y = 120; y < 240; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 3 * 400 * (y - 120), true, false, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 3 * 400 * 120, 0)); + TRY(RosalinaMenu_WriteScreenshot(&file, true, false)); TRY(IFile_Close(&file)); } @@ -278,8 +427,6 @@ end: IFile_Close(&file); svcFlushEntireDataCache(); Draw_SetupFramebuffer(); - Draw_ClearFramebuffer(); - Draw_FlushFramebuffer(); Draw_Unlock(); do @@ -289,12 +436,19 @@ end: if(R_FAILED(res)) Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Operation failed (0x%08lx).", (u32)res); else - Draw_DrawString(10, 30, COLOR_WHITE, "Operation succeeded."); + { + u32 t1 = (u32)(1000 * timeSpentConvertingScreenshot / SYSCLOCK_ARM11); + u32 t2 = (u32)(1000 * timeSpentWritingScreenshot / SYSCLOCK_ARM11); + u32 posY = 30; + posY = Draw_DrawString(10, posY, COLOR_WHITE, "Operation succeeded.\n\n"); + posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Time spent converting: %5lums\n", t1); + posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Time spent writing files: %5lums\n", t2); + } Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); #undef TRY } diff --git a/sysmodules/rosalina/source/menus/cheats.c b/sysmodules/rosalina/source/menus/cheats.c index 635ddc9..f313248 100644 --- a/sysmodules/rosalina/source/menus/cheats.c +++ b/sysmodules/rosalina/source/menus/cheats.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS - * Copyright (C) 2016-2019 Aurora Wright, TuxSH + * 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 @@ -33,16 +33,11 @@ #include "utils.h" #include "fmt.h" #include "ifile.h" +#include "pmdbgext.h" #define MAKE_QWORD(hi,low) \ ((u64) ((((u64)(hi)) << 32) | (low))) -typedef struct CheatProcessInfo -{ - u32 pid; - u64 titleId; -} CheatProcessInfo; - typedef struct CheatDescription { struct { @@ -70,36 +65,6 @@ CheatDescription* cheats[1024] = { 0 }; u8 cheatBuffer[32768] = { 0 }; u8 cheatPage[0x1000] = { 0 }; -static CheatProcessInfo cheatinfo[0x40] = { 0 }; - -static s32 Cheats_FetchProcessInfo(void) -{ - u32 pidList[0x40]; - s32 processAmount; - - s64 sa, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize; - - svcGetProcessList(&processAmount, pidList, 0x40); - - for (s32 i = 0; i < processAmount; i++) - { - Handle processHandle; - Result res = svcOpenProcess(&processHandle, pidList[i]); - if (R_FAILED(res)) continue; - - cheatinfo[i].pid = pidList[i]; - svcGetProcessInfo((s64 *) &cheatinfo[i].titleId, processHandle, 0x10001); - svcGetProcessInfo(&textTotalRoundedSize, processHandle, 0x10002); - svcGetProcessInfo(&rodataTotalRoundedSize, processHandle, 0x10003); - svcGetProcessInfo(&dataTotalRoundedSize, processHandle, 0x10004); - svcGetProcessInfo(&sa, processHandle, 0x10005); - - svcCloseHandle(processHandle); - } - - return processAmount; -} - typedef struct CheatState { u32 index; @@ -131,6 +96,7 @@ typedef struct CheatState CheatState cheat_state = { 0 }; u8 cheatCount = 0; u64 cheatTitleInfo = -1ULL; +u64 cheatRngState = 0; static inline u32* activeOffset() { @@ -149,6 +115,12 @@ static inline u32* activeStorage(CheatDescription* desc) char failureReason[64]; +static u32 Cheat_GetRandomNumber(void) +{ + cheatRngState = 0x5D588B656C078965ULL * cheatRngState + 0x0000000000269EC3ULL; + return (u32)(cheatRngState >> 32); +} + static bool Cheat_IsValidAddress(const Handle processHandle, u32 address, u32 size) { MemInfo info; @@ -168,7 +140,7 @@ static u8 ReadWriteBuffer8 = 0; static bool Cheat_Write8(const Handle processHandle, u32 offset, u8 value) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) + if (addr >= 0x01E81000 && addr < 0x01E82000) { cheatPage[addr - 0x01E81000] = value; return true; @@ -184,7 +156,7 @@ static bool Cheat_Write8(const Handle processHandle, u32 offset, u8 value) static bool Cheat_Write16(const Handle processHandle, u32 offset, u16 value) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 2 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) { *(u16*)(cheatPage + addr - 0x01E81000) = value; return true; @@ -200,7 +172,7 @@ static bool Cheat_Write16(const Handle processHandle, u32 offset, u16 value) static bool Cheat_Write32(const Handle processHandle, u32 offset, u32 value) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 4 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 3 < 0x01E82000) { *(u32*)(cheatPage + addr - 0x01E81000) = value; return true; @@ -216,7 +188,7 @@ static bool Cheat_Write32(const Handle processHandle, u32 offset, u32 value) static bool Cheat_Read8(const Handle processHandle, u32 offset, u8* retValue) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) + if (addr >= 0x01E81000 && addr < 0x01E82000) { *retValue = cheatPage[addr - 0x01E81000]; return true; @@ -233,7 +205,7 @@ static bool Cheat_Read8(const Handle processHandle, u32 offset, u8* retValue) static bool Cheat_Read16(const Handle processHandle, u32 offset, u16* retValue) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 2 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 1 < 0x01E82000) { *retValue = *(u16*)(cheatPage + addr - 0x01E81000); return true; @@ -250,7 +222,7 @@ static bool Cheat_Read16(const Handle processHandle, u32 offset, u16* retValue) static bool Cheat_Read32(const Handle processHandle, u32 offset, u32* retValue) { u32 addr = *activeOffset() + offset; - if (addr >= 0x01E81000 && addr + 4 < 0x01E82000) + if (addr >= 0x01E81000 && addr + 3 < 0x01E82000) { *retValue = *(u32*)(cheatPage + addr - 0x01E81000); return true; @@ -1512,7 +1484,7 @@ static u32 Cheat_ApplyCheat(const Handle processHandle, CheatDescription* const case 0xF: { u32 range = arg1 - (arg0 & 0xFFFFFF); - u32 number = rand() % range; + u32 number = Cheat_GetRandomNumber() % range; *activeData() = (arg0 & 0xFFFFFF) + number; } break; @@ -1886,33 +1858,24 @@ static void Cheat_LoadCheatsIntoMemory(u64 titleId) memset(cheatPage, 0, 0x1000); } -static u32 Cheat_GetCurrentPID(u64* titleId) +static u32 Cheat_GetCurrentProcessAndTitleId(u64* titleId) { - s32 processAmount = Cheats_FetchProcessInfo(); - - s32 index = -1; - - for (s32 i = 0; i < processAmount; i++) - { - - if (((u32) (cheatinfo[i].titleId >> 32)) == 0x00040010 || ((u32) (cheatinfo[i].titleId >> 32) == 0x00040000)) - { - index = i; - - break; - } - } - - if (index != -1) - { - *titleId = cheatinfo[index].titleId; - return cheatinfo[index].pid; - } - else - { + FS_ProgramInfo programInfo; + u32 pid; + u32 launchFlags; + Result res = PMDBG_GetCurrentAppInfo(&programInfo, &pid, &launchFlags); + if (R_FAILED(res)) { *titleId = 0; return 0xFFFFFFFF; } + + *titleId = programInfo.programId; + return pid; +} + +void Cheat_SeedRng(u64 seed) +{ + cheatRngState = seed; } void Cheat_ApplyCheats(void) @@ -1923,7 +1886,7 @@ void Cheat_ApplyCheats(void) } u64 titleId = 0; - u32 pid = Cheat_GetCurrentPID(&titleId); + u32 pid = Cheat_GetCurrentProcessAndTitleId(&titleId); if (!titleId) { @@ -1949,7 +1912,7 @@ void Cheat_ApplyCheats(void) void RosalinaMenu_Cheats(void) { u64 titleId = 0; - u32 pid = Cheat_GetCurrentPID(&titleId); + u32 pid = Cheat_GetCurrentProcessAndTitleId(&titleId); if (titleId != 0) { @@ -1981,7 +1944,7 @@ void RosalinaMenu_Cheats(void) Draw_FlushFramebuffer(); Draw_Unlock(); - } while (!(waitInput() & BUTTON_B) && !terminationRequest); + } while (!(waitInput() & KEY_B) && !menuShouldExit); } else { @@ -2019,18 +1982,18 @@ void RosalinaMenu_Cheats(void) Draw_FlushFramebuffer(); Draw_Unlock(); - if (terminationRequest) break; + if (menuShouldExit) break; u32 pressed; do { pressed = waitInputWithTimeout(50); if (pressed != 0) break; - } while (pressed == 0 && !terminationRequest); + } while (pressed == 0 && !menuShouldExit); - if (pressed & BUTTON_B) + if (pressed & KEY_B) break; - else if ((pressed & BUTTON_A) && R_SUCCEEDED(r)) + else if ((pressed & KEY_A) && R_SUCCEEDED(r)) { if (cheats[selected]->active) { @@ -2041,13 +2004,13 @@ void RosalinaMenu_Cheats(void) r = Cheat_MapMemoryAndApplyCheat(pid, cheats[selected]); } } - else if (pressed & BUTTON_DOWN) + else if (pressed & KEY_DOWN) selected++; - else if (pressed & BUTTON_UP) + else if (pressed & KEY_UP) selected--; - else if (pressed & BUTTON_LEFT) + else if (pressed & KEY_LEFT) selected -= CHEATS_PER_MENU_PAGE; - else if (pressed & BUTTON_RIGHT) + else if (pressed & KEY_RIGHT) { if (selected + CHEATS_PER_MENU_PAGE < cheatCount) selected += CHEATS_PER_MENU_PAGE; @@ -2062,7 +2025,7 @@ void RosalinaMenu_Cheats(void) pagePrev = page; page = selected / CHEATS_PER_MENU_PAGE; - } while (!terminationRequest); + } while (!menuShouldExit); } } diff --git a/sysmodules/rosalina/source/menus/debugger.c b/sysmodules/rosalina/source/menus/debugger.c index 9ffee39..70bf67a 100644 --- a/sysmodules/rosalina/source/menus/debugger.c +++ b/sysmodules/rosalina/source/menus/debugger.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -38,11 +38,11 @@ Menu debuggerMenu = { "Debugger options menu", - .nbItems = 3, { { "Enable debugger", METHOD, .method = &DebuggerMenu_EnableDebugger }, { "Disable debugger", METHOD, .method = &DebuggerMenu_DisableDebugger }, { "Force-debug next application at launch", METHOD, .method = &DebuggerMenu_DebugNextApplicationByForce }, + {}, } }; @@ -84,6 +84,30 @@ void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata) 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; + svcKernelSetState(0x10000, 2); + } + + return res; +} + void DebuggerMenu_EnableDebugger(void) { bool done = false, alreadyEnabled = gdbServer.super.running; @@ -115,16 +139,18 @@ void DebuggerMenu_EnableDebugger(void) 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 = svcWaitSynchronization(gdbServer.super.started_event, 10 * 1000 * 1000 * 1000LL); + 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) @@ -136,33 +162,16 @@ void DebuggerMenu_EnableDebugger(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } void DebuggerMenu_DisableDebugger(void) { bool initialized = gdbServer.referenceCount != 0; - Result res = 0; + + Result res = initialized ? debuggerDisable(2 * 1000 * 1000 * 1000LL) : 0; char buf[65]; - if(initialized) - { - svcSignalEvent(gdbServer.super.shall_terminate_event); - server_kill_connections(&gdbServer.super); - //server_set_should_close_all(&gdbServer.super); - - res = MyThread_Join(&debuggerDebugThread, 2 * 1000 * 1000 * 1000LL); - if(res == 0) - res = MyThread_Join(&debuggerSocketThread, 2 * 1000 * 1000 * 1000LL); - - Handle dummy = 0; - PMDBG_RunQueuedProcess(&dummy); - svcCloseHandle(dummy); - PMDBG_DebugNextApplicationByForce(false); - nextApplicationGdbCtx = NULL; - svcKernelSetState(0x10000, 2); - } - if(res != 0) sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res); @@ -174,7 +183,7 @@ void DebuggerMenu_DisableDebugger(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } void DebuggerMenu_DebugNextApplicationByForce(void) @@ -223,7 +232,7 @@ void DebuggerMenu_DebugNextApplicationByForce(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } void debuggerSocketThreadMain(void) diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 2b82d30..c4e66af 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -33,36 +33,37 @@ #include "hbloader.h" #include "plgloader.h" #include "fmt.h" -#include "utils.h" // for makeARMBranch +#include "utils.h" // for makeArmBranch #include "minisoc.h" #include "ifile.h" #include "pmdbgext.h" Menu miscellaneousMenu = { "Miscellaneous options menu", - .nbItems = 5, { { "Switch the hb. title to the current app.", METHOD, .method = &MiscellaneousMenu_SwitchBoot3dsxTargetTitle }, { "Change the menu combo", METHOD, .method = &MiscellaneousMenu_ChangeMenuCombo }, { "Start InputRedirection", METHOD, .method = &MiscellaneousMenu_InputRedirection }, { "Sync time and date via NTP", METHOD, .method = &MiscellaneousMenu_SyncTimeDate }, { "Save settings", METHOD, .method = &MiscellaneousMenu_SaveSettings }, + {}, } }; void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) { Result res; - u64 titleId = 0; char failureReason[64]; if(HBLDR_3DSX_TID == HBLDR_DEFAULT_3DSX_TID) { + FS_ProgramInfo progInfo; u32 pid; - res = PMDBG_GetCurrentAppTitleIdAndPid(&titleId, &pid); + u32 launchFlags; + res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags); if(R_SUCCEEDED(res)) { - HBLDR_3DSX_TID = titleId; + HBLDR_3DSX_TID = progInfo.programId; miscellaneousMenu.items[0].title = "Switch the hb. title to hblauncher_loader"; } else @@ -95,13 +96,25 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } static void MiscellaneousMenu_ConvertComboToString(char *out, u32 combo) { - static const char *keys[] = { "A", "B", "Select", "Start", "Right", "Left", "Up", "Down", "R", "L", "X", "Y" }; - for(s32 i = 11; i >= 0; i--) + static const char *keys[] = { + "A", "B", "Select", "Start", "Right", "Left", "Up", "Down", "R", "L", "X", "Y", + "?", "?", + "ZL", "ZR", + "?", "?", "?", "?", + "Touch", + "?", "?", "?", + "CStick Right", "CStick Left", "CStick Up", "CStick Down", + "CPad Right", "CPad Left", "CPad Up", "CPad Down", + }; + + char *outOrig = out; + out[0] = 0; + for(s32 i = 31; i >= 0; i--) { if(combo & (1 << i)) { @@ -111,12 +124,13 @@ static void MiscellaneousMenu_ConvertComboToString(char *out, u32 combo) } } - out[-1] = 0; + if (out != outOrig) + out[-1] = 0; } void MiscellaneousMenu_ChangeMenuCombo(void) { - char comboStrOrig[64], comboStr[64]; + char comboStrOrig[128], comboStr[128]; u32 posY; Draw_Lock(); @@ -132,9 +146,6 @@ void MiscellaneousMenu_ChangeMenuCombo(void) posY = Draw_DrawFormattedString(10, 30, COLOR_WHITE, "The current menu combo is: %s", comboStrOrig); posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "Please enter the new combo:"); - Draw_FlushFramebuffer(); - Draw_Unlock(); - menuCombo = waitCombo(); MiscellaneousMenu_ConvertComboToString(comboStr, menuCombo); @@ -151,7 +162,7 @@ void MiscellaneousMenu_ChangeMenuCombo(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } Result SaveSettings(void) @@ -228,12 +239,11 @@ void MiscellaneousMenu_SaveSettings(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } void MiscellaneousMenu_InputRedirection(void) { - static MyThread *inputRedirectionThread = NULL; bool done = false; Result res; @@ -243,11 +253,7 @@ void MiscellaneousMenu_InputRedirection(void) if(wasEnabled) { - res = InputRedirection_DoOrUndoPatches(); - inputRedirectionEnabled = false; - res = MyThread_Join(inputRedirectionThread, 5 * 1000 * 1000 * 1000LL); - svcCloseHandle(inputRedirectionThreadStartedEvent); - + res = InputRedirection_Disable(5 * 1000 * 1000 * 1000LL); if(res != 0) sprintf(buf, "Failed to stop InputRedirection (0x%08lx).", (u32)res); else @@ -294,13 +300,18 @@ void MiscellaneousMenu_InputRedirection(void) res = svcCreateEvent(&inputRedirectionThreadStartedEvent, RESET_STICKY); if(R_SUCCEEDED(res)) { - inputRedirectionThread = inputRedirectionCreateThread(); + inputRedirectionCreateThread(); res = svcWaitSynchronization(inputRedirectionThreadStartedEvent, 10 * 1000 * 1000 * 1000LL); if(res == 0) res = (Result)inputRedirectionStartResult; if(res != 0) + { + svcCloseHandle(inputRedirectionThreadStartedEvent); InputRedirection_DoOrUndoPatches(); + inputRedirectionEnabled = false; + } + inputRedirectionStartResult = 0; } } @@ -328,7 +339,7 @@ void MiscellaneousMenu_InputRedirection(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); } void MiscellaneousMenu_SyncTimeDate(void) @@ -342,12 +353,12 @@ void MiscellaneousMenu_SyncTimeDate(void) bool isSocURegistered; time_t t; - struct tm localt = {0}; res = srvIsServiceRegistered(&isSocURegistered, "soc:U"); cantStart = R_FAILED(res) || !isSocURegistered; int utcOffset = 12; + int utcOffsetMinute = 0; int absOffset; do { @@ -356,20 +367,21 @@ void MiscellaneousMenu_SyncTimeDate(void) absOffset = utcOffset - 12; absOffset = absOffset < 0 ? -absOffset : absOffset; - posY = Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Current UTC offset: %c%02d", utcOffset < 12 ? '-' : '+', absOffset); - posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Use DPAD Left/Right to change offset.\nPress A when done.") + SPACING_Y; + posY = Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Current UTC offset: %c%02d%02d", utcOffset < 12 ? '-' : '+', absOffset, utcOffsetMinute); + posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Use DPAD Left/Right to change hour offset.\nUse DPAD Up/Down to change minute offset.\nPress A when done.") + SPACING_Y; input = waitInput(); - if(input & BUTTON_LEFT) utcOffset = (24 + utcOffset - 1) % 24; // ensure utcOffset >= 0 - if(input & BUTTON_RIGHT) utcOffset = (utcOffset + 1) % 24; - + if(input & KEY_LEFT) utcOffset = (24 + utcOffset - 1) % 24; // ensure utcOffset >= 0 + if(input & KEY_RIGHT) utcOffset = (utcOffset + 1) % 24; + if(input & KEY_UP) utcOffsetMinute = (utcOffsetMinute + 1) % 60; + if(input & KEY_DOWN) utcOffsetMinute = (60 + utcOffsetMinute - 1) % 60; Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(input & (BUTTON_A | BUTTON_B)) && !terminationRequest); + while(!(input & (KEY_A | KEY_B)) && !menuShouldExit); - if (input & BUTTON_B) + if (input & KEY_B) return; utcOffset -= 12; @@ -383,8 +395,8 @@ void MiscellaneousMenu_SyncTimeDate(void) if(R_SUCCEEDED(res)) { t += 3600 * utcOffset; - gmtime_r(&t, &localt); - res = ntpSetTimeDate(&localt); + t += 60 * utcOffsetMinute; + res = ntpSetTimeDate(t); } } @@ -408,6 +420,6 @@ void MiscellaneousMenu_SyncTimeDate(void) Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(input & BUTTON_B) && !terminationRequest); + while(!(input & KEY_B) && !menuShouldExit); -} \ No newline at end of file +} diff --git a/sysmodules/rosalina/source/menus/n3ds.c b/sysmodules/rosalina/source/menus/n3ds.c index 1a44844..9f90034 100644 --- a/sysmodules/rosalina/source/menus/n3ds.c +++ b/sysmodules/rosalina/source/menus/n3ds.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -34,10 +34,10 @@ static char clkRateBuf[128 + 1]; Menu N3DSMenu = { "New 3DS menu", - .nbItems = 2, { { "Enable L2 cache", METHOD, .method = &N3DSMenu_EnableDisableL2Cache }, - { clkRateBuf, METHOD, .method = &N3DSMenu_ChangeClockRate } + { clkRateBuf, METHOD, .method = &N3DSMenu_ChangeClockRate }, + {}, } }; diff --git a/sysmodules/rosalina/source/menus/process_list.c b/sysmodules/rosalina/source/menus/process_list.c index 0b53317..afd7eda 100644 --- a/sysmodules/rosalina/source/menus/process_list.c +++ b/sysmodules/rosalina/source/menus/process_list.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -26,6 +26,7 @@ #include <3ds.h> #include "menus/process_list.h" +#include "process_patches.h" #include "memory.h" #include "csvc.h" #include "draw.h" @@ -104,7 +105,7 @@ static void ProcessListMenu_DumpMemory(const char *name, void *start, u32 size) IFile file; Result res; - char filename[64] = {0}; + char filename[100] = {0}; FS_Archive archive; FS_ArchiveID archiveId; @@ -197,7 +198,7 @@ end: Draw_FlushFramebuffer(); Draw_Unlock(); } - while(!(waitInput() & BUTTON_B) && !terminationRequest); + while(!(waitInput() & KEY_B) && !menuShouldExit); #undef TRY } @@ -493,21 +494,21 @@ static void ProcessListMenu_MemoryViewer(const ProcessInfo *info) u32 pressed = waitInputWithTimeout(1000); - if(pressed & BUTTON_A) + if(pressed & KEY_A) editing = !editing; - else if(pressed & BUTTON_X) + else if(pressed & KEY_X) { if(checkMode(MENU_MODE_GOTO)) finishJumping(); else gotoAddress = __builtin_bswap32(((u32)menus[MENU_MODE_NORMAL].buf) + menus[MENU_MODE_NORMAL].selected); } - else if(pressed & BUTTON_Y) + else if(pressed & KEY_Y) { if(checkMode(MENU_MODE_SEARCH)) finishSearching(); } - else if(pressed & BUTTON_SELECT) + else if(pressed & KEY_SELECT) { clearMenu(); ProcessListMenu_DumpMemory(info->name, menus[MENU_MODE_NORMAL].buf, menus[MENU_MODE_NORMAL].max); @@ -517,35 +518,35 @@ static void ProcessListMenu_MemoryViewer(const ProcessInfo *info) if(editing) { // Edit the highlighted byte - if(pressed & BUTTON_LEFT) + if(pressed & KEY_LEFT) selectedByteAdd0x10(); - else if(pressed & BUTTON_RIGHT) + else if(pressed & KEY_RIGHT) selectedByteSub0x10(); - else if(pressed & BUTTON_UP) + else if(pressed & KEY_UP) selectedByteIncrement(); - else if(pressed & BUTTON_DOWN) + else if(pressed & KEY_DOWN) selectedByteDecrement(); } else { // Move the cursor - if(pressed & BUTTON_LEFT) + if(pressed & KEY_LEFT) selectedMoveLeft(); - else if(pressed & BUTTON_RIGHT) + else if(pressed & KEY_RIGHT) selectedMoveRight(); - else if(pressed & BUTTON_UP) + else if(pressed & KEY_UP) selectedMoveUp(); - else if(pressed & BUTTON_DOWN) + else if(pressed & KEY_DOWN) selectedMoveDown(); - else if(pressed & BUTTON_L1) + else if(pressed & KEY_L) { if(menuMode == MENU_MODE_NORMAL) viewHeap(); else if(menuMode == MENU_MODE_SEARCH) searchPatternReduce(); } - else if(pressed & BUTTON_R1) + else if(pressed & KEY_R) { if(menuMode == MENU_MODE_NORMAL) viewCode(); @@ -554,7 +555,7 @@ static void ProcessListMenu_MemoryViewer(const ProcessInfo *info) } } - if(pressed & BUTTON_B) // go back to the list, or the simple viewer + if(pressed & KEY_B) // go back to the list, or the simple viewer { if(menuMode != MENU_MODE_NORMAL) { @@ -568,7 +569,7 @@ static void ProcessListMenu_MemoryViewer(const ProcessInfo *info) if(menus[menuMode].selected >= menus[menuMode].max) menus[menuMode].selected = menus[menuMode].max - 1; } - while(!terminationRequest); + while(!menuShouldExit); clearMenu(); } @@ -666,7 +667,7 @@ void RosalinaMenu_ProcessList(void) if(gdbServer.super.running) { char ipBuffer[17]; - u32 ip = gethostid(); + u32 ip = socGethostid(); u8 *addr = (u8 *)&ip; int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]); Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer); @@ -685,7 +686,7 @@ void RosalinaMenu_ProcessList(void) Draw_FlushFramebuffer(); Draw_Unlock(); - if(terminationRequest) + if(menuShouldExit) break; u32 pressed; @@ -698,19 +699,19 @@ void RosalinaMenu_ProcessList(void) if(memcmp(infos, infosPrev, sizeof(infos)) != 0) break; } - while(pressed == 0 && !terminationRequest); + while(pressed == 0 && !menuShouldExit); - if(pressed & BUTTON_B) + if(pressed & KEY_B) break; - else if(pressed & BUTTON_A) + else if(pressed & KEY_A) ProcessListMenu_HandleSelected(&infos[selected]); - else if(pressed & BUTTON_DOWN) + else if(pressed & KEY_DOWN) selected++; - else if(pressed & BUTTON_UP) + else if(pressed & KEY_UP) selected--; - else if(pressed & BUTTON_LEFT) + else if(pressed & KEY_LEFT) selected -= PROCESSES_PER_MENU_PAGE; - else if(pressed & BUTTON_RIGHT) + else if(pressed & KEY_RIGHT) { if(selected + PROCESSES_PER_MENU_PAGE < processAmount) selected += PROCESSES_PER_MENU_PAGE; @@ -728,5 +729,5 @@ void RosalinaMenu_ProcessList(void) pagePrev = page; page = selected / PROCESSES_PER_MENU_PAGE; } - while(!terminationRequest); + while(!menuShouldExit); } diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index 53b4eb8..fc37285 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -55,42 +55,42 @@ typedef struct { u8 z; } Pixel; +static u16 g_c[0x600]; +static Pixel g_px[0x400]; + void applyColorSettings(color_setting_t* cs) { - u16 c[0x600]; - Pixel px[0x400]; u8 i = 0; - memset(c, 0, sizeof(c)); - memset(px, 0, sizeof(px)); + memset(g_c, 0, sizeof(g_c)); + memset(g_px, 0, sizeof(g_px)); do { - px[i].r = i; - px[i].g = i; - px[i].b = i; - px[i].z = 0; + g_px[i].r = i; + g_px[i].g = i; + g_px[i].b = i; + g_px[i].z = 0; } while(++i); do { - *(c + i + 0x000) = px[i].r | (px[i].r << 8); - *(c + i + 0x100) = px[i].g | (px[i].g << 8); - *(c + i + 0x200) = px[i].b | (px[i].b << 8); + *(g_c + i + 0x000) = g_px[i].r | (g_px[i].r << 8); + *(g_c + i + 0x100) = g_px[i].g | (g_px[i].g << 8); + *(g_c + i + 0x200) = g_px[i].b | (g_px[i].b << 8); } while(++i); - colorramp_fill(c + 0x000, c + 0x100, c + 0x200, 0x100, cs); + colorramp_fill(g_c + 0x000, g_c + 0x100, g_c + 0x200, 0x100, cs); do { - px[i].r = *(c + i + 0x000) >> 8; - px[i].g = *(c + i + 0x100) >> 8; - px[i].b = *(c + i + 0x200) >> 8; + g_px[i].r = *(g_c + i + 0x000) >> 8; + g_px[i].g = *(g_c + i + 0x100) >> 8; + g_px[i].b = *(g_c + i + 0x200) >> 8; } while(++i); - writeLut((u32*)px); + writeLut((u32*)g_px); } Menu screenFiltersMenu = { "Screen filters menu", - .nbItems = 6, { { "Disable", METHOD, .method = &screenFiltersSetDisabled }, { "Reduce blue light (level 1)", METHOD, .method = &screenFiltersReduceBlueLevel1 }, @@ -98,6 +98,7 @@ Menu screenFiltersMenu = { { "Reduce blue light (level 3)", METHOD, .method = &screenFiltersReduceBlueLevel3 }, { "Reduce blue light (level 4)", METHOD, .method = &screenFiltersReduceBlueLevel4 }, { "Reduce blue light (level 5)", METHOD, .method = &screenFiltersReduceBlueLevel5 }, + {}, } }; @@ -143,10 +144,10 @@ void screenFiltersSetTemperature(int temperature) memset(&cs, 0, sizeof(cs)); cs.temperature = temperature; - cs.gamma[0] = 1.0F; + /*cs.gamma[0] = 1.0F; cs.gamma[1] = 1.0F; cs.gamma[2] = 1.0F; - cs.brightness = 1.0F; + cs.brightness = 1.0F;*/ applyColorSettings(&cs); } diff --git a/sysmodules/rosalina/source/menus/sysconfig.c b/sysmodules/rosalina/source/menus/sysconfig.c index f2f8851..4a357dd 100644 --- a/sysmodules/rosalina/source/menus/sysconfig.c +++ b/sysmodules/rosalina/source/menus/sysconfig.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -34,13 +34,17 @@ Menu sysconfigMenu = { "System configuration menu", - .nbItems = 2, { { "Toggle LEDs", METHOD, .method = &SysConfigMenu_ToggleLEDs }, { "Toggle Wireless", METHOD, .method = &SysConfigMenu_ToggleWireless }, + { "Toggle Power Button", METHOD, .method=&SysConfigMenu_TogglePowerButton }, + { "Control Wireless connection", METHOD, .method = &SysConfigMenu_ControlWifi }, + {}, } }; +bool isConnectionForced = false; + void SysConfigMenu_ToggleLEDs(void) { Draw_Lock(); @@ -62,7 +66,7 @@ void SysConfigMenu_ToggleLEDs(void) u32 pressed = waitInputWithTimeout(1000); - if(pressed & BUTTON_A) + if(pressed & KEY_A) { mcuHwcInit(); u8 result; @@ -71,10 +75,10 @@ void SysConfigMenu_ToggleLEDs(void) MCUHWC_WriteRegister(0x28, &result, 1); mcuHwcExit(); } - else if(pressed & BUTTON_B) + else if(pressed & KEY_B) return; } - while(!terminationRequest); + while(!menuShouldExit); } void SysConfigMenu_ToggleWireless(void) @@ -135,14 +139,221 @@ void SysConfigMenu_ToggleWireless(void) u32 pressed = waitInputWithTimeout(1000); - if(pressed & BUTTON_A && nwmRunning) + if(pressed & KEY_A && nwmRunning) { nwmExtInit(); NWMEXT_ControlWirelessEnabled(!wireless); nwmExtExit(); } - else if(pressed & BUTTON_B) + else if(pressed & KEY_B) return; } - while(!terminationRequest); + while(!menuShouldExit); +} + +void SysConfigMenu_UpdateStatus(bool control) +{ + MenuItem *item = &sysconfigMenu.items[3]; + + if(control) + { + item->title = "Control Wireless connection"; + item->method = &SysConfigMenu_ControlWifi; + } + else + { + item->title = "Disable forced wireless connection"; + item->method = &SysConfigMenu_DisableForcedWifiConnection; + } +} + +static bool SysConfigMenu_ForceWifiConnection(int slot) +{ + char ssid[0x20 + 1] = {0}; + isConnectionForced = false; + + if(R_FAILED(acInit())) + return false; + + acuConfig config = {0}; + ACU_CreateDefaultConfig(&config); + ACU_SetNetworkArea(&config, 2); + ACU_SetAllowApType(&config, 1 << slot); + ACU_SetRequestEulaVersion(&config); + + Handle connectEvent = 0; + svcCreateEvent(&connectEvent, RESET_ONESHOT); + + bool forcedConnection = false; + if(R_SUCCEEDED(ACU_ConnectAsync(&config, connectEvent))) + { + if(R_SUCCEEDED(svcWaitSynchronization(connectEvent, -1)) && R_SUCCEEDED(ACU_GetSSID(ssid))) + forcedConnection = true; + } + svcCloseHandle(connectEvent); + + if(forcedConnection) + { + isConnectionForced = true; + SysConfigMenu_UpdateStatus(false); + } + else + acExit(); + + char infoString[80] = {0}; + u32 infoStringColor = forcedConnection ? COLOR_GREEN : COLOR_RED; + if(forcedConnection) + sprintf(infoString, "Succesfully forced a connection to: %s", ssid); + else + sprintf(infoString, "Failed to connect to slot %d", slot + 1); + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu"); + Draw_DrawString(10, 30, infoStringColor, infoString); + Draw_DrawString(10, 40, COLOR_WHITE, "Press B to go back."); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & KEY_B) + break; + } + while(!menuShouldExit); + + return forcedConnection; +} + +void SysConfigMenu_TogglePowerButton(void) +{ + u32 mcuIRQMask; + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + mcuHwcInit(); + MCUHWC_ReadRegister(0x18, (u8*)&mcuIRQMask, 4); + mcuHwcExit(); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu"); + Draw_DrawString(10, 30, COLOR_WHITE, "Press A to toggle, press B to go back."); + + Draw_DrawString(10, 50, COLOR_WHITE, "Current status:"); + Draw_DrawString(100, 50, (((mcuIRQMask & 0x00000001) == 0x00000001) ? COLOR_RED : COLOR_GREEN), (((mcuIRQMask & 0x00000001) == 0x00000001) ? " DISABLED" : " ENABLED ")); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & KEY_A) + { + mcuHwcInit(); + MCUHWC_ReadRegister(0x18, (u8*)&mcuIRQMask, 4); + mcuIRQMask ^= 0x00000001; + MCUHWC_WriteRegister(0x18, (u8*)&mcuIRQMask, 4); + mcuHwcExit(); + } + else if(pressed & KEY_B) + return; + } + while(!menuShouldExit); +} + +void SysConfigMenu_ControlWifi(void) +{ + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + int slot = 0; + char slotString[12] = {0}; + sprintf(slotString, ">1< 2 3 "); + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu"); + Draw_DrawString(10, 30, COLOR_WHITE, "Press A to force a connection to slot:"); + Draw_DrawString(10, 40, COLOR_WHITE, slotString); + Draw_DrawString(10, 60, COLOR_WHITE, "Press B to go back."); + + Draw_FlushFramebuffer(); + Draw_Unlock(); + + u32 pressed = waitInputWithTimeout(1000); + + if(pressed & KEY_A) + { + if(SysConfigMenu_ForceWifiConnection(slot)) + { + // Connection successfully forced, return from this menu to prevent ac handle refcount leakage. + break; + } + + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + } + else if(pressed & KEY_LEFT) + { + slotString[slot * 4] = ' '; + slotString[(slot * 4) + 2] = ' '; + slot--; + if(slot == -1) + slot = 2; + slotString[slot * 4] = '>'; + slotString[(slot * 4) + 2] = '<'; + } + else if(pressed & KEY_RIGHT) + { + slotString[slot * 4] = ' '; + slotString[(slot * 4) + 2] = ' '; + slot++; + if(slot == 3) + slot = 0; + slotString[slot * 4] = '>'; + slotString[(slot * 4) + 2] = '<'; + } + else if(pressed & KEY_B) + return; + } + while(!menuShouldExit); +} + +void SysConfigMenu_DisableForcedWifiConnection(void) +{ + Draw_Lock(); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); + Draw_Unlock(); + + acExit(); + SysConfigMenu_UpdateStatus(true); + + do + { + Draw_Lock(); + Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu"); + Draw_DrawString(10, 30, COLOR_WHITE, "Forced connection successfully disabled.\nNote: auto-connection may remain broken."); + + u32 pressed = waitInputWithTimeout(1000); + if(pressed & KEY_B) + return; + } + while(!menuShouldExit); } diff --git a/sysmodules/rosalina/source/minisoc.c b/sysmodules/rosalina/source/minisoc.c index 8aa0e30..d52d48c 100644 --- a/sysmodules/rosalina/source/minisoc.c +++ b/sysmodules/rosalina/source/minisoc.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -10,7 +10,17 @@ #include <3ds/ipc.h> #include <3ds/os.h> #include <3ds/synchronization.h> -#include "memory.h" +#include <3ds/result.h> +#include +#include "csvc.h" + +s32 miniSocRefCount = 0; +static u32 socContextAddr = 0x08000000; +static u32 socContextSize = 0x60000; +static Handle miniSocHandle; +static Handle miniSocMemHandle; + +bool miniSocEnabled = false; s32 _net_convert_error(s32 sock_retval); @@ -25,7 +35,7 @@ static Result SOCU_Initialize(Handle memhandle, u32 memsize) cmdbuf[4] = IPC_Desc_SharedHandles(1); cmdbuf[5] = memhandle; - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) return ret; @@ -39,22 +49,14 @@ static Result SOCU_Shutdown(void) cmdbuf[0] = IPC_MakeHeader(0x19,0,0); // 0x190000 - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) return ret; return cmdbuf[1]; } -static s32 miniSocRefCount = 0; -static u32 socContextAddr = 0x08000000; -static u32 socContextSize = 0x60000; -// SOCU_handle from ctrulib -// socMemhandle from ctrulib - -bool miniSocEnabled = false; - -Result miniSocInit() +Result miniSocInit(void) { if(AtomicPostIncrement(&miniSocRefCount)) return 0; @@ -71,20 +73,20 @@ Result miniSocInit() goto cleanup; } - ret = srvGetServiceHandle(&SOCU_handle, "soc:U"); + ret = srvGetServiceHandle(&miniSocHandle, "soc:U"); if(ret != 0) goto cleanup; - ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); + ret = svcControlMemoryEx(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READ | MEMPERM_WRITE, true); if(ret != 0) goto cleanup; socContextAddr = tmp; - ret = svcCreateMemoryBlock(&socMemhandle, (u32)socContextAddr, socContextSize, 0, 3); + ret = svcCreateMemoryBlock(&miniSocMemHandle, (u32)socContextAddr, socContextSize, 0, 3); if(ret != 0) goto cleanup; - ret = SOCU_Initialize(socMemhandle, socContextSize); + ret = SOCU_Initialize(miniSocMemHandle, socContextSize); if(ret != 0) goto cleanup; svcKernelSetState(0x10000, 2); @@ -94,17 +96,17 @@ Result miniSocInit() cleanup: AtomicDecrement(&miniSocRefCount); - if(socMemhandle != 0) + if(miniSocMemHandle != 0) { - svcCloseHandle(socMemhandle); - socMemhandle = 0; + svcCloseHandle(miniSocMemHandle); + miniSocMemHandle = 0; } - if(SOCU_handle != 0) + if(miniSocHandle != 0) { SOCU_Shutdown(); - svcCloseHandle(SOCU_handle); - SOCU_handle = 0; + svcCloseHandle(miniSocHandle); + miniSocHandle = 0; } if(tmp != 0) @@ -113,21 +115,19 @@ cleanup: return ret; } -Result miniSocExit(void) +Result miniSocExitDirect(void) { - if(AtomicDecrement(&miniSocRefCount)) - return 0; - + //if (miniSocRefCount != 0) __builtin_trap(); Result ret = 0; u32 tmp; - svcCloseHandle(socMemhandle); - socMemhandle = 0; + svcCloseHandle(miniSocMemHandle); + miniSocMemHandle = 0; ret = SOCU_Shutdown(); - svcCloseHandle(SOCU_handle); - SOCU_handle = 0; + svcCloseHandle(miniSocHandle); + miniSocHandle = 0; svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE); if(ret == 0) @@ -138,6 +138,14 @@ Result miniSocExit(void) return ret; } +Result miniSocExit(void) +{ + if(!miniSocEnabled || AtomicDecrement(&miniSocRefCount)) + return 0; + + return miniSocExitDirect(); +} + int socSocket(int domain, int type, int protocol) { int ret = 0; @@ -163,11 +171,11 @@ int socSocket(int domain, int type, int protocol) cmdbuf[3] = protocol; cmdbuf[4] = IPC_Desc_CurProcessId(); - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) { //errno = SYNC_ERROR; - return ret; + return R_FAILED(ret) ? ret : -1; } ret = (int)cmdbuf[1]; @@ -213,7 +221,7 @@ int socBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[6] = (u32)tmpaddr; - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) { //errno = SYNC_ERROR; return ret; @@ -241,7 +249,7 @@ int socListen(int sockfd, int max_connections) cmdbuf[2] = (u32)max_connections; cmdbuf[3] = IPC_Desc_CurProcessId(); - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) { //errno = SYNC_ERROR; @@ -283,7 +291,7 @@ int socAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[1] = (u32)tmpaddr; - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; @@ -340,7 +348,7 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[6] = (u32)tmpaddr; - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) return -1; ret = (int)cmdbuf[1]; @@ -383,13 +391,13 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout) staticbufs[0] = IPC_Desc_StaticBuffer(size,0); staticbufs[1] = (u32)fds; - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { - return ret; + return R_FAILED(ret) ? ret : -1; } ret = (int)cmdbuf[1]; @@ -408,7 +416,7 @@ int socClose(int sockfd) cmdbuf[1] = (u32)sockfd; cmdbuf[2] = IPC_Desc_CurProcessId(); - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) { //errno = SYNC_ERROR; return ret; @@ -440,7 +448,7 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9); cmdbuf[8] = (u32)optval; - ret = svcSendSyncRequest(SOCU_handle); + ret = svcSendSyncRequest(miniSocHandle); if(ret != 0) { return ret; } @@ -457,12 +465,262 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle return ret; } -ssize_t soc_recv(int sockfd, void *buf, size_t len, int flags) +long socGethostid(void) { - return soc_recvfrom(sockfd, buf, len, flags, NULL, 0); + int ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x160000 + + ret = svcSendSyncRequest(miniSocHandle); + if(ret != 0) { + //errno = SYNC_ERROR; + return -1; + } + + ret = (int)cmdbuf[1]; + if(ret == 0) + ret = cmdbuf[2]; + + return ret; } -ssize_t soc_send(int sockfd, const void *buf, size_t len, int flags) +static ssize_t _socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { - return soc_sendto(sockfd, buf, len, flags, NULL, 0); + int ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 tmp_addrlen = 0; + u8 tmpaddr[0x1c]; + u32 saved_threadstorage[2]; + + memset(tmpaddr, 0, 0x1c); + + if(src_addr) + tmp_addrlen = 0x1c; + + cmdbuf[0] = IPC_MakeHeader(0x7,4,4); // 0x70104 + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = IPC_Desc_CurProcessId(); + cmdbuf[7] = IPC_Desc_Buffer(len,IPC_BUFFER_W); + cmdbuf[8] = (u32)buf; + + u32 * staticbufs = getThreadStaticBuffers(); + saved_threadstorage[0] = staticbufs[0]; + saved_threadstorage[1] = staticbufs[1]; + + staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); + staticbufs[1] = (u32)tmpaddr; + + ret = svcSendSyncRequest(miniSocHandle); + + staticbufs[0] = saved_threadstorage[0]; + staticbufs[1] = saved_threadstorage[1]; + + if(ret != 0) { + //errno = SYNC_ERROR; + return -1; + } + + ret = (int)cmdbuf[1]; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + //errno = -ret; + return -1; + } + + if(src_addr != NULL) { + src_addr->sa_family = tmpaddr[1]; + if(*addrlen > tmpaddr[0]) + *addrlen = tmpaddr[0]; + memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2); + } + + return ret; +} + +static ssize_t _socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) +{ + int ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 tmp_addrlen = 0; + u8 tmpaddr[0x1c]; + u32 saved_threadstorage[4]; + + if(src_addr) + tmp_addrlen = 0x1c; + + memset(tmpaddr, 0, 0x1c); + + cmdbuf[0] = 0x00080102; + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = 0x20; + + saved_threadstorage[0] = cmdbuf[0x100>>2]; + saved_threadstorage[1] = cmdbuf[0x104>>2]; + saved_threadstorage[2] = cmdbuf[0x108>>2]; + saved_threadstorage[3] = cmdbuf[0x10c>>2]; + + cmdbuf[0x100>>2] = (((u32)len)<<14) | 2; + cmdbuf[0x104>>2] = (u32)buf; + cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; + cmdbuf[0x10c>>2] = (u32)tmpaddr; + + ret = svcSendSyncRequest(miniSocHandle); + if(ret != 0) { + //errno = SYNC_ERROR; + return ret; + } + + cmdbuf[0x100>>2] = saved_threadstorage[0]; + cmdbuf[0x104>>2] = saved_threadstorage[1]; + cmdbuf[0x108>>2] = saved_threadstorage[2]; + cmdbuf[0x10c>>2] = saved_threadstorage[3]; + + ret = (int)cmdbuf[1]; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + //errno = -ret; + return -1; + } + + if(src_addr != NULL) { + src_addr->sa_family = tmpaddr[1]; + if(*addrlen > tmpaddr[0]) + *addrlen = tmpaddr[0]; + memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2); + } + + return ret; +} + +static ssize_t _socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) +{ + int ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 tmp_addrlen = 0; + u8 tmpaddr[0x1c]; + + memset(tmpaddr, 0, 0x1c); + + if(dest_addr) { + if(dest_addr->sa_family == AF_INET) + tmp_addrlen = 8; + else + tmp_addrlen = 0x1c; + + if(addrlen < tmp_addrlen) { + //errno = EINVAL; + return -1; + } + + tmpaddr[0] = tmp_addrlen; + tmpaddr[1] = dest_addr->sa_family; + memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2); + } + + cmdbuf[0] = IPC_MakeHeader(0x9,4,6); // 0x90106 + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = IPC_Desc_CurProcessId(); + cmdbuf[7] = IPC_Desc_StaticBuffer(tmp_addrlen,1); + cmdbuf[8] = (u32)tmpaddr; + cmdbuf[9] = IPC_Desc_Buffer(len,IPC_BUFFER_R); + cmdbuf[10] = (u32)buf; + + ret = svcSendSyncRequest(miniSocHandle); + if(ret != 0) { + //errno = SYNC_ERROR; + return ret; + } + + ret = (int)cmdbuf[1]; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + //errno = -ret; + return -1; + } + + return ret; +} + +static ssize_t _socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) +{ + int ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 tmp_addrlen = 0; + u8 tmpaddr[0x1c]; + + memset(tmpaddr, 0, 0x1c); + + if(dest_addr) { + if(dest_addr->sa_family == AF_INET) + tmp_addrlen = 8; + else + tmp_addrlen = 0x1c; + + if(addrlen < tmp_addrlen) { + //errno = EINVAL; + return -1; + } + + tmpaddr[0] = tmp_addrlen; + tmpaddr[1] = dest_addr->sa_family; + memcpy(&tmpaddr[2], &dest_addr->sa_data, tmp_addrlen-2); + } + + cmdbuf[0] = IPC_MakeHeader(0xA,4,6); // 0xA0106 + cmdbuf[1] = (u32)sockfd; + cmdbuf[2] = (u32)len; + cmdbuf[3] = (u32)flags; + cmdbuf[4] = (u32)tmp_addrlen; + cmdbuf[5] = IPC_Desc_CurProcessId(); + cmdbuf[7] = IPC_Desc_StaticBuffer(len,2); + cmdbuf[8] = (u32)buf; + cmdbuf[9] = IPC_Desc_StaticBuffer(tmp_addrlen,1); + cmdbuf[10] = (u32)tmpaddr; + + ret = svcSendSyncRequest(miniSocHandle); + if(ret != 0) { + //errno = SYNC_ERROR; + return ret; + } + + ret = (int)cmdbuf[1]; + if(ret == 0) + ret = _net_convert_error(cmdbuf[2]); + + if(ret < 0) { + //errno = -ret; + return -1; + } + + return ret; +} + +ssize_t socRecvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) +{ + if(len < 0x2000) + return _socuipc_cmd8(sockfd, buf, len, flags, src_addr, addrlen); + return _socuipc_cmd7(sockfd, buf, len, flags, src_addr, addrlen); +} + +ssize_t socSendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) +{ + if(len < 0x2000) + return _socuipc_cmda(sockfd, buf, len, flags, dest_addr, addrlen); + return _socuipc_cmd9(sockfd, buf, len, flags, dest_addr, addrlen); } diff --git a/sysmodules/rosalina/source/ntp.c b/sysmodules/rosalina/source/ntp.c index 49ed3a6..b721834 100644 --- a/sysmodules/rosalina/source/ntp.c +++ b/sysmodules/rosalina/source/ntp.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -30,25 +30,15 @@ #include "utils.h" #include "minisoc.h" -#define NUM2BCD(n) ((n<99) ? (((n/10)*0x10)|(n%10)) : 0x99) +#define NUM2BCD(n) ((n<99) ? (((n/10)*0x10)|(n%10)) : 0x99) #define NTP_TIMESTAMP_DELTA 2208988800ull -#ifndef NTP_IP -#define NTP_IP 0xD8EF2300 -#endif +#define MAKE_IPV4(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) -typedef struct RtcTime { - // From 3dbrew - u8 seconds; - u8 minutes; - u8 hours; - u8 dayofweek; - u8 dayofmonth; - u8 month; - u8 year; - u8 leapcount; -} RtcTime; +#ifndef NTP_IP +#define NTP_IP MAKE_IPV4(51, 137, 137, 111) // time.windows.com +#endif // From https://github.com/lettier/ntpclient/blob/master/source/c/main.c @@ -82,17 +72,6 @@ typedef struct NtpPacket } NtpPacket; // Total: 384 bits or 48 bytes. -void rtcToBcd(u8 *out, const RtcTime *in) -{ - memcpy(out, in, 8); - for (u32 i = 0; i < 8; i++) - { - u8 units = out[i] % 10; - u8 tens = (out[i] - units) / 10; - out[i] = (tens << 4) | units; - } -} - Result ntpGetTimeStamp(time_t *outTimestamp) { Result res = 0; @@ -102,6 +81,11 @@ Result ntpGetTimeStamp(time_t *outTimestamp) return res; int sock = socSocket(AF_INET, SOCK_DGRAM, 0); + if (sock < -10000) { + // Socket services broken + return sock; + } + struct sockaddr_in servAddr = {0}; // Server address data structure. NtpPacket packet = {0}; @@ -113,7 +97,7 @@ Result ntpGetTimeStamp(time_t *outTimestamp) // Copy the server's IP address to the server address structure. - servAddr.sin_addr.s_addr = htonl(NTP_IP); // 216.239.35.0 time1.google.com + servAddr.sin_addr.s_addr = htonl(NTP_IP); // Convert the port number integer to network big-endian style and save it to the server address structure. servAddr.sin_port = htons(123); @@ -123,10 +107,10 @@ Result ntpGetTimeStamp(time_t *outTimestamp) if(socConnect(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr_in)) < 0) goto cleanup; - if(soc_send(sock, &packet, sizeof(NtpPacket), 0) < 0) + if(socSend(sock, &packet, sizeof(NtpPacket), 0) < 0) goto cleanup; - if(soc_recv(sock, &packet, sizeof(NtpPacket), 0) < 0) + if(socRecv(sock, &packet, sizeof(NtpPacket), 0) < 0) goto cleanup; res = 0; @@ -155,45 +139,33 @@ cleanup: return res; } -Result ntpSetTimeDate(const struct tm *localt) +Result ntpSetTimeDate(time_t timestamp) { - Result res = mcuHwcInit(); + Result res = ptmSysmInit(); if (R_FAILED(res)) return res; - res = cfguInit(); - if (R_FAILED(res)) goto cleanup; + if (R_FAILED(res)) + { + ptmSysmExit(); + return res; + } // First, set the config RTC offset to 0 - u8 rtcOff = 0; - u8 rtcOff2[8] = {0}; - res = CFG_SetConfigInfoBlk4(1, 0x10000, &rtcOff); - if (R_FAILED(res)) goto cleanup; - res = CFG_SetConfigInfoBlk4(8, 0x30001, rtcOff2); + u8 rtcOff[8] = {0}; + res = CFG_SetConfigInfoBlk4(8, 0x30001, rtcOff); if (R_FAILED(res)) goto cleanup; - u8 yr = (u8)(localt->tm_year - 100); // Update the RTC - u8 bcd[8]; - RtcTime lt = { - .seconds = (u8)localt->tm_sec, - .minutes = (u8)localt->tm_min, - .hours = (u8)localt->tm_hour, - .dayofweek = (u8)localt->tm_wday, - .dayofmonth = (u8)localt->tm_mday, - .month = (u8)(localt->tm_mon + 1), - .year = yr, - .leapcount = 0, - }; - rtcToBcd(bcd, <); - - res = MCUHWC_WriteRegister(0x30, bcd, 7); + // 946684800 is the timestamp of 01/01/2000 00:00 relative to the Unix Epoch + s64 msY2k = (timestamp - 946684800) * 1000; + res = PTMSYSM_SetRtcTime(msY2k); if (R_FAILED(res)) goto cleanup; // Save the config changes res = CFG_UpdateConfigSavegame(); cleanup: - mcuHwcExit(); + ptmSysmExit(); cfguExit(); return res; } diff --git a/sysmodules/rosalina/source/pmdbgext.c b/sysmodules/rosalina/source/pmdbgext.c index 061bddd..48af096 100644 --- a/sysmodules/rosalina/source/pmdbgext.c +++ b/sysmodules/rosalina/source/pmdbgext.c @@ -1,5 +1,5 @@ // License for this file: ctrulib's license -// Copyright AuroraWright, TuxSH 2019 +// Copyright AuroraWright, TuxSH 2019-2020 #include #include <3ds/types.h> @@ -10,15 +10,16 @@ #include <3ds/services/pmdbg.h> #include <3ds/ipc.h> -Result PMDBG_GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid) +Result PMDBG_GetCurrentAppInfo(FS_ProgramInfo *outProgramInfo, u32 *outPid, u32 *outLaunchFlags) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x100, 0, 0); if(R_FAILED(ret = svcSendSyncRequest(*pmDbgGetSessionHandle()))) return ret; - memcpy(outTitleId, cmdbuf + 2, 8); - *outPid = cmdbuf[4]; + memcpy(outProgramInfo, cmdbuf + 2, sizeof(FS_ProgramInfo)); + *outPid = cmdbuf[6]; + *outLaunchFlags = cmdbuf[7]; return cmdbuf[1]; } @@ -47,3 +48,16 @@ Result PMDBG_LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInf *outDebug = cmdbuf[3]; return (Result)cmdbuf[1]; } + +Result PMDBG_PrepareToChainloadHomebrew(u64 titleId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x103, 2, 0); + memcpy(&cmdbuf[1], &titleId, 8); + + if(R_FAILED(ret = svcSendSyncRequest(*pmDbgGetSessionHandle()))) return ret; + + return (Result)cmdbuf[1]; +} diff --git a/sysmodules/rosalina/source/menus/process_patches.c b/sysmodules/rosalina/source/process_patches.c similarity index 66% rename from sysmodules/rosalina/source/menus/process_patches.c rename to sysmodules/rosalina/source/process_patches.c index 30a6e25..8eec277 100644 --- a/sysmodules/rosalina/source/menus/process_patches.c +++ b/sysmodules/rosalina/source/process_patches.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 @@ -25,48 +25,11 @@ */ #include <3ds.h> +#include #include "csvc.h" -#include "menus/process_patches.h" -#include "memory.h" -#include "draw.h" -#include "hbloader.h" -#include "fmt.h" +#include "process_patches.h" #include "utils.h" -static Result ProcessPatchesMenu_DoPatchUnpatchFS(u32 textTotalRoundedSize) -{ - static bool patched = false; - static u16 *off; - static u16 origData[2]; - static const u16 pattern[2] = { - 0x7401, // strb r1, [r0, #16] - 0x2000, // movs r0, #0 - }; - - if(patched) - { - memcpy(off, &origData, sizeof(origData)); - patched = false; - } - else - { - off = (u16 *)memsearch((u8 *)0x00100000, &pattern, textTotalRoundedSize, sizeof(pattern)); - if(off == NULL) - return -1; - - for(; (*off & 0xFF00) != 0xB500; off++); // Find function start - - memcpy(origData, off, 4); - off[0] = 0x2001; // mov r0, #1 - off[1] = 0x4770; // bx lr - - patched = true; - } - - //processPatchesMenu.items[1].title = patched ? "Unpatch FS for the archive checks" : "Patch FS for the archive checks"; - return 0; -} - Result OpenProcessByName(const char *name, Handle *h) { u32 pidList[0x40]; @@ -96,7 +59,7 @@ Result OpenProcessByName(const char *name, Handle *h) return 0; } -static u32 ProcessPatchesMenu_PatchUnpatchProcessByName(const char *name, Result (*func)(u32 size)) +Result PatchProcessByName(const char *name, Result (*func)(u32 size)) { Result res; Handle processHandle; @@ -113,8 +76,3 @@ static u32 ProcessPatchesMenu_PatchUnpatchProcessByName(const char *name, Result svcUnmapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, textTotalRoundedSize); return res; } - -void ProcessPatchesMenu_PatchUnpatchFSDirectly(void) -{ - ProcessPatchesMenu_PatchUnpatchProcessByName("fs", &ProcessPatchesMenu_DoPatchUnpatchFS); -} diff --git a/sysmodules/rosalina/source/redshift/colorramp.c b/sysmodules/rosalina/source/redshift/colorramp.c index 6d647a9..e24b9d7 100644 --- a/sysmodules/rosalina/source/redshift/colorramp.c +++ b/sysmodules/rosalina/source/redshift/colorramp.c @@ -19,7 +19,7 @@ */ #include -#include +//#include #include "redshift/redshift.h" @@ -282,8 +282,10 @@ interpolate_color(float a, const float *c1, const float *c2, float *c) } /* Helper macro used in the fill functions */ -#define F(Y, C) pow((Y) * setting->brightness * \ - white_point[C], 1.0/setting->gamma[C]) +#define F(Y, C) ((Y) * white_point[C]) + +/*#define F(Y, C) pow((Y) * setting->brightness * \ + white_point[C], 1.0/setting->gamma[C])*/ void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b, @@ -324,4 +326,4 @@ colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b, } } -#undef F \ No newline at end of file +#undef F diff --git a/sysmodules/rosalina/source/service_manager.c b/sysmodules/rosalina/source/service_manager.c index 33cc78e..1244133 100644 --- a/sysmodules/rosalina/source/service_manager.c +++ b/sysmodules/rosalina/source/service_manager.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* 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 diff --git a/sysmodules/rosalina/source/sock_util.c b/sysmodules/rosalina/source/sock_util.c index 7223059..db25d04 100644 --- a/sysmodules/rosalina/source/sock_util.c +++ b/sysmodules/rosalina/source/sock_util.c @@ -1,6 +1,6 @@ /* * This file is part of Luma3DS. -* Copyright (C) 2016-2019 Aurora Wright, TuxSH +* Copyright (C) 2016-2020 Aurora Wright, TuxSH * * SPDX-License-Identifier: (MIT OR GPL-2.0-or-later) */ @@ -16,8 +16,8 @@ #include "sock_util.h" #include "sleep.h" -extern Handle terminationRequestEvent; -extern bool terminationRequest; +extern Handle preTerminationEvent; +extern bool preTerminationRequested; // soc's poll function is odd, and doesn't like -1 as fd. // so this compacts everything together @@ -103,29 +103,36 @@ Result server_init(struct sock_server *serv) return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY); } -void server_bind(struct sock_server *serv, u16 port) +Result server_bind(struct sock_server *serv, u16 port) { int server_sockfd; - Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event }; + Handle handles[2] = { preTerminationEvent, serv->shall_terminate_event }; s32 idx = -1; server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); - int res; - while(server_sockfd == -1) + int res; + u32 tries = 15; + while(server_sockfd == -1 && --tries > 0) { if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0) - return; + return -1; server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); } + if (server_sockfd < -10000 || tries == 0) { + // Socket services broken + serv->init_result = -1; + svcSignalEvent(serv->shall_terminate_event); + return -1; + } + struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = htons(port); - saddr.sin_addr.s_addr = gethostid(); + saddr.sin_addr.s_addr = socGethostid(); res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); - if(res == 0) { res = socListen(server_sockfd, 2); @@ -145,11 +152,20 @@ void server_bind(struct sock_server *serv, u16 port) serv->ctx_ptrs[idx] = new_ctx; } } + + if (res != 0) { + // Socket services broken + serv->init_result = res; + svcSignalEvent(serv->shall_terminate_event); + return res; + } + + return 0; } static bool server_should_exit(struct sock_server *serv) { - return svcWaitSynchronization(serv->shall_terminate_event, 0) == 0 || svcWaitSynchronization(terminationRequestEvent, 0) == 0; + return svcWaitSynchronization(serv->shall_terminate_event, 0) == 0 || svcWaitSynchronization(preTerminationEvent, 0) == 0; } void server_run(struct sock_server *serv) @@ -158,7 +174,7 @@ void server_run(struct sock_server *serv) serv->running = true; svcSignalEvent(serv->started_event); - while(serv->running && !terminationRequest) + while(serv->running && !preTerminationRequested) { if(server_should_exit(serv)) goto abort_connections; @@ -181,7 +197,7 @@ void server_run(struct sock_server *serv) int pollres = socPoll(fds, serv->nfds, 50); - if(server_should_exit(serv)) + if(server_should_exit(serv) || pollres < -10000) goto abort_connections; for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++) @@ -266,6 +282,7 @@ abort_connections: server_kill_connections(serv); serv->running = false; svcClearEvent(serv->started_event); + svcSignalEvent(serv->shall_terminate_event); } void server_set_should_close_all(struct sock_server *serv) @@ -294,7 +311,8 @@ void server_kill_connections(struct sock_server *serv) socClose(fds[i].fd); fds[i].fd = -1; - serv->ctx_ptrs[i]->should_close = true; + if(serv->ctx_ptrs[i] != NULL) + serv->ctx_ptrs[i]->should_close = true; } } diff --git a/sysmodules/rosalina/source/task_runner.c b/sysmodules/rosalina/source/task_runner.c index b651349..3e320cc 100644 --- a/sysmodules/rosalina/source/task_runner.c +++ b/sysmodules/rosalina/source/task_runner.c @@ -7,10 +7,15 @@ TaskRunner g_taskRunner; static MyThread taskRunnerThread; static u8 ALIGN(8) taskRunnerThreadStack[0x1000]; +static void taskRunnerNoOpFunction(void *args) +{ + (void)args; +} + MyThread *taskRunnerCreateThread(void) { TaskRunner_Init(); - MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 0x20, 1); + MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 58, 1); return &taskRunnerThread; } @@ -30,9 +35,15 @@ void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsi LightEvent_Signal(&g_taskRunner.parametersSetEvent); } +void TaskRunner_Terminate(void) +{ + g_taskRunner.shouldTerminate = true; + TaskRunner_RunTask(taskRunnerNoOpFunction, NULL, 0); +} + void TaskRunner_HandleTasks(void) { - for (;;) { + while (!g_taskRunner.shouldTerminate) { LightEvent_Signal(&g_taskRunner.readyEvent); LightEvent_Wait(&g_taskRunner.parametersSetEvent); g_taskRunner.task(g_taskRunner.argStorage); @@ -42,4 +53,4 @@ void TaskRunner_HandleTasks(void) void TaskRunner_WaitReady(void) { LightEvent_Wait(&g_taskRunner.readyEvent); -} \ No newline at end of file +} diff --git a/sysmodules/rosalina/source/utils.c b/sysmodules/rosalina/source/utils.c new file mode 100644 index 0000000..9719896 --- /dev/null +++ b/sysmodules/rosalina/source/utils.c @@ -0,0 +1,110 @@ +/* +* 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 "utils.h" +#include "csvc.h" +#include +#include + +void formatMemoryPermission(char *outbuf, MemPerm perm) +{ + if (perm == MEMPERM_DONTCARE) + { + strcpy(outbuf, "???"); + return; + } + + outbuf[0] = perm & MEMPERM_READ ? 'r' : '-'; + outbuf[1] = perm & MEMPERM_WRITE ? 'w' : '-'; + outbuf[2] = perm & MEMPERM_EXECUTE ? 'x' : '-'; + outbuf[3] = '\0'; +} + +void formatUserMemoryState(char *outbuf, MemState state) +{ + static const char *states[12] = + { + "Free", + "Reserved", + "IO", + "Static", + "Code", + "Private", + "Shared", + "Continuous", + "Aliased", + "Alias", + "AliasCode", + "Locked" + }; + + strcpy(outbuf, state > 11 ? "Unknown" : states[state]); +} + +u32 formatMemoryMapOfProcess(char *outbuf, u32 bufLen, Handle handle) +{ + u32 maxLineSize = 35 + (handle == CUR_PROCESS_HANDLE ? 15 : 0); + u32 address = 0; + u32 posInBuffer = 0; + u32 maxPosInBuffer = bufLen - maxLineSize; // 35 is the maximum length of a formatted region + MemInfo memi; + PageInfo pagei; + char pabuf[32]; + char permbuf[8]; + char statebuf[16]; + + s64 TTBCR; + svcGetSystemInfo(&TTBCR, 0x10002, 0); + + while (address < (1u << (32 - (u32)TTBCR)) // Limit to check for regions + && posInBuffer < maxPosInBuffer + && R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address))) + { + // Update the address for next region + address = memi.base_addr + memi.size; + + // If region isn't FREE then add it to the list + if (memi.state != MEMSTATE_FREE) + { + if (handle == CUR_PROCESS_HANDLE) + { + u32 pa = svcConvertVAToPA((void *)memi.base_addr, false); + sprintf(pabuf, " (PA %08lx)", pa); + } + else + pabuf[0] = '\0'; + + formatMemoryPermission(permbuf, memi.perm); + formatUserMemoryState(statebuf, memi.state); + + posInBuffer += sprintf(outbuf + posInBuffer, "%08lx - %08lx%s %s %s\n", + memi.base_addr, address, pabuf, permbuf, statebuf); + } + } + + svcCloseHandle(handle); + return posInBuffer; +} diff --git a/sysmodules/sm/LICENSE b/sysmodules/sm/LICENSE index 6e8d147..2c2c2a1 100644 --- a/sysmodules/sm/LICENSE +++ b/sysmodules/sm/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 TuxSH +Copyright (c) 2017-2020 TuxSH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/sysmodules/sm/Makefile b/sysmodules/sm/Makefile index b14d489..fa49ced 100644 --- a/sysmodules/sm/Makefile +++ b/sysmodules/sm/Makefile @@ -28,7 +28,7 @@ INCLUDES := include ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft DEFINES := -DARM11 -D_3DS -CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \ +CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -Os -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections \ $(ARCH) $(DEFINES) @@ -37,7 +37,7 @@ CFLAGS += $(INCLUDE) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit LIBS := -lctru diff --git a/sysmodules/sm/README.md b/sysmodules/sm/README.md index b3e1885..b63f514 100644 --- a/sysmodules/sm/README.md +++ b/sysmodules/sm/README.md @@ -1,5 +1,5 @@ # 3ds_sm -Open source replacement of the ARM11 SM system module. +Open source replacement of the Arm11 SM system module. This is licensed under the MIT license. # Usage diff --git a/sysmodules/sm/source/common.h b/sysmodules/sm/source/common.h index bbecb3a..7ee7f6b 100644 --- a/sysmodules/sm/source/common.h +++ b/sysmodules/sm/source/common.h @@ -1,7 +1,7 @@ /* common.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ @@ -10,8 +10,10 @@ This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for #include <3ds.h> #include -#define IS_PRE_7X (osGetFirmVersion() < SYSTEM_VERSION(2, 39, 4)) -#define IS_PRE_93 (osGetFirmVersion() < SYSTEM_VERSION(2, 48, 3)) +#define KERNEL_VERSION_MINOR (GET_VERSION_MINOR(osGetKernelVersion())) + +#define IS_PRE_7X (KERNEL_VERSION_MINOR < 39) +#define IS_PRE_93 (KERNEL_VERSION_MINOR < 48) extern u32 nbSection0Modules; extern Handle resumeGetServiceHandleOrPortRegisteredSemaphore; diff --git a/sysmodules/sm/source/list.c b/sysmodules/sm/source/list.c index 467c7e9..4dcbb89 100644 --- a/sysmodules/sm/source/list.c +++ b/sysmodules/sm/source/list.c @@ -1,7 +1,7 @@ /* list.c -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/list.h b/sysmodules/sm/source/list.h index 14150fe..c666937 100644 --- a/sysmodules/sm/source/list.h +++ b/sysmodules/sm/source/list.h @@ -1,7 +1,7 @@ /* list.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/main.c b/sysmodules/sm/source/main.c index 3318bf3..28961f0 100644 --- a/sysmodules/sm/source/main.c +++ b/sysmodules/sm/source/main.c @@ -1,7 +1,7 @@ /* main.c -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ @@ -24,10 +24,27 @@ static ProcessData processDataPool[64]; static u8 ALIGN(4) serviceAccessListStaticBuffer[0x110]; -void __appInit(void) -{ - s64 out; +void __ctru_exit(int rc) { (void)rc; } // needed to avoid linking error +// this is called after main exits +void __wrap_exit(int rc) +{ + (void)rc; + // Not supposed to terminate... kernel will clean up the handles if it does happen anyway + svcExitProcess(); +} + +void __sync_init(); +// void __libc_init_array(void); + +// Called before main +void initSystem(void) +{ + __sync_init(); + + //__libc_init_array(); + + s64 out; u32 *staticBuffers = getThreadStaticBuffers(); staticBuffers[0] = IPC_Desc_StaticBuffer(0x110, 0); staticBuffers[1] = (u32)serviceAccessListStaticBuffer; @@ -40,28 +57,6 @@ void __appInit(void) buildList(&freeProcessDataList, processDataPool, sizeof(processDataPool) / sizeof(ProcessData), sizeof(ProcessData)); } - -// this is called after main exits -void __appExit(void){} - -void __system_allocateHeaps(void){} - -void __system_initSyscalls(void){} - -Result __sync_init(void); -Result __sync_fini(void); - -void __ctru_exit(void){} - -void initSystem(void) -{ - void __libc_init_array(void); - __sync_init(); - __system_allocateHeaps(); - __appInit(); - __libc_init_array(); -} - int main(void) { Result res; diff --git a/sysmodules/sm/source/notifications.c b/sysmodules/sm/source/notifications.c index afd719e..7a69004 100644 --- a/sysmodules/sm/source/notifications.c +++ b/sysmodules/sm/source/notifications.c @@ -1,7 +1,7 @@ /* notifications.c -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ @@ -109,7 +109,7 @@ Result ReceiveNotification(SessionData *sessionData, u32 *notificationId) if(processData == NULL || !processData->notificationEnabled || processData->nbPendingNotifications == 0) { - if(processData->nbPendingNotifications) + if(processData != NULL && processData->nbPendingNotifications) *notificationId = 0; return 0xD8806404; } diff --git a/sysmodules/sm/source/notifications.h b/sysmodules/sm/source/notifications.h index a8b7fbf..42b640f 100644 --- a/sysmodules/sm/source/notifications.h +++ b/sysmodules/sm/source/notifications.h @@ -1,7 +1,7 @@ /* notifications.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/processes.c b/sysmodules/sm/source/processes.c index 5977e98..18ffadc 100644 --- a/sysmodules/sm/source/processes.c +++ b/sysmodules/sm/source/processes.c @@ -1,7 +1,7 @@ /* processes.c -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/processes.h b/sysmodules/sm/source/processes.h index 3f9b927..bbef223 100644 --- a/sysmodules/sm/source/processes.h +++ b/sysmodules/sm/source/processes.h @@ -1,7 +1,7 @@ /* processes.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/services.c b/sysmodules/sm/source/services.c index c36c35c..a81af7c 100644 --- a/sysmodules/sm/source/services.c +++ b/sysmodules/sm/source/services.c @@ -1,7 +1,7 @@ /* services.c -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/services.h b/sysmodules/sm/source/services.h index 8c79882..71fe2db 100644 --- a/sysmodules/sm/source/services.h +++ b/sysmodules/sm/source/services.h @@ -1,7 +1,7 @@ /* services.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/srv.c b/sysmodules/sm/source/srv.c index feb2e68..5afb505 100644 --- a/sysmodules/sm/source/srv.c +++ b/sysmodules/sm/source/srv.c @@ -1,7 +1,7 @@ /* srv.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/srv.h b/sysmodules/sm/source/srv.h index 24e23bd..afd0ba7 100644 --- a/sysmodules/sm/source/srv.h +++ b/sysmodules/sm/source/srv.h @@ -1,7 +1,7 @@ /* srv.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/srv_pm.c b/sysmodules/sm/source/srv_pm.c index 490986f..102a279 100644 --- a/sysmodules/sm/source/srv_pm.c +++ b/sysmodules/sm/source/srv_pm.c @@ -1,7 +1,7 @@ /* srv_pm.c -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */ diff --git a/sysmodules/sm/source/srv_pm.h b/sysmodules/sm/source/srv_pm.h index a9ca8d9..e7c081a 100644 --- a/sysmodules/sm/source/srv_pm.h +++ b/sysmodules/sm/source/srv_pm.h @@ -1,7 +1,7 @@ /* srv_pm.h -(c) TuxSH, 2017 +(c) TuxSH, 2017-2020 This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details). */