--- /dev/null
+Corbenik
+==============================
+
+## This is the README intended for people looking at the code. If you're a user, read `README.user.md` instead.
+
+This is (yet another) CFW for the 3DS. Unlike other CFWs, this was mostly written from scratch and for fun. I'm a control freak, and this carries quite a bit of my mindset being a LFS/Gentoo user.
+
+Some parts are inherited from other CFWs - e.g. the firmware loading code in `src/firm` is mostly based on Cakes, and the patch bytecode is based on Luma3DS' implementation in C (though it isn't really derived from it.)
+
+Out of the bunch of CFWs in existence, Corbenik is most similar to cakes of the bunch, in that it uses external patches. External patches are headered, can have dependencies, and consist of a lightweight and specialized bytecode/assembly which is intended solely for effiecient patching.
+
+See `doc/bytecode.md`, `host/bytecode_asm.py` and `patch/*` for more on this. The assembler is a bit crappy at the moment, and I *do* plan to improve it. However, it outputs the correct code and gets the job done.
+
+## Rationale
+
+I was initially going to make cakes dynamic, but I quickly realized a fatal flaw in any "patch" format: what you can do from a patch is limited to what the parser handles. With Cakes, converting to a dynamic method isn't terribly difficult, but what about the patches that have a 'find, then seek backwards until' type of logic? Cakes would need have another construct to decribe that, and at that point, the .cake format has become a kludge.
+
+In my opinion, the best way to fix this was to externalize patches as programs - arm binaries or bytecode. The former didn't go so well (look back in the history of this repo. Fun times) and I ended up going with the latter.
+
+I also had a number of mad science experiments which would be very hard to perform in the context of ReiNAND based firmwares, and Cakes wouldn't make it easy either due to its limited patch format.
+
+## Comparison
+
+If you want to know how Corbenik sizes up to other CFWs as of NOW - see `doc/features.md`. I don't intend to sugarcoat - Corbenik is under development and is incomplete. There will be no stable release until a number of common features are implemented, such as emunand.
+
+However! It does have a few legs up on other CFWs, namely:
+ * Injection of arbitrary ARM11 services, including svcBackdoor.
+ * Bytecode patches? Bytecode patches.
+ * Not only corbenik, but the loader replacement uses them too.
+ * Loader can resize titles in memory and append code to segments. This isn't well tested, and it isn't enabled.
+ * Pretty much every simple patch that Luma3DS has, and most every patch for loader.
+ * All of the common bits aside from EmuNand, Reboot, and the exception vector hook, basically.
+ * Loader is STILL smaller than Nintendo's by two units.
+ * Loader is a little slower to boot than Cakes, and loader takes negligibly longer to load stuff. I may be able to optimize more, but at this point it is fast enough to not impact me.
+
+Feedback is welcome, but don't report anything obvious in nightlies. Corbenik is my day-to-day CFW now, so I'll run into the same bugs as you.
+
+For compilation instructions, see `doc/compiling.md`.
+
+Unless otherwise noted, everything original in this repo can be used under the terms of the GNU GPLv3 or later. This includes situations where there's no copyright header within a source file. I get lazy with those; assume everything can be used under the GPLv3. No source files within this repo bear questionable licenses, I make sure when it is introduced.
+
+## Quote of the Day
+
+Welcome to "The World."
+
-Corbenik
-==============================
+About
+-------------------------
-This is (yet another) CFW for the 3DS. Unlike other CFWs, this was mostly written from scratch and for fun. I'm a control freak, and this carries quite a bit of my mindset being a LFS/Gentoo user.
+Corbenik is another CFW for the 3DS somewhat like cakes, but using
+bytecode-based patches. This allows for much greater flexibility.
-Some parts are inherited from other CFWs - e.g. the firmware loading code in src/firm is mostly based on Cakes, and the patch bytecode is based on Luma3DS' implementation in C (though, it isn't really derived from it)
+It's mainly intended for developers; so if you don't know your way
+around the 3DS, chances are this isn't for you.
-Out of the bunch of CFWs in existence, Corbenik is most similar to cakes of the bunch, in that it uses external patches. External patches are headered, can have dependencies, and consist of a lightweight and specialized bytecode/assembly which is intended soley for effiecient patching.
+Not every feature has been implemented/tested yet, but at the moment
+it offers a rather comprehensive SysNAND experience for N3DS users.
-See `doc/bytecode.md`, `host/bytecode_asm.py` and `patch/*` for more on this. The assembler is a bit crappy at the moment, and I *do* plan to improve it. However, it outputs the correct code and gets the job done.
+Corbenik is licensed under the terms of the GPLv3. Please obey it.
+You should have recieved a copy either as part of the git repository,
+or as part of the tarball/zipfile you downloaded. If not, get a copy
+here: `http://www.gnu.org/licenses/gpl-3.0.txt`
-## Rationale
+Installing
+-------------------------
-I was initially going to make cakes dynamic, but I quickly realized a fatal flaw in any "patch" format: what you can do from a patch is limited to what the parser handles. With Cakes, converting to a dynamic method isn't terribly difficult, but what about the patches that have a 'find, then seek backwards until' type of logic? Cakes would need have another construct to decribe that, and at that point, the .cake format has become a kludge.
+Copy the files to the root of your SD (and optionally, rename
+arm9loaderhax.bin and set it up with a bootloader.)
-In my opinion, the best way to fix this was to externalize patches as programs - arm binaries or bytecode. The former didn't go so well (look back in the history of this repo. Fun times) and I ended up going with the latter.
+Without the FIRMs, it cannot boot up your system. You'll need to
+fetch the following at minimum, and put it at `/corbenik/firmware/native`:
-I also had a number of mad science experiments which would be very hard to perform in the context of ReiNAND based firmwares, and Cakes wouldn't make it easy either due to its limited patch format.
+Old 3DS (Native FIRM, 11.0):
+ http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000002/00000052
+New 3DS (Native FIRM, 11.0):
+ http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000002/00000021
-## Comparison
+You'll need the firmkey for it as well unless you have decrypted it, which should
+be placed at `/corbenik/keys/native.key`. I can't tell you how to get it
+obviously, but a good place to start may be an older version of Plailect's guide
+when it still had a section on Cakes.
-If you want to know how Corbenik sizes up to other CFWs as of NOW - see `doc/features.md`. I don't intend to sugarcoat - Corbenik is under development and is incomplete. There will be no stable release until a number of common features are implemented, such as emunand.
+On New3DS units, there's additional crypto on arm9loader which requires the 9.6
+key to decrypt. It usually is named ``Slot0x11Key96.bin`, and I also can't tell
+you where to find this, aside from "check Plailect's guide." Corbenik will
+attempt to read this from the root as well as `/corbenik/keys/11.key`.
-However! It does have a few legs up on other CFWs, namely:
- * Injection of arbitrary ARM11 services, including svcBackdoor.
- * Bytecode patches? Bytecode patches.
- * Not only corbenik, but the loader replacement uses them too.
- * Loader can resize titles in memory and append code to segments. This isn't well tested, and it isn't enabled.
- * Pretty much every simple patch that Luma3DS has, and most every patch for loader.
- * All of the common bits aside from EmuNand, Reboot, and the exception vector hook, basically.
- * Loader is STILL smaller than Nintendo's by two units.
+Setup
+-------------------------
-That said, feedback is welcome, but don't report anything obvious. Chances are I know, since Corbenik is my day-to-day CFW now, and I'll run into the same bugs as you.
+For starters, you'll want to go into options and enable `System Modules` to get
+loader to run patches as well.
-For compilation instructions, see `doc/compiling.md`.
+If you're using 11.0 NATIVE_FIRM like I suggested, you'll want to tick
+`Service Replacement` to fix the broken svcBackdoor. Without this, Retroarch
+won't work - and other applications that do JIT also won't work.
-Unless otherwise noted, everything original in this repo can be used under the terms of the GNU GPLv3 or later. This includes situations where there's no copyright header within a source file. I get lazy with those; assume everything can be used under the GPL, or files were from software licensed GPLv2 or later (and thus are upgraded.) No source files within this repo bear questionable licenses.
+While you're there, you can enable `Autoboot` if you'd like, including
+`silent mode` if you're using something like BootAnim9.
-## Quote of the Day
+You'll also want to go into `Patches` and enable the usual bits, which includes:
-Welcome to "The World."
+ * Signature Fix
+ * FIRM Protect
+
+You'll also want these patches, which are done by loader and therefore require it:
+
+ * Block Cart Updates
+ * Block eShop Updates
+ * Block NIM updates
+ * Region free HOME
+ * RO signature fix
+
+If you're on 11.0, you also want these:
+
+ * Title Downgrade Fix
+
+If you're deliberately still running 10.4 or something, you'll want these:
+
+ * Fake Friends Version
+
+If you region changed your console and replaced SecureInfo_A, you want:
+
+ * SecureInfo_A Signature Fix
+
+Optional, but recommended patches are:
+
+ * MSET Version
+ * ErrDisp devmode
+
+And these YOU SHOULD NOT ENABLE unless you have specialized needs:
+
+ * Developer UNITINFO
+ * ARM11 XN Disable
+ * Force TestMenu
+
+Credits
+-------------------------
+
+This software contains code from multiple other open source projects, including:
+
+ @mid-kid/CakesForeveryWan - FIRM Decryptor
+
+ @AuroraWright/Luma3DS - Used as reference for patcher bytecode (and in earlier
+ versions, the patch code itself) The version of loader
+ in use also originated from the code here.
+
+ @d0k3/GodMode9 - FatFS version originates from here, start.s too.
+ Additionally, recursive directory removal and listing
+ patches is partially based on GodMode9.
+
+ @yifanlu - Loader.
+
+The complete "Thanks cool people" list:
+
+ @yifanlu For the absolutely insane and wonderful idea to use bytecode,
+ as well as the loader replacement.
+
+ @mid-kid General inspiration from Cakes.
+
+ @Wolfvak Go use BootAnim9.
+
+ @AuroraWright Luma made chunks of this possible.
+
+ @Reisyukaku You can thank him for the 'Force TestMenu' patch.
+
+ @d0k3 Mostly code. Oh, and Decrypt9WIP/GodMode9 too.
+
+ @smealum HANS code, and pioneering the open source hax frontier.
+
+ @TuxSH Lots of RE work and important commits to Luma that I rely on.
+
+ CyberConnect2 Because the name originates from .hack, which you should go play.
Feature graph
-----------------
+===================
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
-|CFW |Firms? |Patch Method |Supplies Officially |Available |Optimization[1]|Focus? |Notes |
+|CFW |Firms? |Patch Method |Supplies Officially |3rd Party |Optimization[1]|Focus? |Notes |
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
-|CakesFW |Dec/Enc (SD) |Loadable, Fixed |Sig,Emu(M),Twl,Agb,Sys,Ptc |Mis,Bck,Mod|Speed/Read |Devs/Advanced Users| [2] |
+|CakesFW |Dec/Enc (SD) |Loadable Fixed |S EN T G Y P R |L B U I F |Speed/Read |Devs/Advanced Users| [2] |
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
-|Luma3DS |Enc(NAND) Dec(SD)|Builtin, Dynamic |Sig,Emu(2),Sys,Mod,Bck,Mis,Ptc|N/A |Giant Mess |"Noob-proof" | [3] |
+|Luma3DS |Enc(NAND) Dec(SD)|Builtin Dynamic |S E2 Y L B P U X R |N/A |Speed |"Noob-proof" | [3] |
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
-|ReiNAND |Meme(SD) |Builtin, Dynamic |Sig,Emu,Sys,Mod,Ptc |N/A |Readability |Minimalist | [4] |
+|ReiNAND |Meme(SD) |Builtin Dynamic |S E1 L P F Y R |N/A |Readability |Minimalist | [4] |
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
-|Corbenik|Dec/Enc (SD) |Builtin, Dynamic |Sig,Ptc,Sys,Mod,Bck,Mis |N/A |Read/Speed |Advanced Devs | [5] |
+|Corbenik|Dec/Enc(SD) |Loadable Bytecode|S P Y L B F U X | |Read/Speed |Advanced Devs | [5] |
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
-|NTR |N/A |Executable |Mis |Mis |Douchebaggery |Shilling Closed Src| [6] |
+|NTR |Hook |ARM11 Binaries |X F |X |Closed Src? |Being Dead | [6] |
+--------+-----------------+-----------------+------------------------------+-----------+---------------+-------------------+-------+
- * Sig: Signature Patch.
- * Twl: TWL Signature Patch
- * Agb: AGB Signature Patch
- * Ptc: FIRM protection
- * Emu: Emunand.
- * (M) - Can have many (unlimited)
- * (X) - Can have X emunands.
- * Sys: Can boot sysnand from a9lh.
- * Mod: Loader replacement
- * Bck: Load svcBackdoor on 11.0
- * Mis: Other misc fixes and alterations including:
- * UNITINFO patch
- * GBA bios screen
- * Region-free
+ * R: Reboot patch
+ * S: Basic Signature Patch
+ * T: TWL Signature Patch
+ * G: AGB Signature Patch
+ * P: FIRM protection
+ * E: Emunand.
+ * N - Can have many (unlimited)
+ * X - Can have X emunands.
+ * Y: Can boot sysnand from a9lh.
+ * L: Loader replacement
+ * B: Load svcBackdoor on 11.0
+ * U: UNITINFO
+ * I: GBA BIOS screen
+ * F: Region free
+ * X: Extras that are not general features listed above
Misc features by CFW:
- * Cakes:
+ * Cakes
* mid-kid/lgy_cakes
* TWL patches
* AGB patches
* You have multiple choices. Wolfvak's, mid-kid's, mine, etc...
* Wolfvak/icing
* UNITINFO
- * svcBackdoor (incomplete)
+ * svcBackdoor (o3DS only)
* Luma
* Loader replacement. CPU speed/language emulation
+ * ARM11 XN Clear (dev)
+ * Exception vector hook (dev)
* Corbenik
* Arbitrary service injection to empty slots.
- Similar results can be achieved in cakes, but with much pain.
- I've yet to find a use for this, but it's certainly neat.
- * Arbitrary sysmodule injection.
- * Loader replacement - loosely based on Luma3ds' with some significant
- alterations.
- * Again, shit will be moved someday soon to externals.
+ * Loader replacement. Uses patch files.
+ * Baked in: langemu (based on Luma)
+ * Baked in: CPU speed change
+ * ARM11 XN Clear
+ * Alternate menu force (courtesy @Reisyukaku)
[1] I'm not just referring to speed; I'm referring to purpose-based optimization. For example;
do you want something well documented? Would you choose a slower algorithm that can be more
easily debugged at the expense of speed? Would you use preprocessor macros to use different implementations?
- CakesFW is Speed/Read. Speed first, keep readability if possible whenever possible. Which is a good
- approach.
+ CakesFW is Speed/Read. It's hit and miss on documentation, but of the bunch, cakes is the best documented.
- No, I don't call Luma a complete mess lightly. Go look thorugh the code. You back? Good. Tell me,
- are the comments helpful and do you understand what the blatant pointer abuse in patches.c is
- actually ref'ing? No? I had to decode that. It's referencing the exefs's code section. Which was
- impossible to tell without ten minutes staring at it. Moving on now...
+ Luma uses very fast code to do its thing. The source, however, lacks documentation, and some things done
+ are not self-evident without analysis. The amount of pointer math rather than structs is astounding.
ReiNAND is cruft-free and well documented. It doesn't do a lot, but what it does do, it does well.
Unix philosphy in a nutshell. The only complaint is memekey.
My focus will always be readability over speed, unless choosing speed and adding additional documentation
suffices. As an aside; if you see a single trigraph in my code, please report it. Trigraphs are by design a bug.
-[2] CakesFW uses a patch format that has static offsets. They're loaded off FS and in theory are impervious
- to updates. In practice, updating patches is a pain and better done by offset patches like Luma3DS/Rei.
+[2] CakesFW uses a patch format that has static offsets. They're loaded off SD and _in theory_ are impervious
+ to updates. Memory patches in cakes are kind of a kludge, though.
+
+ In practice, updating patches is a pain and better done by offset patches like Luma3DS/Rei.
Either way, Cakes allows doing some things the other firmware authors would probably call idiotic; I call them
smart since I get a choice. Cakes is lacking a few things from Luma3DS mainly because (in my opinion) the patch
- format is incapable of accomodating some changes in a sane manner that doesn't require excessive RE or on console
- one off offset checks.
+ format is problematic and not really future proof or extensible.
-[3] Luma is a weird beast - "Noob-proof" as github states very perfectly describes it for better or worse. It can do
+[3] "Noob-proof" as github states very perfectly describes it for better or worse. It can do
a lot, has a very good focus on what it wants to do and probably works good enough for 90% of users. It handles
- the vast majority of use cases well and sanely.
-
- Some internal bits aren't exposed as configurable because turning them off is bad for the inexperienced. This is both
- good and bad. On the upside, less brick complaints. On the downside, it loses some power for hacker-ish people who
- know what they're doing and have odd requirements.
+ the vast majority of use cases well and sanely. You will never brick with Luma, but by the same
+ token, a number of options aren't exposed to prevent users shooting themselves in the foot.
- As I've been told by @TuxSH - "Noob-proof" != Just for noobs. I find that "Noob-proof" as a goal tends to somewhat
- limit the people who truly understand what they're doing, however, in any software - not just Luma.
+ As I've been told by @TuxSH - "Noob-proof" != Just for noobs. I agree. I do find that "Noob-proof" as a goal
+ tends to somewhat limit the people who truly understand what they're doing. This isn't a bad thing.
+ Simply a design choice.
- My only real complaint about Luma is the sheer amount of pointer math instead of reading headers correctly.
+ My only real complaint about Luma is the sheer amount of pointer math instead of reading headers correctly,
+ and the more-than-slightly evangelical mindset of some users.
[4] Reisyukaku has fallen behind a bit; his firmware is still in use and rather slim. He does, however, do some fancy
ass magic to load a re-encrypted copy (?) of the nintendo firmware using a key refered to as the 'memekey'. How
[5] Yes, Corbenik currently lacks quite a few things from this graph. Quite. A. Few. This will change with time.
-[6] Okay, first - I could rant about how NTR is harming us long run for hours. I won't rant for hours, but I will
+[6] Okay, first - I could rant about how NTR was harming us long run for hours. I won't rant for hours, but I will
explain some of the rationale here:
NTR is a secondary CFW; it's designed to be used with a primary one. It consists of a proprietary blob, ntr.bin
- which loads into memory with some offset patches done by BootNTR - then takes over the debug service and
- subsequently the arm11 kernel and threading to keep itself resident[7].
+ which loads into memory with some offset patches done by BootNTR - then takes over the debug service(?) and
+ subsequently the arm11 kernel and spawns a thread in HOME to keep itself resident[7].
Normally, the functionality would be useful, but when you consider he's using techniques he hasn't bothered to doc
- on 3dbrew, you should by now know his goal is lock-in. From BootNTR it's apparent he's a shitty coder[8]. He
- won't document it, because someone else will create a better optimized version. Hm...that sounds a lot like a
- certain Japanese company who developed a cons- oh wait.
+ on 3dbrew, you should by now know his goal is lock-in. From BootNTR and layeredFS it's also apparent he's a
+ shitty coder[8].
- The point is; NTR is not your friend. Stop using it.
+ He also quit development because people kept pestering him for source. I understand his rationale, but do you
+ really want to use software by someone who will throw up his arms and say 'fuck you' at a moment's notice
+ due to a few bad eggs?
+
+ The point is; NTR is not your friend. It's unmaintained, and nobody but him can continue it due to
+ the source code issue. Stop using it.
[7] At least from what I can tell. See https://github.com/patois/NTRDisasm. This is an out of date version, as well.
+ I have no idea how accurate I am here. I'd have to run NTR through a debugger.
+
+[8] Tell me that giant switch statement in BootNTR couldn't be implemented as a dynamic patcher on the 3DS itself,
+ considering all of the python offset extractor code could be rewritten in C. Dare you. He also can't be bothered
+ to port to 10.4 NATIVE_FIRM even though there's literally no difference that should break NTR.
-[8] Tell me that giant switch statement couldn't be implemented as a dynamic patcher on the 3DS itself, considering
- all of the python offset extractor code could be rewritten in C. Dare you. He also can't be bothered to port to 10.4
- NATIVE_FIRM even though there's literally no difference that should break NTR.
+ And don't even get me started on layeredFS - again, python code that could be a dynamic patcher on console.
struct patch_state
{
- char filename[255];
+ char filename[256];
uint8_t state;
} __attribute__((packed));
struct options_s
{
- int index;
+ int64_t index;
char name[64];
+ char desc[256];
enum type allowed;
uint32_t a, b;
} __attribute__((packed));
int cursor_max = -1;
int exit = 0;
+ if (options[0].index == -1) {
+ set_cursor(TOP_SCREEN, 0, 0);
+ header("Any:Back");
+ fprintf(stdout, "No entries.\n");
+ wait_key();
+ return 0;
+ }
+
while(!exit) {
- set_cursor(TOP_SCREEN, 0, 0);
+ set_cursor(TOP_SCREEN, 0, 0);
// Figure out the max if unset.
if (cursor_max == -1) {
#define FCRAM_START 0x24000000
// firm.c
-// 24
-#define FCRAM_FIRM_LOC FCRAM_START
-// 241
-#define FCRAM_TWL_FIRM_LOC (FCRAM_START + FCRAM_SPACING) // Double size
-// 242
-#define FCRAM_AGB_FIRM_LOC (FCRAM_START + FCRAM_SPACING * 3)
-
-// 243
-// patch.c
-#define FCRAM_PATCH_LOC (FCRAM_START + FCRAM_SPACING * 4)
-
-// 244
+#define FCRAM_FIRM_LOC FCRAM_START
+#define FCRAM_TWL_FIRM_LOC (FCRAM_FIRM_LOC + FCRAM_SPACING) // Double size
+#define FCRAM_AGB_FIRM_LOC (FCRAM_TWL_FIRM_LOC + FCRAM_SPACING * 2)
+
+// Location patches get loaded to.
+#define FCRAM_PATCH_LOC (FCRAM_AGB_FIRM_LOC + FCRAM_SPACING * 2)
+
// Throwaway temporary space. Don't expect it to stay sane.
-#define FCRAM_JUNK_LOCATION (FCRAM_START + FCRAM_SPACING * 5)
+#define FCRAM_JUNK_LOC (FCRAM_PATCH_LOC + FCRAM_SPACING)
+
+// Path that the patch menu is created at.
+#define FCRAM_MENU_LOC (FCRAM_JUNK_LOC + FCRAM_SPACING)
+
+// Path that the patch enable list is located at.
+#define FCRAM_PATCHLIST_LOC (FCRAM_MENU_LOC + (FCRAM_SPACING / 2))
#endif
#define MENU_POWER 7
#define MENU_BOOTME 8
+#define MAX_PATCHES ( ( FCRAM_SPACING / 2) / sizeof(struct options_s) )
+struct options_s *patches = (struct options_s*)FCRAM_MENU_LOC;
+uint8_t* enable_list = (uint8_t*)FCRAM_PATCHLIST_LOC;
+
static struct options_s options[] = {
// space
- { 0, "", not_option, 0, 0 },
+ { 0, "", "", not_option, 0, 0 },
// Patches.
- { 0, "\x1b[32;40mPatches\x1b[0m", not_option, 0, 0 },
-
- { OPTION_SIGPATCH, "Signature Patch", boolean_val, 0, 0 },
+ { 0, "\x1b[32;40mOptions\x1b[0m", "", not_option, 0, 0 },
- { OPTION_FIRMPROT, "FIRM Protection", boolean_val, 0, 0 },
+ { OPTION_LOADER, "System Modules", "Replaces system modules (including loader)", boolean_val, 0, 0 },
+ { OPTION_LOADER_CPU_L2, " CPU - L2 cache", "Forces the system to use the L2 cache. Ignored if not a N3DS.", boolean_val, 0, 0 },
+ { OPTION_LOADER_CPU_800MHZ, " CPU - 800Mhz", "Forces the system to run in 800Mhz mode. Ignored if not a N3DS.", boolean_val, 0, 0 },
+ { OPTION_LOADER_LANGEMU, " Language Emulation", "Reads language emulation configuration and imitates the region/language.", boolean_val, 0, 0 },
- { OPTION_LOADER, "System Modules", boolean_val, 0, 0 },
- { OPTION_LOADER_CPU_L2, " CPU - L2 cache", boolean_val, 0, 0 },
- { OPTION_LOADER_CPU_800MHZ, " CPU - 800Mhz", boolean_val, 0, 0 },
- { OPTION_LOADER_LANGEMU, " Language Emulation", boolean_val, 0, 0 },
+ { 0, "", "", not_option, 0, 0 },
- { OPTION_SERVICES, "Service Replacement", boolean_val, 0, 0 },
+ { OPTION_SERVICES, "Service Replacement", "Replaces ARM11 services, including svcBackdoor. With 11.0 NATIVE_FIRM, you need this.", boolean_val, 0, 0 },
- { OPTION_AADOWNGRADE, "Anti-anti-downgrade", boolean_val, 0, 0 },
+ { 0, "", "", not_option, 0, 0 },
- // space
- { 0, "", not_option, 0, 0 },
- // Patches.
- { 0, "\x1b[32;40mPatches (Developer)\x1b[0m", not_option, 0, 0 },
+ { OPTION_AUTOBOOT, "Autoboot", "Boot the system automatically, unless the R key is held.", boolean_val, 0, 0 },
+ { OPTION_SILENCE, " Silent mode", "Suppress all debug output during autoboot. You'll see the screen turn on, then off.", boolean_val, 0, 0 },
- { OPTION_UNITINFO, "Developer UNITINFO", boolean_val, 0, 0 },
- { OPTION_MEMEXEC, "Disable XN on MPU", boolean_val, 0, 0 },
- { OPTION_REPLACE_ALLOCATED_SVC, "Force service replace", boolean_val, 0, 0 },
+ { 0, "", "", not_option, 0, 0 },
- // { OPTION_ARM9THREAD, "ARM9 Thread", boolean_val, 0, 0 },
+ { OPTION_READ_ME, "Hide `Help`", "Hides the help option from the main menu.", boolean_val, 0, 0 },
// space
- { 0, "", not_option, 0, 0 },
+ { 0, "", "", not_option, 0, 0 },
// Patches.
- { 0, "\x1b[32;40mOptions\x1b[0m", not_option, 0, 0 },
-
- { OPTION_AUTOBOOT, "Autoboot", boolean_val, 0, 0 },
- { OPTION_SILENCE, " Stealth mode", boolean_val, 0, 0 },
- { OPTION_TRACE, "Debug pauses during operation", boolean_val, 0, 0 },
- { OPTION_OVERLY_VERBOSE, "Over-the-top verbosity", boolean_val, 0, 0 },
+ { 0, "\x1b[32;40mDeveloper Options\x1b[0m", "", not_option, 0, 0 },
- // { OPTION_TRANSP_BG, "Black -> transparent", boolean_val, 0, 0 },
- // { OPTION_NO_CLEAR_BG, "Preserve framebuffer", boolean_val, 0, 0 },
-
- { OPTION_READ_ME, "Hide `Help`", boolean_val, 0, 0 },
+ { OPTION_REPLACE_ALLOCATED_SVC, "Force service replace", "Replace ARM11 services even if they exist. Don't use unless you know what you're doing.", boolean_val, 0, 0 },
+ { OPTION_TRACE, "Debug Pauses", "After each important step, [WAIT] will be shown and you'll need to press a key. Debug.", boolean_val, 0, 0 },
+ { OPTION_OVERLY_VERBOSE, "Verbose", "Output more debug information than the average user needs.", boolean_val, 0, 0 },
+ // { OPTION_ARM9THREAD, "ARM9 Thread", boolean_val, 0, 0 },
// { IGNORE_PATCH_DEPS, "Ignore dependencies", boolean_val, 0, 0 },
// { IGNORE_BROKEN_SHIT, "Allow unsafe options", boolean_val, 0, 0 },
// Sentinel.
- { -1, "", 0, -1, -1 }, // cursor_min and cursor_max are stored in the last two.
+ { -1, "", "", 0, -1, -1 }, // cursor_min and cursor_max are stored in the last two.
};
static int cursor_y = 0;
fprintf(stdout, "\x1b[30;42m.corbenik//%s %s\x1b[0m\n", VERSION, append);
}
+static int current_menu_index_patches = 0;
+
+// This function is based on PathDeleteWorker from GodMode9.
+// It was easier to just import it.
+int list_patches_build_back(char* fpath, int desc_is_path) {
+ FILINFO fno = {.lfname = NULL};
+
+ // this code handles directory content deletion
+ if (f_stat(fpath, &fno) != FR_OK)
+ return 1; // fpath does not exist
+
+ if (fno.fattrib & AM_DIR) { // process folder contents
+ DIR pdir;
+ char* fname = fpath + strnlen(fpath, 255);
+ if (f_opendir(&pdir, fpath) != FR_OK)
+ return 1;
+
+ *(fname++) = '/';
+ fno.lfname = fname;
+ fno.lfsize = fpath + 255 - fname;
+
+ while (f_readdir(&pdir, &fno) == FR_OK) {
+ if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
+ continue; // filter out virtual entries
+ if (fname[0] == 0)
+ strncpy(fname, fno.fname, fpath + 255 - fname);
+ if (fno.fname[0] == 0)
+ break;
+ else // return value won't matter
+ list_patches_build_back(fpath, desc_is_path);
+ }
+
+ f_closedir(&pdir);
+ *(--fname) = '\0';
+ } else {
+ struct system_patch p;
+ read_file(&p, fpath, sizeof(struct system_patch));
+
+ if (memcmp(p.magic, "AIDA", 4))
+ return 0;
+
+ strncpy(patches[current_menu_index_patches].name, p.name, 64);
+ if (desc_is_path)
+ strncpy(patches[current_menu_index_patches].desc, fpath, 255);
+ else
+ strncpy(patches[current_menu_index_patches].desc, p.desc, 255);
+ patches[current_menu_index_patches].index = p.uuid;
+ patches[current_menu_index_patches].allowed = boolean_val;
+ patches[current_menu_index_patches].a = 0;
+ patches[current_menu_index_patches].b = 0;
+ if (desc_is_path)
+ enable_list[p.uuid] = 0;
+
+ current_menu_index_patches++;
+ }
+
+ return 0;
+}
+
+void list_patches_build(char* name, int desc_is_fname) {
+ current_menu_index_patches = 0;
+
+ char fpath[256];
+ strncpy(fpath, name, 256);
+ list_patches_build_back(fpath, desc_is_fname);
+ patches[current_menu_index_patches].index = -1;
+
+ read_file(enable_list, PATH_TEMP "/PATCHENABLE", FCRAM_SPACING / 2);
+}
+
+int show_menu(struct options_s *options, uint8_t* toggles);
+
int
menu_patches()
{
+ list_patches_build(PATH_PATCHES, 0);
+
+ show_menu(patches, enable_list);
+
+ // Remove old settings, save new
+ f_unlink(PATH_TEMP "/PATCHENABLE");
+ write_file(enable_list, PATH_TEMP "/PATCHENABLE", FCRAM_SPACING / 2);
+
+ // TODO - Determine whether it actually changed.
+ config.options[OPTION_RECONFIGURED] = 1;
+
return MENU_MAIN;
}
-int show_menu(struct options_s *options, uint8_t* toggles);
-
int
menu_options()
{
}
uint32_t size = fsize(f);
- fread((uint8_t *)FCRAM_JUNK_LOCATION, 1, size, f);
+ fread((uint8_t *)FCRAM_JUNK_LOC, 1, size, f);
fclose(f);
// Look for the section that holds all the sysmodules
return 1;
}
- ncch_h *module = (ncch_h *)FCRAM_JUNK_LOCATION;
+ ncch_h *module = (ncch_h *)FCRAM_JUNK_LOC;
ncch_h *sysmodule = (ncch_h *)((uint32_t)firm_loc + sysmodule_section->offset);
// Check if we want to replace an existing sysmodule
#include "patch_file.h"
-/* Not possible to do bytecode here, sadly. */
-
-// This patch handles replacement of services. This includes backdoor, but not
+// This code handles replacement of services. This includes backdoor, but not
// just backdoor.
// Any service can be replaced provided there's enough space within the
// exception page.
continue;
}
+ // TODO - We can just fread directly to freeSpace with a little reordering.
+
uint32_t size = fsize(data);
- uint8_t *read_to = (void *)FCRAM_JUNK_LOCATION;
+ uint8_t *read_to = (void *)FCRAM_JUNK_LOC;
fprintf(stderr, "Svc: %s, %d bytes\n", at, size);
extern int doing_autoboot;
+extern uint8_t* enable_list;
+
void
wait()
{
fprintf(stderr, "\r \r");
}
+void list_patches_build(char* name, int desc_is_fname);
+
int generate_patch_cache() {
// Remove cache
rrmdir(PATH_LOADER_CACHE);
f_mkdir(PATH_LOADER_CACHE);
- wait();
-
- // Loader only uses TID cache bytecode, so run through these.
- execb(PATH_PATCHES "/block_nim_update.vco", 1);
- execb(PATH_PATCHES "/block_eshop_update.vco", 1);
- execb(PATH_PATCHES "/block_cart_update.vco", 1);
- execb(PATH_PATCHES "/errdisp.vco", 1);
- execb(PATH_PATCHES "/friends_ver.vco", 1);
- execb(PATH_PATCHES "/mset_str.vco", 1);
- // execb(PATH_PATCHES "/ns_force_menu.vco");
- execb(PATH_PATCHES "/regionfree.vco", 1);
- execb(PATH_PATCHES "/secinfo_sigs.vco", 1);
- execb(PATH_PATCHES "/ro_sigs.vco", 1);
-
- wait();
-
- // Use builtin signature patcher?
- if (config.options[OPTION_SIGPATCH]) {
- // TODO - Patch menu. This is okay-ish for now.
- if (execb(PATH_PATCHES "/sig.vco", 1)) {
- abort("Fatal. Sigpatch has failed.");
- }
-
- wait();
- }
-
- if (config.options[OPTION_FIRMPROT]) {
- if (execb(PATH_PATCHES "/prot.vco", 1)) {
- abort("Fatal. Firmprot has failed.");
- }
+ list_patches_build(PATH_PATCHES, 1);
- wait();
- }
+ struct options_s *patches = (struct options_s*)FCRAM_MENU_LOC;
- if (config.options[OPTION_AADOWNGRADE]) {
- if (execb(PATH_PATCHES "/aadowngrade.vco", 1)) {
- abort("Anti-anti-downgrade patch failed.");
- }
+ for(int i=0; patches[i].index != -1; i++) {
+ if (enable_list[patches[i].index]) {
+ // Patch is enabled. Cache it.
+ if(execb(patches[i].desc, 1)) {
+ abort("Failed to apply:\n %s\n", patches[i].name);
+ }
- wait();
- }
-
- if (config.options[OPTION_UNITINFO]) {
- if (execb(PATH_PATCHES "/unitinfo.vco", 1)) {
- abort("UNITINFO patch failed.");
- }
-
- wait();
- }
-
- if (config.options[OPTION_MEMEXEC]) {
- if (execb(PATH_PATCHES "/memexec.vco", 1)) {
- abort("MPU execution patch failed.");
- }
-
- wait();
- }
+ wait();
+ }
+ }
return 0;
}