3DS reverse engineering

Discussion of development of software for any "obsolete" computer or video game system.
nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Tue Jan 21, 2020 10:43 pm

tepples wrote:
Tue Jan 21, 2020 6:39 pm
Would it help to put the two diodes in parallel? I imagine that way they'd at least give the same voltage drop, but half the current would be passing through each.
That would be about same voltage drop as one diode (half drop of two diodes in series). And I have heard that two diodes in parallel is frowned upon: In theory it should split the amperes. But in practice the diode with slightly less resistance will get more amperes (if you try to pass 2A through two 1A diodes in parallel, then one of them will overheat and blow up, and then the other diode will jump in, and overheat and blow up, too) (but it might work better when passing only 1A through two 1A diodes in parallel).
lidnariq wrote:
Tue Jan 21, 2020 6:48 pm
It'd let them run cooler, yes, as long as they're far enough away from each other. They'll heat each other if they're right on top of each other. (Two adjacent diodes still can handler more heat dissipation than a single diode.)
Ah, yes, the diodes in series were close together, too. So they may have heated-up each other. I am now using only one diode, which feels less hot (and gives blue power LED, instead of the blinking red power LED).

The occassional power-off was caused by not having the bottom case attached: The lower backlight cable is very touch-sensitive (the console tends to power-off when touching the cable, or if the console/cable is resting on a table then just touching the console is getting critical) (no, I am not shortcutting it by putting it on a metal table, I guess the connector is just losing contact for a moment when moving the cable).

Power consumption when injecting supply directly to the battery pins is still 0.14A (when the console is switched off). So I do now know that the amperes are getting lost "somewhere on the mainboard" (not in the charger circuit).

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Tue Feb 04, 2020 4:00 pm

I am now trying to damage (or not to damage) the MCU. I've written an assembler for the RL78 instruction set, and looked up different MCU firmware versions (there are quite some differences for code and data addresses, including whether variables are accessed via short addresses or not). To deal with taht, I've written a bunch for functions for searching known code snippets in different firmware versions, and for patching them accordingly. In theory it's almost ready for use, or if I got something wrong... then I could still desolder all chips and use the damaged mainboard to draw a new3ds-xl schematic : )

If the MCU survives patching then the console will directly respond to power-button keystrokes without needing the current polling-trickery. And it should be possible to reduce the hardcoded 3 second hold-power-button delay to something more reasonable; and thereafter, it could either power-off instantly, or at least switch the power-led to purple color; so that the user knows that the console will power-down, and that one can now release the power button.

The other patch feature will be a "jump to ram" function, so one can execute any kind of custom code, eg. for dumping MCU registers and memory.

I have been thinking a bit more about whether or not needing the evil delay after holding the power button. If the console has crashed then the delay is useless... but if only the game has crashed, then the OS might still be able to do some important cleanup during the delay. If that's actually the case depends on whether nintendo has implemented any such features in the OS code (eg. ignore the hanging game, and force closing all files and updating fat/directory entries). I have no idea if the OS can do that...?

While looking at the MCU's power-button code, I've had a closer look at the timings. The button handler is triggered by INTRTCI interrupts, which are set to 32768Hz/64 = 512Hz, and which are then further divided by 4 in the power-button handler. So the timebase is 128Hz (although nintendo's code seems to be using a logical unit of 125Hz for it, eg. the 3 second delay is 3*125 ticks).
The value in MCU[24h] is further divided by 16, so that's counted in 8Hz units. The default is MCU[24h]=5Dh, or 93 decimal, that would be 93/8Hz = 11.625 seconds. Hmmm, but the theory was that the power down occurs after 7 seconds. I have never verified that with a stop watch though. Maybe the 7 seconds was yet too optimistic, and it's actually 4.623 seconds slower than that. Or maybe the OS changes the MCU[24h] default setting later on during boot?

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Wed Feb 05, 2020 1:49 pm

Hmmmm, that was almost too easy to destroy the console, but it seems to be dead now : /

I've used the original firmware image, and changed only the last byte of the three "HH:MM:SS",00h IDs (changed 00h to "q"), and the MCU[01h] version.lsb (changed 38h to 78h). And then uploaded it by writing 4003h bytes to MCU[05h and up]. After about 2 seconds, my program displayed "Okay", and then the console powered off after a brief moment (which should be right because the MCU reboots after reflashing).

But now, it won't power up anymore. It does merely blink the power led red (after supplying battery power), and holding the power-button for 2 seconds causes the power led to go black forever (until resupplying battery power). That behaviour is caused by this code in the MCU boot procedure:

Code: Select all

 verify_hhmmss_of_current_firmware
 if bad,
   verify_hhmmss_of_firmware_backup_copy
   if also bad,
     blink red power led, and shutdown via stop opcode when holding pwr button for 2 seconds
   else,
     restore firmware_backup_copy
So, apparently the current firmware AND backup copy are BOTH destroyed. I didn't even knew that that would be possible... that makes me wonder if there is a serious bug in nintendo's backup feature.

As for what went wrong in general... maybe writing 4003h bytes in one pass was wrong? Erasing seems to be done in 400h-byte units, and writing in 100h-byte units. So maybe one needs to split the 4003h bytes into several snippets; with "device,index,data(3)" in first part, and then "device,data(100h or 400h)" in further parts? Or whatever.
Even if the writes got corrupted, the code for the led blinking and power button handling seems to be still intact; but there seems to be no way to recover from that behaviour.

Going by the datasheet it should be possible to reflash the chip via external 1-wire UART and MODE pin. But it's probably difficult to find that two pins among of the hundreds of test points on the mainboard.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Thu Feb 06, 2020 3:48 pm

I've reviewed the MCU firmware code. Writing 4003h bytes as continous block seems to have been right.

STOP conditions
Sending STOP conditions anywhere inside of the 4000h byte block would abort flash writing, a STOP condition on LAST byte would "abort", too, but that might still work okay since it was the last byte anyways (I am not 100% sure if it would abort before or after the last byte, so it may be safer to send all bytes (including last byte) without stop condition).
Sending a STOP condition after the leading 3 bytes shouldn't be needed, and it would probably rather screw up things (or at least would make it much more difficult to safely send the following 4000h bytes). So, best don't use any STOP conditions at all.

Delays
A delay after the leading 3 bytes doesn't seem to be required. The 4000h-byte transfer function is "enqueued as callback" (but the normal I2C interrupt is disabled immediately upon receiving the 3-byte flash ID, so the databytes should safely arrive in the callback function, even if the callback got started a bit later than having sent the first data byte). Delays before/during flashing are probably automatically handled via SCL-hold on the I2C bus. So additional manual delays shouldn't be needed (and any LONG delays could be fatal because they would cause the MCU's watchdog to reboot during flashing).

So far, everything looks fine...

Uhm, but I've made a stupid mistake in my uploader when updating the new "HH:MM:SS",00h timestamps:

Code: Select all

 mov  r0,'q'     ;new last byte for the "HH:MM:SS",00h timestamps
 ldr  r2,=mcu_image+0ff6h+8           ;\
 mov  r1,3000h                        ; store
 strb r0,[r2,r1]     ;[4FF6h+N-1000h] ; (3x)
 strb r1,[r2,0Ah]    ;[2000h+N-1000h] ;
 strb r0,[r2]        ;[0FF6h+N]       ;/
That should have stored thrice "r0" (not "r1"). The "r1" was there because I had copied the check/compare code, and merely changed "ldrb" to "strb", without changing the "r1" register number... so well, it's been just lazyness.

The related bug on Nintendo's side is that their flash function does check ONLY the ID's at [4FF6h+N] and [1FF6h+N] (the latter one later getting swapped to [0FF6h+N]). But coincidentally, their flash function doesn't check [2000h+N], so the flash function continues with swapping the 4K at 01000h and 00000h (with proper error-detection, they would have instead wanted to restore the 12K backup from 5000h to 2000h).
What is happening now is that my uploaded code is neatly installed at 0000h (first 4K) and at 2000h (other 12K), but hangs because the boot procedure checks all three IDs, including the bugged one at [2000h+N].
At that point it should also restore the backup (and maybe it did actually do so). I think the problem there is that it does merely copy 12K from 5000h to 2000h (but forgets to swap the 4K at 00000h and 01000h, so the current firmware becomes a mixup of old+new version (and the backup also becomes a similar mixup of new+old version)).

Conclusion: The "strb r1" was lazy, and it was bad luck that I had written it to [2000h+N]. Writing wrong data to [4FF6h+N] or [0FF6h+N] instead of [2000h+N] would have probably triggered the intended error handling.
When avoiding that specific mistake...
I think that MCU flashing should be perfectly safe.
Or if it goes wrong... having more bricked consoles could be pretty valuable for drawing schematics. Especially the Old3DS mainboards with text layer would be pretty nice to have for that purpose. Just don't brick New3DS-XL's, because I have already done that myself ; )

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Fri Feb 07, 2020 8:42 am

Damn, I really want to get rid of using this broken console with japanese gui, and I had hoped that I could now get/buy a normal working english console like everyone else... but no, I guess I`ll be stuck with it some more time : /

Looking at the mainboard, there are those eye-catching test points with solder stop layer instead of gold contacts. And the 3dbrew "Pinouts" page does also clearly state that those solder points are wired to the relevant pins for reflashing the mcu firmware. The pinouts are described in "78K0R/KC3-L, 78K0R/KE3-L" datasheet, and the programming protocol in the "78K0R/Kx3-L Flash Memory Programming" application note. That looks as all info is available, and it isn't so difficult to unbrick MCUs...?

Pokun
Posts: 1324
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 3DS reverse engineering

Post by Pokun » Fri Feb 07, 2020 10:32 am

What? I've been using a Japanese 3DS LL all this time. Decided on it ever since I heard it was going to be region locked, no way I'm missing out on Japanese games because of some region lockout.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Fri Feb 07, 2020 3:14 pm

Sorry. I should have said language barrier in general. I somewhat got the console donated as "the gui supports japanese only but you can take apart the mainboard for hacking if you want to have it". The region lock is also part of the reason why I've never had any gaming experience on that console, but I am mainly interested in rev-engineering anyways... though I am a bit curious how it would feel like to play a stereoscopic game... I guess the effect could look quite spectacular at first glance... but might wear off quickly?

profi200
Posts: 29
Joined: Fri May 10, 2019 4:48 am

Re: 3DS reverse engineering

Post by profi200 » Sat Feb 08, 2020 7:31 am

It's not like i didn't warn you about MCU firmware flashing :wink: I would not call this safe at all. 1 mistake and it's a expensive brick as you demonstrated above. I have no idea if this is recoverable (in practice) and how much effort it is to get working again.

Why can't you buy a used 3DS? Should be doable with the patreon money.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Feb 09, 2020 8:25 pm

I am seeing the bricking more positive, it seems that the data has been written successfully from first timestamp, up to including the last timestamp at the end of the firmware image (otherwise the brick wouldn't have occured), so I think that I have proven tbat writing isn't a problem at all.

The only problem was me screwing up the middle timestamp, plus nintendo screwing up to verify that middle timestamp before applying the written data. That's a very rare and unfortunate combination of bugs, and it's almost impossible that such a thing could ever happen again.

Unbricking via serial cable is making some progress. The signals are 1.8V with bidirectional data line... most of my uarts are +/-12V and most of my parallel ports are 5V, after considering max232's and transitors and mosfets and whatever... I have dropped the bidirectional functionality (replies could be useful, but one could also ignore them), and simply used a schottky diode for the data line, and another one for reset signal, both wired to a parallel port with software generated baudrate timings.

It's already working quite well, I can send the reset command, whichbgets confirmed with a status response (seen in the oscilloscope). Sending the get-silicon-signature command is also working (showing an extra response block after the status response). The responses don't occur always though, maybe my software timings are a bit too inaccurate... if neccessary I could retry in raw dos instead of windows, or port the code to 8bit and then run it on an old homecomputer with more stable timings.

Sending erase/write commands for repairing the broken timestamp did have partial success... it's now unable to even blink the power led. That's good because it does confirm that erase/write does actually work as described in the datasheet. A negative side effect is that the long 1.8V supply pin is no longer powered, I guess that supply got switched on by the (now erased) mcu reset handler. So I'll now need to search a more permanently powered supply pin for dragging the flash mode pin high... I hope the pin right of the long pin will work for that purpose (it does have 1.8V, but I don't know yet if it has enough amperes).

The current plan is to unbrick the MCU, and then finally scrap the console and desolder all components and to trace the mainboard wiring... at least if I can scratch together money for buying a second hand console as replacement. My finances are more fragile than ever, I have a bed and a small table with internet at my parents, and (fortunately) about 150 euro from patreon and other sources, and between 80 and 300 euro government support, that's quite a bit below the german poverty limit of 1000 eur/month, but it isn't that bad... except that I have now learned that homelessness envolves a bunch unexpected extra expenses... I am getting familar with having saved up a few hundred euros, only to see somebody popping up and claiming that I still have to pay hundreds of euros (plus fees) for estimated taxes or predicted television usage or things related to my old flat.

Pokun
Posts: 1324
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: 3DS reverse engineering

Post by Pokun » Mon Feb 10, 2020 3:28 am

nocash wrote:
Fri Feb 07, 2020 3:14 pm
Sorry. I should have said language barrier in general. I somewhat got the console donated as "the gui supports japanese only but you can take apart the mainboard for hacking if you want to have it". The region lock is also part of the reason why I've never had any gaming experience on that console, but I am mainly interested in rev-engineering anyways... though I am a bit curious how it would feel like to play a stereoscopic game... I guess the effect could look quite spectacular at first glance... but might wear off quickly?
I'm just grateful that reverse-engineering is partly done on a Japanese system so that any hardware differences between regions are figured out early.

If you get a working 3DS and better financial situation again, maybe picking up some cheap second-hand games to get a feel for the system would be a good thing. Most games requires literacy in the language it's for, but there are games like Super Mario 3D-Land that hardly doesn't (just a few simple menus and the letter from the princess that you get once in a while). Also all 3DS systems comes with a good number of built-in apps. That's one thing I like about the 3DS, and was a bit disappointed when the Switch didn't. I got my LL before the games arrived, so all I had was the built-in AR Games and stuff for some time. It also had a 3D movie with paper planes installed. It was one of the movies in that discontinued 3D movie app, but it was installed in the menu and it still works. I would like to figure out how to extract it some time.

I thought the 3D would be tiring at first, but it doesn't really. I play with it on all the time. But you do get used to it after a while and then you don't really think about it. The 3D limits the distance and angle you can play the game from a bit. I guess this is improved with the head-tracking cameras in the New 3DS.
Super Mario 3D-Land actually has a practical use for the 3D (in an optical illusion that doesn't work when the 3D is off), it's the only game that I've seen does. I think it enables the 3D-indicator LED when this optical illusion happens? I don't know, because the 3D-LED is only present on the original 3DS I think, and I only have the LL. Maybe people thought it was annoying so they removed it on all subsequent models.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Mon Feb 10, 2020 9:39 am

Got it unbricked. The transfer timing got 100% stable after using a "cli" opcode to disable interrupts. For the erase/write commands, the parameters can be used to specify any length, but they seem to be working for max 1000h bytes only (don't know why, it's an odd limit because that would be four 1K blocks). And it seems to be required to issue a reset command after each 1000h byte write (otherwise the chip throws response packets in the middle of incoming data packets).

Compared with eMMC hardmod, the MCU hardmod is much easier, it requires only super-minimalistic hardware and software resources, and the solder pads are easily accessible without needing to remove the mainboard (so no risk to damage any of the crappy ribbon cable connectors). I could only recommend MCU reflashing : )

The pinouts for New3DS-XL are:

Code: Select all

                           _   _
   _    _    _       TOOLx(_) (_)FLMD0
  (_)  (_)  (_)            _ x _
     ____    _    _  TOOLx(_) (_)/RESET
    (____|  (_)  (_)
    VDD18 PVDD18 GND
I haven't yet tested which pin is TOOL0 and which is TOOL1, so I have just wired the data line to both pins (with TOOL1 serving as an extra pull-up). The pins are near headphone socket, the four pins on the right covered under the green solder stop layer.

And for Old3DS:

Code: Select all

           FLMD0
     TP79  TP75  TP74
      _ |   _     _
     (_)'  (_)-  (_)-
      _     _     _
    -(_)   (_)-  (_)-
     TP78  TP76  TP77
     GND   TOOL1 TOOL0
That, going by mainboard photos and by signal names from the 3dbrew Pinouts page (which isn't too accurate; it claims TP78 to be a I/O signal instead of GND). The other missing pins might be TP79=PVDD18? and TP74=/RESET?. The pins are near headphone socket, too, and all six pins covered under the green solder stop layer.

The actual wiring is as simple as this:

Code: Select all

               Schottky diodes
                   BAT85
  PC.Data0 ---------|<|------------- TOOL0 (or both TOOL0 and TOOL1)
  PC.Data1 ---------|<|------------- /RESET
                         PVDD18----- FLMD0
  PC.Ground ------------------------ GND
The datasheet says something about 9600 baud 8N2. But, the chip seems to be actually sending only 1 stop bit (not 2 stop bits). In the other direction, it may be best to send only 1 stop bit at the end of the bytes (but just in case: one could send a 2nd "stop bit" or similar delay before sending the next byte). The 9600 baud might apply for the first "low pulse" (from chip), but thereafter the baudrate seems to be auto-detected (after sending anything to the chip, the chip seems to respond with the same baudrate, too).

coto
Posts: 20
Joined: Wed Mar 06, 2019 6:00 pm

Re: 3DS reverse engineering

Post by coto » Mon Feb 10, 2020 11:07 am

nocash wrote:
Thu Feb 06, 2020 3:48 pm

(Lots of neat 3DS info...)

Or if it goes wrong... having more bricked consoles could be pretty valuable for drawing schematics. Especially the Old3DS mainboards with text layer would be pretty nice to have for that purpose. Just don't brick New3DS-XL's, because I have already done that myself ; )
Ouch. I remember reading back then people bricking 3DSes by playing around the MCU, but a New3DS-XL... RIP.
nocash wrote:
Mon Feb 10, 2020 9:39 am
Got it unbricked. The transfer timing got 100% stable after using a "cli" opcode to disable interrupts. For the erase/write commands, the parameters can be used to specify any length, but they seem to be working for max 1000h bytes only (don't know why, it's an odd limit because that would be four 1K blocks). And it seems to be required to issue a reset command after each 1000h byte write (otherwise the chip throws response packets in the middle of incoming data packets).

Compared with eMMC hardmod, the MCU hardmod is much easier, it requires only super-minimalistic hardware and software resources, and the solder pads are easily accessible without needing to remove the mainboard (so no risk to damage any of the crappy ribbon cable connectors). I could only recommend MCU reflashing : )

The pinouts for New3DS-XL are:

Code: Select all

                           _   _
   _    _    _       TOOLx(_) (_)FLMD0
  (_)  (_)  (_)            _ x _
     ____    _    _  TOOLx(_) (_)/RESET
    (____|  (_)  (_)
    VDD18 PVDD18 GND
I haven't yet tested which pin is TOOL0 and which is TOOL1, so I have just wired the data line to both pins (with TOOL1 serving as an extra pull-up). The pins are near headphone socket, the four pins on the right covered under the green solder stop layer.

And for Old3DS:

Code: Select all

           FLMD0
     TP79  TP75  TP74
      _ |   _     _
     (_)'  (_)-  (_)-
      _     _     _
    -(_)   (_)-  (_)-
     TP78  TP76  TP77
     GND   TOOL1 TOOL0
That, going by mainboard photos and by signal names from the 3dbrew Pinouts page (which isn't too accurate; it claims TP78 to be a I/O signal instead of GND). The other missing pins might be TP79=PVDD18? and TP74=/RESET?. The pins are near headphone socket, too, and all six pins covered under the green solder stop layer.

The actual wiring is as simple as this:

Code: Select all

               Schottky diodes
                   BAT85
  PC.Data0 ---------|<|------------- TOOL0 (or both TOOL0 and TOOL1)
  PC.Data1 ---------|<|------------- /RESET
                         PVDD18----- FLMD0
  PC.Ground ------------------------ GND
The datasheet says something about 9600 baud 8N2. But, the chip seems to be actually sending only 1 stop bit (not 2 stop bits). In the other direction, it may be best to send only 1 stop bit at the end of the bytes (but just in case: one could send a 2nd "stop bit" or similar delay before sending the next byte). The 9600 baud might apply for the first "low pulse" (from chip), but thereafter the baudrate seems to be auto-detected (after sending anything to the chip, the chip seems to respond with the same baudrate, too).
Should have read a bit further.. anyway, good job.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Tue Feb 11, 2020 9:56 pm

I've meanwhile tested reflashing via normal I2C commands. Patching the hardcoded delay settings worked without problems. Adding the hook function for switching power-led to purple upon holding the button did also work without problems. And the hook for executing custom code in ram... that was a bit more troublesome and required to reflash via cable several times.

The first problem was that MOVW AX,[nnnn] doesn't work with odd addresses. That was half expected because the datasheet mentioned MOVW to work only with even addresses when using 8bit wide addresss (SFRs and short-addresses), it didn't mention 16bit wide addresses, but they are now confirmed to work only with even addresses, too (MOVW to-or-from [nnnn] does forcefully access [nnnn AND FFFEh]).

The other problem was very hard to figure out... and turned out to be a bug in my ARM assembler (some corner case related to abbreviated MOV+LSR opcodes working differently than abbreviated ALU+LSR opcodes)... so that problem was completly unrelated to the RL78 stuff... but yet harder to track down ; )

With code execution it's now possible to dump MCU memory. There are 32Kbytes FFh-filled at 08000h-0FFFFh (but that doesn't seem to be writeable flash, I've tried writing there via uart cable, and that didn't work). Then there is a lot zerofilled space at 10000h..ED7FFh. And a repeating 4-byte pattern at ED800h..EFFFFh, two bytes in that area are used as I/O ports, and EFFF8h is used as code address, but there's no visible code there, maybe it needs to be unlocked, or works only on opcode fetches, not on data reads? There should be also some ROM code for the TOOL0 pin handling, but that code isn't visible anywhere either. And finally, the whole data area at F1000h..F7FFFh contains mirrors of code area 01000h..07FFFh (then followed by at least 7000h FFh's, which may be also mirrors from the FFh-filled code area). RAM seems to start at FF900h (unless the preceeding FFh's are also RAM). And, not yet tested if RAM does continously exist from FFF900h up to including short address area (the firmware leaves 20h bytes at FFE00h unused, but that 20h bytes return random values when reading, so I guess that's also working, but uninitialized RAM).

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Sun Feb 16, 2020 6:46 pm

I've found the MCU ROM, and dumped it today. It's enabled via the writes to FLPMC (those with value 1Dh do enable it, and those with 0Ch do hide it again). There is 10Kbyte of ROM at ED800h..EFFFFh, and another 1.5Kbyte of ROM at F0800h..F0DFFh (plus a weird 0.5Kbyte RAM mirror at F0E00h..F0FFFh that gets enabled alongsides with enabling the ROM).

EDIT: That 1.5Kbyte seem to be RAM, not ROM. It's containing code relocated from ROM (and for some reason, that relocated code is still in there when running the normal 3DS MCU firmware... a bit wasteful to have that much reserved hidden RAM, without allowing the firmware to use that memory, too).

The entrypoint seems to be at EFFFCh, there seem to be no exception vectors (unless there's another yet undumped ROM snippet). At first glance, the ROM seems to be complete, the EFFF8h vector for 3DS-updating is there, and the UART packet handling is there, too (spotted the packet-checksumming, error codes, and the command list... including two undocumented commands).

As by now, I have no idea why the ROM is so huge, it's 10Kbytes (only 9.51Kbytes used though), which seems a bit too much for a handful of flash write/erase functions.

For the MCU Patcher, I still need to add some "boring" functions for loading/decrypting the original image from eMMC, and probably some options for whether or not to change the power-button timings. The inner workings of the patcher are already working quite well, the current features are:

Code: Select all

Code Execution in Battery RAM:
  MCU[05h-07h] = "exc"  --> Battery RAM code gets executed immediately
  MCU[05h-07h] = "exq"  --> Battery RAM code gets enqueued as callback
  Before execution, use MCU[61h] to upload code to Battery RAM, the RAM
  can be also used to store parameters and return values, you may want to
  restore the original RAM content after execution for not confusing the OS.
  The ROM/RAM memory map varies for different MCU firmware versions, however,
  the patched firmware provides useful ROM/RAM addresses in below tables,
  code should either use relative jumps, or addresses from those tables.
Call Table Vectors for ROM functions:
  00080h  Process Standard Callbacks    ;\
  00082h  Add Callback AX               ; Nintendo's own stuff (not useful)
  00084h  Process Enqueued Callbacks    ;/
  000B4h  I2C_Receive_Block             ;\Slave I2C recv/send (can be used
  000B6h  I2C_Send_Block                ;/from within callbacks only)
  000B8h  FLASH Init and kill IRQs      ;\
  000BAh  FLASH Erase 400h bytes        ; FLASH init/erase/write/finish
  000BCh  FLASH Write max 100h bytes    ; (eg. for custom code in backup area)
  000BEh  FLASH Finish 400h bytes       ;/
Pointers to RAM arrays:
  F4FE8h  MCU[00h..5Ah] Registers  (5Bh bytes)  ;\
  F4FEAh  MCU[61h] Battery RAM     (C8h bytes)  ; Pointers to RAM arrays
  F4FECh  MCU[2Dh] Notify LED RAM  (64h bytes)  ;
  F4FEEh  MCU[4Fh] Pedometer_array (150h bytes) ;/
Other General Patches:
  Faster power button tap duration (0s instead laggy delay)
  Faster power button hold duration (1s instead 3s)
  Changed Power LED color upon holding power button (purple)
  Faster shutdown after holding power button (can be 0s instead 7s)
  Faster shutdown after normal power down (omitting LED fade-out delay)
Apart from just searching code that needs to be patched, the patching tool does also search the entrypoints for nintendo's I2C and FLASH functions, and the location of the RAM arrays, and stores that addresses in the call table at 000Bxh, and in the data table at F4FE8h. So the uploaded code can use that tables as some kind of mini-OS.
It's quite comfortable to run small code snippets in RAM, and if the RAM is too small, one could easily use the FLASH function vectors to overwrite the flash backup, and replace it by 16Kbytes of custom code.

For curiosity, I have also dumped the registers of the MCU's I2C slave devices. They are all a bit different to access: The power managment chip returns only 1 byte at once (followed by FFh's when trying to read more data). The fuel gauge works only when reading 2 bytes from even addresses (reading 1 byte from odd addresses mirrors to even address, and reading more than 2 bytes weirdly repeats each 2-byte-pair twice). The touchscreen/sound controller just allows to read 1 or more bytes. Ah, and the pedometer, I haven't tried that because it can be already read via official MCU functions.

nocash
Posts: 1137
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash » Tue Feb 25, 2020 7:06 pm

I have finally brewed up some code for loading/decrypting/decompressing .code files from eMMC, the current purpose would be loading the original MCU firmware before patching. It's working okay, but I could imagine a few possible problems:

1) I am ignoring the .tmd/.cmd files, and just load "ncsd:\title\00040130\?0001f02\content\000000??.app" (the first "?" wildcard for Old3DS-vs-New3DS, and the other two "??" for the version number). I guess that should be safe, assuming that the console won't ever have more than one MCU version installed?

2) The MCU file is loaded from eMMC, whilst hacked consoles might actually load it from SD card, so there might be a version mismatch. I can compare the version numbers from registers MCU[00h..01h], and check if they are same as in the MCU file. If they don't match, then I could retry loading the file from SD card, and check if that does contain a matching version...
The thing that could crash the MCU would be a false-match between Old3DS and New3DS files with same MCU version number. I don't know if Old3DS+New3DS MCU's do ever share the same MCU version numbers (and if yes, if there's a way to distinguish them)?

3) The NCCH/.code files are originally encrypted via AES key 2Ch. But firmware 7.0.0 and up are said to additionaly use AES key 25h/18h/1Bh, I don't have those newer keys implemented... and I got told that my console has firmware 9.1.0... nethertheless, the decryption does mysteriously work okay with key 2Ch.
My current theory is that key 25h/18h/1Bh are maybe used only for shop-titles, but never for pre-installed system files. Could that be right?

Post Reply