The first cluster now is properly used by unlaunch to save its configs, so it will never be the same across runs of the installer, to account for this, skip the first 0x4000 bytes when checking for its sha1, so that the user configurable part is ignored |
||
|---|---|---|
| .github/workflows | ||
| arm7 | ||
| arm9 | ||
| nitrofiles | ||
| .clangd | ||
| .gitattributes | ||
| .gitignore | ||
| icon.bmp | ||
| LICENSE.txt | ||
| Makefile | ||
| README.md | ||
"Safe" unlaunch installer
A basic homebrew with a single job, install and uninstall unlaunch from a console.
WARNING
This can modify your internal system NAND! There is always a risk of bricking, albeit small, when you modify NAND. Please proceed with caution.
Features
- Safety checks to install and uninstall unlaunch without a risk of bricking
- Fully compatible with older unlaunch installs
- Works on every DSi, whether it's retail or development
- Keeps a recovery copy of unlaunch in NAND to protect against future bricks (only on retail consoles)
Notes
This installer comes bundled with a specific version of unlaunch (2.0), but can
load a separate unlaunch installer from the root of the sd card, named
unlaunch.dsi.
Supported unlaunch versions are 1.8, 1.9 and 2.0, since earlier ones don't work if installed with this new method.
Due to some unforunate version differences, the install method used by this application won't be usable on consoles with firmware 1.4.2 (1.4.3 for china). So installing on consoles that ship that version will be prevented
Differences with official installer
The Nintendo DSi's stage2 has a failsafe where it will load a backup launcher (HNAA) if it can't find the real one (eg. missing, corrupted), even on retail consoles.
The official installer will append itself to the tmd of the "real" launcher. This leaves the console bricked in case of failed install or uninstall (since the backup launcher doesn't exist, stage2 can't save you). The safe unlaunch installer takes advantage of this feature by installing unlaunch to the backup launcher. The official launcher's TMD is "broken" by changing a byte, making stage2 load unlaunch in the backup launcher.
This is safer than normal unlaunch installs because as long as the main TMD isn't touched, the system can't be bricked by those operations (apart from total nand failure), and when the main TMD is tampered with, unlaunch is already there as fallback in case of errors. Uninstalling is also safer as this program only has to restore that previously changed byte to restore the main TMD. This allows to keep backup unlaunch "installed" as general brick protection since it won't interfere with the system. As a bonus, if you sell/trade you console in the future and the new owner uses the official installer, they'll be protected from bricks.
Patches applied to unlaunch
The installer ships with 2 binary patches, one is an "ahestetic" one to enable
the dsi H&S screen and sound.
The other is a mandatory one, required to make unlaunch properly use the tmd that
was installed in the HNAA folder, otherwise it would attempt to save its settings
to random fat blocks, since it assumes that unlaunch is installed in the blocks right
after the title.tmd associated with the launcher read from HWINFO_S.
More specifically, the sound and splash patch modifies the arm7 instruction of unlaunch at
address 0x1308 (in the then relocated code it is run at 0x23fe038). The patched instruction
is a bl to the function patching a second binary blob of the launcher, and is replaced with
a nop.
The other patch, modifies the code responsible for reading the launcher title id from HWINFO.
The original code is as follow
@ this loads in r0 the buffer containing the contents read
@ from HWINFO_S, offsetted at the position of the title id
FC 05 9F E5 ldr r0, [pc, #0x5fc]
FC 15 9F E5 ldr r1, [pc, #0x5fc]
@ This reads the title id and then stores it to the address
@ pointed by r1, which is then used across the whole program
00 00 90 E5 ldr r0, [r0]
00 00 81 E5 str r0, [r1]
F4 05 9F E5 ldr r0, [pc, #0x5f4]
9d 01 00 EB bl #0x602a3c4
C5 FD FF EB bl #0x602946c
EC 05 9F E5 ldr r0, [pc, #0x5ec]
00 00 90 E5 ldr r0, [r0]
E8 15 9F E5 ldr r1, [pc, #0x5e8]
66 00 00 EB bl #0x6029f00
E4 05 9F E5 ldr r0, [pc, #0x5e4]
E4 15 9F E5 ldr r1, [pc, #0x5e4]
14 20 A0 E3 mov r2, #0x14
0C 09 00 EB bl #0x602c1a8
DC 05 9F E5 ldr r0, [pc, #0x5dc]
91 01 00 EB bl #0x602a3c4
BA FD FF EB bl #0x602946c
D4 05 9F E5 ldr r0, [pc, #0x5d4]
00 00 90 E5 ldr r0, [r0]
D0 15 9F E5 ldr r1, [pc, #0x5d0]
02 2C A0 E3 mov r2, #0x200
5B 00 00 EB bl #0x6029f04
C8 15 9F E5 ldr r1, [pc, #0x5c8]
E4 01 91 E5 ldr r0, [r1, #0x1e4]
72 08 00 EB bl #0x602bf6c
C0 15 9F E5 ldr r1, [pc, #0x5c0]
19 00 00 EB bl #0x6029e10
00 00 A0 E3 mov r0, #0
01 00 C1 E4 strb r0, [r1], #1
B4 05 9F E5 ldr r0, [pc, #0x5b4]
93 01 D0 E5 ldrb r0, [r0, #0x193]
01 00 C1 E4 strb r0, [r1], #1
FF 9F BD E8 pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, sb, sl, fp, ip, pc}
The patched code is
@ Instead of reading the title id from the HWINFO_S buffer,
@ read the hardcoded value placed at the bottom.
@ all the relative addresses have been incremented by 4 to account
@ for the shift of the instructions (same for the relative bl instructions)
7C 00 9F E5 ldr r0, [pc, #0x7c]
FC 15 9F E5 ldr r1, [pc, #0x5fc]
00 00 81 E5 str r0, [r1]
F8 05 9F E5 ldr r0, [pc, #0x5f8]
9D 01 00 EB bl #0x602a3c4
C6 FD FF EB bl #0x602946c
F0 05 9F E5 ldr r0, [pc, #0x5f0]
00 00 90 E5 ldr r0, [r0]
EC 15 9F E5 ldr r1, [pc, #0x5ec]
67 00 00 EB bl #0x6029f00
E8 05 9F E5 ldr r0, [pc, #0x5e8]
E8 15 9F E5 ldr r1, [pc, #0x5e8]
14 20 A0 E3 mov r2, #0x14
0D 09 00 EB bl #0x602c1a8
E0 05 9F E5 ldr r0, [pc, #0x5e0]
92 01 00 EB bl #0x602a3c4
BB FD FF EB bl #0x602946c
D8 05 9F E5 ldr r0, [pc, #0x5d8]
00 00 90 E5 ldr r0, [r0]
D4 15 9F E5 ldr r1, [pc, #0x5d4]
02 2C A0 E3 mov r2, #0x200
5C 00 00 EB bl #0x6029f04
CC 15 9F E5 ldr r1, [pc, #0x5cc]
E8 01 91 E5 ldr r0, [r1, #0x1e8]
73 08 00 EB bl #0x602bf6c
C4 15 9F E5 ldr r1, [pc, #0x5c4]
1A 00 00 EB bl #0x6029e10
00 00 A0 E3 mov r0, #0
01 00 C1 E4 strb r0, [r1], #1
B8 05 9F E5 ldr r0, [pc, #0x5b8]
97 01 D0 E5 ldrb r0, [r0, #0x197]
01 00 C1 E4 strb r0, [r1], #1
FF 9F BD E8 pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, sb, sl, fp, ip, pc}
41 41 4E 48 .word 0x484e4141
The patched code is found at address 0x60a7 in the decompressed binary, and is loaded into
ram at address 0x6029d38.
The lzss compressed arm7 payload is found at offset 0x8580 for unlaunch 2.0 with a length of 0x67FD.
Credits
- DevkitPro: devkitARM and libnds
- Martin Korth (nocash): GBATEK
- JeffRuLz/Epicpkmn11: TMFH/NTM (what this is project used as base for menus and other things)
- rvtr: Adding support for installing to dev/proto consoles and the ( ͡° ͜ʖ ͡°) icon