3DS reverse engineering

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
3DS reverse engineering
by on (#234407)
I've started adding ARM11 support to my disassembler some days ago, and I am now examining 3DS bootroms, and try to learn about the 3DS in general. I have a New3DS console laying around for some years, but I could never make any sense of it (and don't really know how to start a game, and least how to program homebrew code for it). But I've managed to view two game trailers - and the stereoscopic 3D does actually look neat! I might like that hardware - if I could ever figure out how to use it.

For understanding the 3DS hardware I/O registers, my starting point is here: https://www.3dbrew.org/wiki/IO_Registers
At first glance, that refers to things like "ABC Registers for ABC Services used Process ABC for ABC module" - without giving much of a hint what "ABC" stands for.
At second glance, it looks as names like "ABC" are just newly invented homebrew aliases for well-known NDS/DSi registers. Plus some new 3DS registers. At the moment I couldn't say if there are many new registers, or if it the 3DS is just a DSi with some extra gimmicks.

Some general specs are here: https://www.3dbrew.org/wiki/Hardware the two main differences seem to be new GPU for stereoscopic 3D and the newer ARM11 CPU.

The GPU seems to be some standard off-the-shelf hardware (DMP PICA), so I hope that specs are openly available. It might be difficult to emulate that thing though, and possibly slow when using raw software emulation (without trying to parse the stuff to opengl or direct3d). The bootrom seems to be capable of displaying an error message? Though I can't see any font data in the bootrom, or is there a built-in font in the GPU itself?

The ARM11 seems to be DualCore? Or even QuadCore for New3DS? I had believed the 3DS would just have ARM9+ARM11. But now it looks as if it's actually ARM9+ARM11+ARM11 (+ARM11+ARM11 for New3DS. That - and the speed of 268MHz (or even 804MHz) per ARM11 core - that would be also difficult (and very slow) to emulate. Not to mention the Virtual Memory on ARM11 side, which might also slowdown emulation.

Many I/O registers are said to be accessible by ARM9 and ARM11. I wonder what that means in practice, especially if there are two or more ARM11 cores. It isn't too clear if there are separate sets of I/O ports for each core, or if all cores access the same registers (with only one of them being supposed to do so at once).

I have no idea where the homebrew register names came from. As far as I remember somebody mentioned that the official 3DS SDK is using names like SCFG_xxx (same/similar as on DSi) (EDIT: Or was it something different, like REG_OS_PAUSE_JTAG or HWi_WSYS09_JTAG on 3DS, instead of the DSi's SCFG_JTAG?). So the homebrew names might be just there for lack of official names. Though in case of "MP" it looks as if the homebrewers didn't even realize why they had used that name for it (I guess it stands for local MultiPlayer wifi, going by their description). Btw. are there any documents with official register names? Or official specs for the hardware? Or more homebrew specs other than 3dbrew wiki?

Would be cool if somebody could answer such newbie questions!
Re: 3DS reverse engineering
by on (#234411)
Although I haven't tried it myself, I noticed that Nintendo has relaxed developer registration for individuals so it's easier than ever to legally get development tools and documents for Nintendo's systems. But now I also read that by registering you are swearing that you don't leak it or use it for homebrew or emulator development, and breaching the contract may jeopardize your emulator or the homebrew wiki you contribute to.
Re: 3DS reverse engineering
by on (#234924)
I've plundered the 3dbrew hardware register pages, and collected and reformatted the info for viewing as 80 column text. The result is now included in a new "3DS Reference" section in gbatek: http://problemkaputt.de/gbatek.htm#3dsreference
At the moment, it is just containing shamelessly copied info from of 3dbrew pages, I didn't write any of the descriptions myself (and, in most cases, I didn't even read them yet). Plans for future would be to read & verify & rewrite & extend the text step by step, until, hopefully, I could honestly say that I've written & contributed a good bit of information on my own someday.

Anyways, for now, the text is just reflecting what I know about the console - if it's missing important parts that are already known and documented elsewhere - please let me know! There's also a todo-list at the end of the 3DS section with some specific issues & questions (and plenty of "unknown" bits in the register descriptions).

Pokun wrote:
Although I haven't tried it myself, I noticed that Nintendo has relaxed developer registration for individuals so it's easier than ever to legally get development tools and documents for Nintendo's systems. But now I also read that by registering you are swearing that you don't leak it or use it for homebrew or emulator development...
Yeah, looks as if they are announcing something like that here: https://developer.nintendo.com/ it does almost sound to good to be true - free devkits for everyone without any programming experience whatsoever? I guess it may turn out that the free devkit might require expensive devhardware, and programming manuals for 3D consoles are traditionally only covering OS functions and libraries instead of hardware specs. Either way, I am not so motivated to swear & register for obtaining documentation.

The code in the 3DS bootrooms is surprisingly easy to read. I was almost thinking that it were written in ASM, or that their compiler evolved to produce more meaningful code. On the other hand, wide parts of the bootrom consists of mini-functions that do things like "[register]=value" (which is inefficient by itself, but a compiler can't screw up too much on such basic commands). The part that isn't easy to read is the boot error text output - I think pixel drawing is yet a bit too complex for compiler code.
Alongsides, I have also found the font for the error message - the size and encoding are rather unexpected:
Code:
;------------------
font_3x5_pix:      SPC  !   "   #   $   %   &   '   (   )
 dd 02B5D48Ch  ;00 000 010 101 101 011 101 010 010 001 100
 dd 02BF1B12h  ;00 000 010 101 111 110 001 101 100 010 010
 dd 02152412h  ;00 000 010 000 101 010 010 010 000 010 010
 dd 001DCA12h  ;00 000 000 000 111 011 100 101 000 010 010
 dd 0217560Ch  ;00 000 010 000 101 110 101 011 000 001 100
;---                *   +   ,   -   .   /   0   1   2   3
 dd 00001FBFh  ;00 000 000 000 000 000 001 111 110 111 111
 dd 2A001A89h  ;00 101 010 000 000 000 001 101 010 001 001
 dd 171C2ABFh  ;00 010 111 000 111 000 010 101 010 111 111
 dd 2A404AA1h  ;00 101 010 010 000 000 100 101 010 100 001
 dd 00824FFFh  ;00 000 000 100 000 100 100 111 111 111 111
;---                4   5   6   7   8   9   :   ;   <   =
 dd 2FFFF008h  ;00 101 111 111 111 111 111 000 000 001 000
 dd 2C96D497h  ;00 101 100 100 101 101 101 010 010 010 111
 dd 3FE7F020h  ;00 111 111 111 001 111 111 000 000 100 000
 dd 09A69497h  ;00 001 001 101 001 101 001 010 010 010 111
 dd 0FE7F108h  ;00 001 111 111 001 111 111 000 100 001 000
;---                >   ?   @   A   B   C   D   E   F   G
 dd 264B2DFEh  ;00 100 110 010 010 110 010 110 111 111 110
 dd 11B6DB24h  ;00 010 001 101 101 101 101 101 100 100 100
 dd 0AF74BFFh  ;00 001 010 111 101 110 100 101 111 111 111
 dd 10BEDB25h  ;00 010 000 101 111 101 101 101 100 100 101
 dd 22772DE7h  ;00 100 010 011 101 110 010 110 111 100 111
;---                H   I   J   K   L   M   N   O   P   Q
 dd 2A365AB2h  ;00 101 010 001 101 100 101 101 010 110 010
 dd 2A367B6Dh  ;00 101 010 001 101 100 111 101 101 101 101
 dd 3A3A5F75h  ;00 111 010 001 110 100 101 111 101 110 101
 dd 2AB65B62h  ;00 101 010 101 101 100 101 101 101 100 010
 dd 2A57DAA3h  ;00 101 010 010 101 111 101 101 010 100 011
;---                R   S   T   U   V   W   X   Y   Z   [
 dd 33F6DB7Bh  ;00 110 011 111 101 101 101 101 101 111 011
 dd 2C56DB4Ah  ;00 101 100 010 101 101 101 101 101 001 010
 dd 3256D492h  ;00 110 010 010 101 101 101 010 010 010 010
 dd 2956FAA2h  ;00 101 001 010 101 101 111 101 010 100 010
 dd 2E5D5ABBh  ;00 101 110 010 111 010 101 101 010 111 011
;---
;well, that is a bit crazy, saving memory for the sake of
;keeping more unused ROM zerofilled.
;or perhaps it's done for not overloading the HLL-coded wrchr
;function with much too many amounts of data : /

Oh, and no$gba was also updated together with gbatek - http://problemkaputt.de/gba.htm - with some basic groundwork for possible future 3DS support - and a rather bewildering bugfix for a problem that I wasn't aware off at all (it seems that all builds in the past some years did have the profiler feature enabled by default - making no$gba debug version to run slow as glaciers).
Code:
23 Feb 2019 - no$gba version 2.9d
- debug/setup: disabled profiler by default (for fast emulation) (thanks Dwedit)
- debug/disass: disassembler support for UAL syntax (optional) and ARM11 opcodes
- dsi/help: added SD_EXT_IRQ_STAT/MASK (insert/eject state and irq for emmc)
- 3ds/help: added 3DS register specs (thanks 3dbrew.org/wiki/IO_Registers)
Re: 3DS reverse engineering
by on (#234951)
Have you ever heard of the Citra Emulator, nocash? https://github.com/citra-emu/citra
Re: 3DS reverse engineering
by on (#234952)
Heard of it, yes. But I may be wrong about what it is doing... as far as I know it's emulating the ARM11 cpu, and the 3DS OS, without trying to emulate the 3DS hardware. I have had a brief look at the citra homepage and github page yesterday, and I didn't find source code files for hardware emulation (except perhaps for the yuv-to-rgb Y2R part), and for console specs they do only have a link to an ARM11 pdf, and to the 3dbrew wiki. I may have missed some important stuff though, maybe there's much more low level HW emulation in there...?

What I know of: For citra related 3DS sound, there is a separate github page from wwylele with Teak DSP emulation, and with readme pages describing the Teak MMIO registers. That is looking like pretty cool low level stuff : )
Re: 3DS reverse engineering
by on (#234958)
nocash wrote:
Yeah, looks as if they are announcing something like that here: https://developer.nintendo.com/ it does almost sound to good to be true - free devkits for everyone without any programming experience whatsoever? I guess it may turn out that the free devkit might require expensive devhardware, and programming manuals for 3D consoles are traditionally only covering OS functions and libraries instead of hardware specs. Either way, I am not so motivated to swear & register for obtaining documentation.


Exactly, everything in this website is pretty much useless without 3000 USD of development hardware. The information too, it's just API reference, programming "best practices", dozens of manuals for every single software included and so on. The most useful and uncommon info would be the shader coding manual, but I think this info is somehow around the internet already.


~
People need to stop this wrong mindset of "if someone already done something similar, I won't even touch the subject", knowledge is built upon multiple people taking different approaches researching something, be sure that, when humanity forget this completely, it'll be the END.
Re: 3DS reverse engineering
by on (#234975)
Oh, yeah, I hope it won't be the end of the world, but the next gen handheld scene community can be sometimes as helpful as saying "Don't worry about that, I think that we already know how to do it!" ; )

3dbrew has this about shaders https://www.3dbrew.org/wiki/GPU/Shader_Instruction_Set the opcode table is a bit hard to read, but I hope that it will make some more sense when analyzing it step by step. The page says that it was rev-engineered, I don't know if nintendo has better specs for it. Why are that shader instructions so special at all, I thought that the PICA200 gpu would be standard hardware? I haven't checked if there are official specs for it yet though.

This page https://www.3dbrew.org/wiki/GPU/Internal_Registers seems to cover the main part of the gpu. The page formatting appears to be a little bit very insane - but the actual info isn't so bad - the trick is to split the 9 sections to 9 separate pages/files/chapters, that's making it much easier to read.

The one big thing that seems to be missing is information about matrices. Searching the 3dbrew wiki gives only three hits for matrix (mostly for pages that describe fileformats), but there isn't anything mentioning that the GPU could do matrix maths - is that still missing/undocumeted?
Or is it really unsupported by the GPU?
The ARM11 seems to have some SIMD extension, maybe that allows to do matrix maths on ARM11 side?
Re: 3DS reverse engineering
by on (#235057)
nocash wrote:
3dbrew has this about shaders https://www.3dbrew.org/wiki/GPU/Shader_Instruction_Set the opcode table is a bit hard to read, but I hope that it will make some more sense when analyzing it step by step. The page says that it was rev-engineered, I don't know if nintendo has better specs for it. Why are that shader instructions so special at all, I thought that the PICA200 gpu would be standard hardware? I haven't checked if there are official specs for it yet though.


GPUs this day change architecture and internal assembly language all the time, so they don't even bother to release to public, it's closed to engineers or to console developers that don't rely on High Level APIs. Isn't that the hardware is special, is just unknown (and most people don't care about knowing it, even people which should), and being from DMP is even more unknown and strange. Exactly this, they aren't special, just strange!

nocash wrote:
The one big thing that seems to be missing is information about matrices. Searching the 3dbrew wiki gives only three hits for matrix (mostly for pages that describe fileformats), but there isn't anything mentioning that the GPU could do matrix maths - is that still missing/undocumeted?
Or is it really unsupported by the GPU?
The ARM11 seems to have some SIMD extension, maybe that allows to do matrix maths on ARM11 side?


The OpenGL "modern" standard is do heavy matrix calculations on CPU side and just upload them as uniforms to the shader side, and do final multiplications there, so your guess about the SIMD is pretty accurate. But as you can see here:

Code:
; Really simple & stupid PICA200 shader
; Also serves as an example of picasso syntax

; Uniforms
.fvec projMtx[4], mdlvMtx[4]

; Constants
.constf myconst(0.0, 1.0, -1.0, 0.0)
.alias zeros myconst.xxxx
.alias ones myconst.yyyy
.alias negones myconst.zzzz
.alias dummytcoord myconst.xxxy ; (0,0,0,1)

; Outputs
.out outpos position
.out outtc0 texcoord0
.out outtc1 texcoord1
.out outtc2 texcoord2
.out outclr color

; Inputs
.alias inpos v0
.alias intex v1
.alias inarg v2

.proc main
   ; r0 = (inpos.x, inpos.y, inpos.z, 1.0)
   mov r0.xyz, inpos
   mov r0.w, ones
   
   ; r1 = mdlvMtx * r0
   dp4 r1.x, mdlvMtx[0], r0
   dp4 r1.y, mdlvMtx[1], r0
   dp4 r1.z, mdlvMtx[2], r0
   dp4 r1.w, mdlvMtx[3], r0
   
   ; outpos = projMtx * r1
   dp4 outpos.x, projMtx[0], r1
   dp4 outpos.y, projMtx[1], r1
   dp4 outpos.z, projMtx[2], r1
   dp4 outpos.w, projMtx[3], r1
   
   ; Set texcoords
   mov outtc0, intex
   mov outtc1, dummytcoord
   mov outtc2, dummytcoord
   
   ; Set vertex color
   mov outclr.xyz, inarg
   mov outclr.w, ones
   
   end
.end


This is the example one common assembler to the 3DS GPU provides, as you can see there's some matrix*vector multiplications using DP4. But maybe there's some quick way to multiply matrix*matrix.
Re: 3DS reverse engineering
by on (#235127)
Thanks for the shader example. Okay, if they are doing it like that then there seems to be really no matrix hardware.
I guess one could also use the shader for matrix by matrix multiplication, best with pre-swapped rows/columns in one matrix, or otherwise use the ARM11 for that multiplication.

If there's no matrix hardware, that does also solve another question that I had in mind: I was wondering if the GPU were automatically producing stereoscopic output (by setting Left and Right projection matrices before rendering the scene). But now it's looking as if one must render Left and Right scenes separately.

Some 3D related terms are a bit confusing to me. I can't grasp what is meant by "Uniform", or, I get some idea what it is, but not why it's called like that. Looking at https://en.wikipedia.org/wiki/Uniform_(disambiguation) doesn't help either (I couldn't say if or which of that meanings does apply in this case). For now, I am just treating it as slang for saying "constant", or "immediate", or "general purpose".

---

For booting code, I think I have now figured out how to do that... The bootrom does first load a "NCSD" sector (from first eMMC sector), which points to a "FIRM" sector, which contains entrypoints & load addresses for bootcode. And storing the "sighax" values in the FIRM's RSA signature field should most probably allow to freely modify the entrypoints & bootcode.

So far, that sounds relative simple and comfortable. I'll only need to figure out which encryption keys are needed for modification (and if they are console-unique). But for now, I can just wire the console to a SD/MMC card reader - and then see where I can get from there (and with the wires attached I could also easily unbrick the console if something goes wrong).

---

Also good to know that there's no official documentation for the GPU, then I won't have to waste time on searching for it!
Re: 3DS reverse engineering
by on (#235176)
About the stereoscopic output, yes! To my knowledge devs must read an float value from 1FF81080h (3D Slider), if its greater than 0.0 the 3D is active and the value also indicates the 3D level so you need to base your dual rendering in it, and keep on drawing left,right,left,right[...]. I don't know the maximum value although.

I'm sorry! It's one of the cases you use a name for years a never argue about it's meaning wwww. Uniform is an read-only value you send from CPU to GPU. It can be vertex, texture coordinates, parameters. I think they didn't call it a const cause there's already a const to values hardcoded inside the shader itself, but the motive behind the use of "Uniform" is unknown to me too.
Re: 3DS reverse engineering
by on (#235200)
3dlabs' logic was something like "it is uniform to all executions of this shader in this drawcall", vs varying "it varies between different executions". Varying being a variable passed between shader stages. In the above asm, varyings are called either inputs or outputs.
Re: 3DS reverse engineering
by on (#235201)
Thanks! I was wondering if one needed to study uniform maths for fully understanding this console.
Re: 3DS reverse engineering
by on (#235607)
Hmmmm, the 3DS project seems to have died before I got started with it : /

After disassemblid the New 3DS XL a bunch of times, one of the pins in one of the three top-screen-unit connectors got bent inside of the connector, making it impossible to fully insert the FFC cable. The connector has 31 pins, the total width of the socket is about 9.4mm. I think that it is this specific part: https://www.molex.com/molex/products/da ... ECTORS.xml that is, the black socket with white lid, on the far left edge of this photo: https://d3nevzfk7ii3be.cloudfront.net/i ... A2dBL.full

Does anybody know how to get a replacement part for that?

Currently, the console switches off a few seconds after power up, with the bottom screen backlight flashing for a short moment. I assume the broken connector goes to top screen backlight (and probably speakers/sliders). It might be possible to bridge the backlight pins with a resistor (if I knew where those pins are on mainboard), maybe the console would boot up with that, so I could at least continue rev-engineering the console (just without top screen).

---

What I was doing was hooking the 3DS mainboard's eMMC chip to an SD/MMC card reader, which didn't work with neither of my card readers. I had no problems doing the same thing with the DSi. I think the difference is that DSi has resistors in the CLK and CMD lines (those should help in cases where the console pulls CLK low, while the card reader wants to pull it high). The 3DS board does have solder pads for that resistors too, but they are just bridged with wires. So I had cut that wires, and attached cables for later attaching resistors on the other PCB side. Well, and with that cables in place, I was optimistic that I won't ever have to remove the mainboard again - and then discovered that the FFC connector had died : /

PS.
molex webpage wrote:
Durability (mating cycles max) 10
I can confirm that 10 cycles appear to be maximum, mine died after plugging/unplugging 5-7 times.
Re: 3DS reverse engineering
by on (#236617)
nocash wrote:
Hmmmm, the 3DS project seems to have died before I got started with it : /

After disassemblid the New 3DS XL a bunch of times, one of the pins in one of the three top-screen-unit connectors got bent inside of the connector, making it impossible to fully insert the FFC cable. The connector has 31 pins, the total width of the socket is about 9.4mm. I think that it is this specific part: https://www.molex.com/molex/products/da ... ECTORS.xml that is, the black socket with white lid, on the far left edge of this photo: https://d3nevzfk7ii3be.cloudfront.net/i ... A2dBL.full

Does anybody know how to get a replacement part for that?

Currently, the console switches off a few seconds after power up, with the bottom screen backlight flashing for a short moment. I assume the broken connector goes to top screen backlight (and probably speakers/sliders). It might be possible to bridge the backlight pins with a resistor (if I knew where those pins are on mainboard), maybe the console would boot up with that, so I could at least continue rev-engineering the console (just without top screen).

---

What I was doing was hooking the 3DS mainboard's eMMC chip to an SD/MMC card reader, which didn't work with neither of my card readers. I had no problems doing the same thing with the DSi. I think the difference is that DSi has resistors in the CLK and CMD lines (those should help in cases where the console pulls CLK low, while the card reader wants to pull it high). The 3DS board does have solder pads for that resistors too, but they are just bridged with wires. So I had cut that wires, and attached cables for later attaching resistors on the other PCB side. Well, and with that cables in place, I was optimistic that I won't ever have to remove the mainboard again - and then discovered that the FFC connector had died : /

PS.
molex webpage wrote:
Durability (mating cycles max) 10
I can confirm that 10 cycles appear to be maximum, mine died after plugging/unplugging 5-7 times.

Any luck getting that part and resuming 3ds R&D?

If you need some assistance in getting the thing fully softmodded, I could help you in PMs with that. It's really easy if you already have a userland entry point.
The online guides tend to be overly wordy because they are mostly dealing with people who aren't technically savvy. I can steer you around most of that.
Re: 3DS reverse engineering
by on (#236810)
Damaged hardware
I didn't got a replacement part. Molex is listing several distributors like mouser, and those distributors seem to be stating that they don't have that connector in stock, and that one could contact them for ordering details. I haven't tried that... the connectors seem to be produced in reels of 3000 pieces, which makes me doubt that they would happily process orders of 1-2 pieces, though maybe they'd say "no problem". Does anybody have experiences ordering such exotic parts?

The other option would be buying a new New3DSXL mainboard for about $40 or so. That would hopefully also get me rid of having a japanese firmware on the console (which is really distracting, I can't even power-off the console without running into a mysterious japanese power-off message; I've been usally holding the power-button pressed for some seconds to make that message disappear).

Anyways, I've got the console resurrected (with lower-screen only) by bridging the upper backlight contacts with a resistor (wired to the two "square" gold contacts on the right board-edge, next to the power-managment chip) (I've tried 180, 1K5, 3K3 and 10K ohm, of which 1K5 worked best; 180 worked, too, but that would produce more heat, and 3K3 and 10K didn't work at all).

Hardmod
I've got the hardmod working so far that I can dump the CID and CSD when connecting the New3DS to the SD/MMC slot of a DSi console, so I do at least know that my wiring is correct (and that it was correct all the time, and that I wouldn't have needed to take apart the console a dozen of times to check the damn wiring). I've meanwhile also found a webpage that says that New3DS works only with some card readers (as opposed to Old3DS), so that might explain why my PC can read DSi eMMC, but not 3DS eMMC. My theory is that JEDEC might have intentionally vandalized the MMC specs to make newer eMMC chips incompatible with standard MMC card readers, which might help to phase-out MMC, and to push ahead their newer UFS standard. Or maybe they have just unintentionally screwed up the MMC standard.

In theory I could use the DSi hardware to install sighax & new firmware on the 3DS. The problem is that I would need a OTP dump for obtaining the firmware encryption key. Or alternately: I would need to know the (de-)crypted content of the firmware sectors, then I could simply install my new code by XORing the decrypted old/new bytes, I guess that's how it's usually done?
The first problem would be: Are there many different firmwares to deal with? Or are the firmwares all same (at least concerning the first some bytes with entrypoint)? If there are different firmwares, how are chances to know which version I have (on japanese console without top screen)?
The second problem would be: If the firmware is already patched, is there some standard for dealing with that situation? Ie. detect if it is patched, and to remove the patch (or keep using the existing patch - if it's containing a standarized stub that loads the actual firmware from some unencrypted region).

Software/specs
Apart from fighting with (defunct) hardware, I've spent the last some weeks on forensic analysis of several 3dbrew pages. I am having quite some problems to understand the language used there. If a sentence begins with something like "As of version 1.2.3-45 there is (in almost all cases, but not always, there are certain exceptions)..." well, then I am so confused that I find it difficult to read the rest of the sentence.
My current strategy is to annotate everything "Uh, what does that mean?", and then, to carefully remove all irrelevant & confusing words in the sentence step by step (which can sometimes end up with figuring out that the whole sentence was completely irrelevant, but it takes time to get there).
Well, and the rest of the time I am trying to re-order the information, like moving the most important tables to the begin of the page/chapter, and merging tables+subtables into a single table... hopefully making it easier to grasp what it is all about.
Re: 3DS reverse engineering
by on (#236814)
nocash wrote:
If there are different firmwares, how are chances to know which version I have (on japanese console without top screen)?


You can check these memory addresses:

Code:
FIRM_VERMAJOR   1FF80063h   1 byte
FIRM_VERMINOR   1FF80062h   1 byte
FIRM_VERREV     1FF80061h   1 byte


I think it's possible to find this information looking at the firm0 partition in the NAND (0B130000h), but I don't know where.
Re: 3DS reverse engineering
by on (#236816)
The firm sectors are encrypted, so there is no way to read version info from there without knowing the decryption keys in first place.

Yeah, reading ram locations would work, but I have no idea how to write homebrew code in which file format for 3ds yet (except firm format, which seems to be pretty simple, apart from getting around the encryption issue).

I have some zelda card exploit, but with the japanese language barrier it's no fun to use: Like randomly clicking some icons until zelda pops up, and then randomly clicking some more symbols until something shows up which might be a homebrew file menu, but then not knowing how to write my own homebrew code (or at least knowing how to power off the console properly). That's not so satisfying. Well, I guess my main problem is that I am unwilling to learn how to use the existing exploits and high level tools, and instead want to jump straight into low level coding.
Re: 3DS reverse engineering
by on (#236839)
If the Japanese is really that much of a problem we are many people on the forum that are professional or amateur translators and can help you if you post photos.
Re: 3DS reverse engineering
by on (#236860)
nocash wrote:
The firm sectors are encrypted, so there is no way to read version info from there without knowing the decryption keys in first place.



See if this helps
https://pirate.s-ul.eu/6AdyvCX2

It's a spreadsheet with the keys, made by Reisyukaku years ago but recently locked down.
(https://docs.google.com/spreadsheets/d/ ... FisP8/edit)
Re: 3DS reverse engineering
by on (#236959)
Not knowing japanese is part of the problem. The other parts are the 3DS boot delays and the whole 3DS GUI in general, I would rather avoid dealing with that, and prefer to patch the console to boot my own code. Hmmmm, translated photos? Knowing how to "click [image] for OK and [image] for Cancel" could be useful, but only when knowing what I am accepting when clicking OK. I guess that would require loads of photos, plus some huge poster-sized neon photos saying "Never click [image] or [image] because that would block all exploits or delete all data". So, no, I don't think that's practicable.

The spreadsheet is nice for verifying that my key generator has put the keys into correct keyslots. Though there seem to be a few bugs in the spreadsheet (I think the normal key in keyslot 38h should be in keyslot 38h only, not also in keyslot 3Ah. And the DSi keyX in keyslot 03h should be console unique). Anyways, the spreadsheet doesn't help on patching eMMC because I don't have OTP dump for generating all the console unique keys.

At the moment, I could see three DIY hacking approaches (or combinations thereof):

Patching firm0 at eMMC offset 0B130000h
For XORing without knowing the AES key: Is there anything known about how many firm0 versions exist? And does somebody know how to get hold of those version(s)?
I think there must be at least two versions (one for Old3DS, one for New3DS). Possibly with about 30 variations for the different firmware updates, and 6 more variants for 6 regions, and possibly 2 more variants for debug/retail? In worst case that would be up to 1440 different versions (2*30*6*2).
I have one decrypted firm0 dump (unfortunately not the one installed on the actual console). That dump contains some zerofilled areas - that would make XORing much easier (if one knows where the zerofilled area is located in each version). But to do that, one would also need to patch the NCSD header with RSA slot 3 sighax signature, and then redirect firm0 it to the zerofilled area.

sighax
The bootrom uses three RSA keys in RSA slot 1,2,3:
- RSA slot 1: For FIRM signature in eMMC
- RSA slot 2: For FIRM signature in WifiFlash/Ntrcard
- RSA slot 3: For NCSD signature in eMMC
So that would require three different sighax signatures (and another three for debug version). Unfortunately, the .bin file download on http://www.sighax.com/ contains only one of those brute-forced signatures (and doesn't even tell which one... probably the retail RSA slot 1 one, as that would be most commonly used).
This tool might be capable of brute-forcing missing signatures: https://github.com/Myriachan/sighax did anybody already do that brute work? I've read that it would take 1 week with a fast GPU (or presumably several months with my own old PC).

Booting from Wifi-Flash (from flash offset 400h)
Wifi-Flash boot uses a fixed AES key. So that would work without needing any OTP-based console unique keys. The main issue would be the missing sighax signature for RSA slot 2. Another issue is that the 3DS Wifi-Flash chip probably doesn't have any write-able memory at offset 400h (but I have a spare bigger chip from a DSi wifi board, so I could use that instead; and rewire the write-protect pin, of course).
Re: 3DS reverse engineering
by on (#236983)
nocash wrote:
The spreadsheet is nice for verifying that my key generator has put the keys into correct keyslots. Though there seem to be a few bugs in the spreadsheet (I think the normal key in keyslot 38h should be in keyslot 38h only, not also in keyslot 3Ah. And the DSi keyX in keyslot 03h should be console unique). Anyways, the spreadsheet doesn't help on patching eMMC because I don't have OTP dump for generating all the console unique keys.

Here are the correct non console unique keys:
https://pastebin.com/7TYfQzSv
This list is generated from:
https://github.com/yellows8/boot9_tools/ (this yellows8 guy's stuff can be trusted without question)

A script for generating the console unique keys from otp is also there. (when you get around to softmodding your 3ds and you are able to dump otp).
nocash wrote:
At the moment, I could see three DIY hacking approaches (or combinations thereof):

Patching firm0 at eMMC offset 0B130000h
For XORing without knowing the AES key: Is there anything known about how many firm0 versions exist? And does somebody know how to get hold of those version(s)?
I think there must be at least two versions (one for Old3DS, one for New3DS). Possibly with about 30 variations for the different firmware updates, and 6 more variants for 6 regions, and possibly 2 more variants for debug/retail? In worst case that would be up to 1440 different versions (2*30*6*2).
I have one decrypted firm0 dump (unfortunately not the one installed on the actual console). That dump contains some zerofilled areas - that would make XORing much easier (if one knows where the zerofilled area is located in each version). But to do that, one would also need to patch the NCSD header with RSA slot 3 sighax signature, and then redirect firm0 it to the zerofilled area.

Using a known-plaintext attack on firm0 would probably be the way to go here. Fortunately for new 3ds, there are only 14 different native firms for overall firmware versions 8.1 to 11.9.
nocash wrote:
sighax
The bootrom uses three RSA keys in RSA slot 1,2,3:
- RSA slot 1: For FIRM signature in eMMC
- RSA slot 2: For FIRM signature in WifiFlash/Ntrcard
- RSA slot 3: For NCSD signature in eMMC
So that would require three different sighax signatures (and another three for debug version). Unfortunately, the .bin file download on http://www.sighax.com/ contains only one of those brute-forced signatures (and doesn't even tell which one... probably the retail RSA slot 1 one, as that would be most commonly used).
This tool might be capable of brute-forcing missing signatures: https://github.com/Myriachan/sighax did anybody already do that brute work? I've read that it would take 1 week with a fast GPU (or presumably several months with my own old PC).

Yeah, the brute force work has been done. The results are posted here:
https://gist.github.com/SciresM/cdd2266 ... e86f9d8c52
Re: 3DS reverse engineering
by on (#236994)
zoogie wrote:
Yeah, the brute force work has been done. The results are posted here...
Many thanks! That's very useful to have!

zoogie wrote:
Here are the correct non console unique keys... can be trusted without question.
I think that has the same small glitch in there. These three opcodes in ARM9 bootrom,
FFFF9446 movs r0,10h
FFFF94CC movs r0,24h
FFFF9550 movs r0,38h
are executed in loops (with r4=0..3), and they are apparently supposed to set normal key 10h..13h, 24h..27h, 38h..3Bh.
But, with the "mov r0,imm" (instead of "add r0,r4,imm"), they are actually setting only key 10h, 24h, 38h, and leave key 11h..13h, 25h..27h, 39h..3Bh uninitialized (and same for console unique Key.X slots 11h..13h, 25h..27h).
In practice it doesn't make much of a difference, unless the console should rely on whatever is in the uninitialized keyslots - maybe they are zerofilled upon /reset, or maybe contain old values on warmboot?

zoogie wrote:
Using a known-plaintext attack on firm0 would probably be the way to go here. Fortunately for new 3ds, there are only 14 different native firms for overall firmware versions 8.1 to 11.9.
I thought "firm0" and "firm1" (in the boot sectors) would be something different than "native firm" (in the title\00040138 folder).
But now, looking closer at it, it does really look as if all three of them are exact copies of each other, good to know that!
Makes me wonder what the copies are used for...
- "firm0" boot sectors are normally loaded by bootrom.
- "firm1" boot sectors are a backup copy of above, and loaded only if above sectors were corrupted.
- the ".firm" file (within "title\00040138\x0000002" ExeFS) is what for? Is that ever used for any purpose?
Re: 3DS reverse engineering
by on (#237039)
nocash wrote:
I think that has the same small glitch in there. These three opcodes in ARM9 bootrom,
FFFF9446 movs r0,10h
FFFF94CC movs r0,24h
FFFF9550 movs r0,38h
are executed in loops (with r4=0..3), and they are apparently supposed to set normal key 10h..13h, 24h..27h, 38h..3Bh.
But, with the "mov r0,imm" (instead of "add r0,r4,imm"), they are actually setting only key 10h, 24h, 38h, and leave key 11h..13h, 25h..27h, 39h..3Bh uninitialized (and same for console unique Key.X slots 11h..13h, 25h..27h).
In practice it doesn't make much of a difference, unless the console should rely on whatever is in the uninitialized keyslots - maybe they are zerofilled upon /reset, or maybe contain old values on warmboot?

I'm not sure why Nintendo does that, but several keyslots are are in groups of four with the same key values. I don't think this is a bug.
nocash wrote:
I thought "firm0" and "firm1" (in the boot sectors) would be something different than "native firm" (in the title\00040138 folder).
But now, looking closer at it, it does really look as if all three of them are exact copies of each other, good to know that!
Makes me wonder what the copies are used for...
- "firm0" boot sectors are normally loaded by bootrom.
- "firm1" boot sectors are a backup copy of above, and loaded only if above sectors were corrupted.
- the ".firm" file (within "title\00040138\x0000002" ExeFS) is what for? Is that ever used for any purpose?

firm0 and firm1 refer to consecutive 4 MB partitions that native FIRM is installed to (at offset firm0/1 + 0). The actual native FIRM file is usually slightly under 1MB, so most of the firm0/1 partition space is leftover padding.

This is roughly how native firm winds up in firm0/1:
1. A .cia (Ctr Importable Archive) with titleID 00040138x0000002 is downloaded to the 3ds during a system update.
2. The ncch contained in the above .cia is installed to the CTR-NAND file partition in that "title\00040138\x0000002" filepath you mentioned.
3. AM InstallFIRM is called, then the FIRM contained in the above ncch is installed to firm0 and firm1, identical copies.

Other types of FIRMs like TWL and AGB can be launched straight from their ncch containers in CTR-NAND.
Re: 3DS reverse engineering
by on (#238572)
Wheeee, I got my first 3DS program working!
It's blinking the power LED by sending I2C commands from ARM11.
And, once when I got that working, I have added a feature that can power-off the console by simply pushing button A/B. Yeah!!!
The power-off feature is definetly making it most useful 3DS tool that I could think of.

Before getting there, I had spent last some weeks mostly on doing nothing useful... or at least nothing other than considering how to boot from SPI-flash... and then came up with the conclusion that there are too many problems for SPI booting: The built-in 4Kbyte chip doesn't have write-able memory at offset 400h (see DSi wifi thread), there are easy to use solder pads for installing a bigger 128Kbyte chip, but no good way for deactivating the old chip (other than completely removing it; which may be difficult if its bottom plate is soldered to GND), and I had tried to wire an old 128Kbyte chip to my PC, but it didn't work (either bad wiring, or the chip was damaged, or whatever).

So I gave up on SPI-booting, and focused on directly patching the eMMC via hardmod instead. After borrowing another PC card reader I've finally managed to dump the original firmware, so I can now safely unbrick the console if something goes wrong. For actually patching the console, I've spent 2-3 days on writing a relative small DSi tool (it's 2500 lines, mostly for eMMC and SHA256 stuff): It can backup the original NCSD and FIRM sectors, and then patch the NCSD and FIRM sectors for booting 512 bytes of code (ie. the LED-blinking code, and the 512 bytes should be also more than enough for loading more code from some other location).

Some noteworthy troubles: The DSi doesn't seem to strong enough to drive the eMMC CLK line when the 3DS is pulling it low (as so during bluescreen booterror). I had originally tried to fix that by inserting 120 ohm between 3DS CPU and eMMC, but that wasn't enough: I am now using 660 ohm, and that's working. Well, and then I got some things wrong, or wasn't aware of some issues that are different than DSi: The 3DS is booting the FIRM's wirth stack pointer set to zero. After issuing a I2C command, one seems to need to wait a while before sending another command (additionally to waiting for the busy-flag). Plus some mere software bugs in my code. But I somehow got it alive after all : )

The most painstaking part was probably attempting to reboot the 3DS after reflashing the firmware. In the 3DS bluescreen, the power button is even less responsive as than in the 3DS firmware. It's really bewildering: My initial approaches have been to hold the power-button several times for several seconds, hoping that console would eventually switch off.
Once and then, I've succeeded with that method. More often I gave up, and put the console aside... and at some point I noticed that console would sometimes mysteriously power-off seconds after attempting to switch it off. So, I think the power-off procedure is somewhat like so:
-- step 1: Hold power-button pressed for about 5 seconds
-- step 2: Hold your breath and wait about 5 seconds (without attempting to push the button)
Arguably, it would be easier to remove the battery, or to add a mechanical power-supply switch. But I can now use button A/B for power-off, so good-bye to that problem!

The current 512 byte code limit is due to using the two "ACI" blocks in firm0 (I am XORing one block with my FIRM header, the other block with my FIRM code (and redirect NCSD to the first of those blocks)). The ACI blocks are apparently same in all firmware versions (on New3DS at least). Except that, the last byte can be 02 (older firmware) or 03 (newer firmware). So there's a 50% chance to get it working on first attempt (and 100% chance on second attempt with 02/03 flipped). When patching both firm0 and firm1 (with 02 and 03 accordingly) then it should even work at 100% chance on first attempt).

Well, I am pretty happy that I've finally managed to run code on the damn console. After having solved that, I can now finally start testing various things that had been puzzling me for years.

PS.
Here's the DSi source code for patching the 3DS firmware. It's probably not so useful in it's current form (unless you need a LED-blinker) (also note that there's no uninstall function, so it's effectively bricking the 3DS).
Later versions might be useful in case some people don't have any working exploits for their console/region. I don't know if that's an issue... or are there so many 3DS exploits that nobody ever needs hardmodding?
Attachment:
Firm3ds.zip [29.75 KiB]
Downloaded 247 times
Re: 3DS reverse engineering
by on (#238624)
So i registered just to tell you come to IRC. I understand you want to preserve all conversations but nothing will stop you from reposting relevant parts here. Besides nothing will guarantee this site will still exist in 20+ years.
All of the smart people who reverse engineered the 3DS for many years (and some who still do) are on EFnet in #3dsdev. You will get much quicker help if you ask there since it's coming from the experts themselves. We also have a bot posting links to 3dbrew edits to the channel so you will miss nothing. And it can translate all of the error codes Nintendo uses which will help you if you start reverse engineering the firmware.


nocash wrote:
The 3DS is booting the FIRM's wirth stack pointer set to zero. After issuing a I2C command, one seems to need to wait a while before sending another command (additionally to waiting for the busy-flag).

boot9/11 clears every single reg before jumping to the entrypoint. They even use some weird barely documented coprocessor writes to clear all cache lines which is ironic considering how spectacularly they failed in the end with security.
The MCU is a buggy piece of shit. But it's not generally like you need to wait on every single MCU reg write/read. It's just some which will ruin your day if you don't follow the "rules". For example turning on the LCDs has been a problem since forever on New 3DS consoles. If you don't give the MCU at least 3 ms after writing to the reg screens may not turn on or show glitchy lines.

nocash wrote:
The most painstaking part was probably attempting to reboot the 3DS after reflashing the firmware. In the 3DS bluescreen, the power button is even less responsive as than in the 3DS firmware. It's really bewildering: My initial approaches have been to hold the power-button several times for several seconds, hoping that console would eventually switch off.
Once and then, I've succeeded with that method. More often I gave up, and put the console aside... and at some point I noticed that console would sometimes mysteriously power-off seconds after attempting to switch it off. So, I think the power-off procedure is somewhat like so:
-- step 1: Hold power-button pressed for about 5 seconds
-- step 2: Hold your breath and wait about 5 seconds (without attempting to push the button)
Arguably, it would be easier to remove the battery, or to add a mechanical power-supply switch. But I can now use button A/B for power-off, so good-bye to that problem!

Pressing the power button will do nothing but trigger the MCU interrupt notifying the running OS. When you hold it for at least 3 seconds it will force poweroff after another ~7 seconds.


I would highly recommend you install some bootloader like boot9strap or fastboot3DS. That will make your life much easier since you can boot FIRM files directly from the SD card or one of the partitions on eMMC. If you know the installed firmware version you can easily use the known plaintext attack replacing the contents of firm0/1. I'm sure someone will share the matching NATIVE_FIRM for your 3DS (but not here of course) :wink:
Re: 3DS reverse engineering
by on (#238716)
Can I invite anyone back to join more public places? Dev forums could be really helpful to get things done, and also helpful to know what was already done.

MCU Delays: When writing to the power LED register, all following MCU writes were ignored until I had added a delay after each write (the part marked "EXTRA delay" in the source code in previous post).
I don't know if that's specific to the LED register, or if it's needed for all writes. HLL code might be slow enough for not needing that delay at all. And a smaller delay with only 10-100 cycles would be probably enough, too.

EDIT: There seems to be a hardware timer at 17E00604h (related to MPCore Timer interrupts). The bootrom uses that timer to memorize the previous I2C transfer end time (ie. the end of the last data byte of a "device+index+data" transfer sequence), and checks that time before starting a new I2C transfer.
If the difference between current time and memorzized time is 188 or higher then it starts right away. Otherwise it does seem to try to wait "(188-difference)*2 clock cycles".
To compute that value, it does multiply everything by 1000000, then divide it by 268112, and does then carefully undo those steps by multiplying the result by 268112, and then dividing it by 1000000. Which, I assume that alone might serve as a suitable delay, so it could then simply omit waiting for the computed amount of clock cycles ; )

LCD Init Delays: I guess the delays in the bootrom should be more or less suitable; unless they are too slow for practical use. The way how the bootrom calculates the delay timings (with 64bit multiiplactions... and divisions?) is a bit confusing, I'll still need to figure out what those delays mean in terms of "microseconds" or "clock cycles".

LCD/GPU Init: Apart from the delays, I have almost fully figured out how the bootrom is initializing the video hardware for text output. Implementing my own text output functions should be done in 1-2 days... and then I can finally test anything I want : )

Knowing the installed firmware version: No, that isn't required. I got my LED blinker booted & working - and I have no idea what firmware version I have. At least the New3DS seems to have only two(?) different ACI versions, so one could either easily guess/retry, or simply patch both firm0 and firm1 for not needing any retries.

Booting more than 512 bytes: That was already included as untested/unimplemented feature, appended at the end of the source code in previous post. I've meanwhile implemented & tested that stuff, and it worked just fine, so I could now boot larger programs or FIRM partitions or whatever.

Existing Exploits: Yeah, using existing exploits might have been much easier. Somehow the japanese gui, the obscure 3ds guide, the slowish firmware, and the broken top screen got in my way. Altogether I had decided that the easy method is much too annoying, and that it would be more satisfying to look-up the boot process on 3dbrew and to write my own bootloader.
The problem about XORing the installed firmware with homebrew bootcode is that it's only working if it wasn't already patched with other homebrew bootcode. Is there some standarized way for determining if NCSD/FIRM are already patched? And uninstall info for removing the old patch before installing a new one?

My installer is currently storing that kind of uninstall info at the end of the first 4000h-byte block in eMMC. But of course, everyone else is supposedly doing that differently. And the first 4000h bytes are a bit risky anyways (assuming that software crashes with accidental eMMC-writes may tend to destroy just that area).
Re: 3DS reverse engineering
by on (#238747)
You are hitting a brickwall if you try to get them to move anywhere else other than IRC or the Wiki. They would not even move to a different network even though EFnet is motorious for stability problems. I would highly recommend joining that channel as said even if you don't want to use it for dev talk.

When i was measuring how much time/cycles the CPU spends waiting for a single byte I2C transfer (switched to using interrupts since) i got far over 10000 cyles on ARM11 (measured using the MPCore performance monitor) so don't worry about that I2C is a real slug. Performance is not just about code size.
I had no problems at all with the power LED but i only use it as sleep indicator anyway.

There was no need to reverse engineer the GPU/LCD init code. It has been figured out long ago. Most of the register names are missing but it works well: https://github.com/derrekr/fastboot3DS/ ... gfx.c#L249
boot9strap has very similar code.

Everything detects modified FIRM partitions by looking for the sighax signatures. That's it. There is a new exploit since a while which allows pre-bootrom lockout code execution in an easier way than what b9s implements (see superhax folder in the linked repo above).
Re: 3DS reverse engineering
by on (#238791)
Hi nocash, I made an account to get a chance to talk to you. I'm also making a 3DS emulator: https://github.com/PSI-Rockin/Corgi3DS

My emulator runs the boot ROMs and successfully loads NATIVE_FIRM off the NAND. It doesn't get much further than that as Kernel11 needs MMU, but it's also capable of booting ARM9 payloads such as GodMode9 from an SD image. As far as I know, this is the furthest anyone has ever gotten with an LLE 3DS emulator.

I've used your documentation in the past for previous projects, and I'm a big fan of your work. If you would like, I can offer assistance and advice for your emulator - just let me know.

Good luck! Can't wait to see how yours turns out.
Re: 3DS reverse engineering
by on (#238805)
PSI wrote:
...
As far as I know, this is the furthest anyone has ever gotten with an LLE 3DS emulator.

Well, there's this
https://github.com/archshift/llama
The fact that it's coded in Rust is a bit of a killjoy, but at least it's in a pretty advanced stage.
Re: 3DS reverse engineering
by on (#238817)
Llama does appear to have some good work put into it. Judging by its description though (having to manually provide CPU entrypoints for a list of files), it doesn't seem to be capable of booting from the boot ROMs, which would require an encrypted OTP and NAND. Someone please correct me if I'm wrong.
Re: 3DS reverse engineering
by on (#238955)
Yipieh, I got my screen output and backlight enable working. Currently it's only showing a striped bitmap, but it should be no issue to display text output instead of that test screen.

profi200 wrote:
There was no need to reverse engineer the GPU/LCD init code. It has been figured out long ago. Most of the register names are missing but it works well: https://github.com/derrekr/fastboot3DS/ ... gfx.c#L249 boot9strap has very similar code.
Good point. Using that might have been easier. But after disassembling the bootcode, I ended up writing my own code... it took a bit longer than 1-2 days though.
After extracting the GPU/LCD related code from the bootrom, I still about 2400 lines of messy video code. The most messy/buggy/confusing part was the table-based backlight initialization.
Those tables contain only one halfword each. But the bootrom tries to read more than one halfword from each table, and then does weird squaring and interpolation on those table value(s). I guess all that code could make sense with bigger tables, but with the 1-entry-only tables it's just crazy nonsense.

Then I spend some days on having made a silly mistake (most of my GPU register writes did hang the CPU... which turned out to be just caused by using a wrong I/O base address, kinda stupid).

And then I finally got a picture displayed, but the console powered off shortly after backlight enable. I got that fixed by setting 10202000h+240h (and +A40h) to 0020h. A bigger value like 0040h causes power-off. I am not sure what has happened there, part of the problem might be that I've replaced the top-screen backlight by a resistor (which may be too small for large brightness settings). But even then, my initialization should be same as for bootrom error messages (the bootrom does work okay, even with the resistor, but my own code behaves differently for some reason).
EDIT: Seems to be now working as with bootrom. I think the problem was caused by a bug in my I2C reading function for retriving MCU type/version (which had returned all FFh's, ie. lcd_type=F, and mcu_version=F.FF; correct would have been type=1 and ver=3.38hex).

profi200 wrote:
When i was measuring how much time/cycles the CPU spends waiting for a single byte I2C transfer (switched to using interrupts since) i got far over 10000 cyles on ARM11 (measured using the MPCore performance monitor)...
I had no problems at all with the power LED but i only use it as sleep indicator anyway.
Do you know what frequency that MPCore timer counts at? Bootrom code looks like... 134MHz?
And is that 10000 cycles for one raw I2C byte? Or a whole "Device+Index+Databyte" sequence with 3 bytes in total?
The delay is needed only after the last Databyte of each transfer. If you were doing only one transfer per frame, then you have had more than enough delay time.
Btw. I have edited the I2C delay stuff in previous post. The bootrom seems to aim at 2*188 cycles delay after last byte... although my early tests included a much longer DSi-style delay before each byte - which should have worked, too (theoretically, but somehow it didn't work in practice).

profi200 wrote:
Everything detects modified FIRM partitions by looking for the sighax signatures. That's it.
That's not so very suitable for detection. It would require to (RSA-)decrypt the signature and then examine if it contains normal padding bytes (or have a database with all currently known used sighax signatures (which could run into billions if somebody likes bruteforcing more and more variants).
And worst, the FIRM cannot by (AES-)decrypted without OTP dump, so impossible to examine the signatures at all (like, when you get a console, don't have a OTP dump, and want to patch it via hardmod - one could do that only with original FIRM, or with a backup-copy of the original FIRM stored in some unused eMMC sectors). But well, not so much of a problem if there's no standard for backups yet.

PSI wrote:
Hi nocash, I made an account to get a chance to talk to you. I'm also making a 3DS emulator: https://github.com/PSI-Rockin/Corgi3DS
My emulator runs the boot ROMs and successfully loads NATIVE_FIRM off the NAND. It doesn't get much further than that as Kernel11 needs MMU, but it's also capable of booting ARM9 payloads such as GodMode9 from an SD image.
Cool, nice to hear that there is someone doing low-level emulation for 3DS. The other low-level thing that I know of is the Teak/DSP emulation from wwylele, which is also quite impressive (although that part is most distant from the boot process).

Yeah, the MMU is keeping me away from adding 3DS support in no$gba, too. At the moment, I don't even know what page-size it is using. I have no clear picture of what needs to be done for emulating it.

Another small obstacle is that no$gba is currently designed to map most I/O ports to only ARM7, or only ARM9. Whilst 3DS seems to allow to access (many) I/O ports from either ARM9 or ARM11 (or both). Well, that isn't a major problem, but I may need to rewrite a bunch of code, instead of just re-using the old DSi emulation for 3DS.

The good thing about 3DS is that the bootroms are dumped meanwhile, so one can start emulation & research at power-up time. For the DSi, the bootroms are still undumped. And, when I had starting to emulate DSi, it wasn't even known how to decrypt the eMMC bootsectors, so emulation had to start excecution after the yet unknown boot process (that wasn't so funny to work that way).
Re: 3DS reverse engineering
by on (#238967)
The MMU is well-documented on ARM's official docs. I haven't looked too deeply into it, although I know a few things: it's completely accessed through CP15 registers, it works through a "page-walking" scheme (where the code provides pointers to page tables in memory to the MMU), and page sizes range from 4 KB to 16 MB. It seems rather complex, and there's also the issue of having to emulate access privileges...

The good news is that the boot ROMs don't need any MMU emulation at all, so you can feasibly get the boot ROM error screen just by pretending the NAND isn't there. It writes directly to framebuffer to display the error too. I do think you need timer emulation (and interrupts) to get the error screen however, and of course you need PXI (aka IPC).

To actually get a firmware or payload to boot is more involved. You need AES, SHA, and RSA hardware all implemented, and the eMMC protocol must obviously be implemented too. You will also need the OTP and the NAND CID: OTP is used to derive the console-unique keys to decrypt the NAND, and the CID is also used for decryption. The boot process is semi-documented on 3dbrew, so you get some idea of what's going on.
Re: 3DS reverse engineering
by on (#238971)
nocash wrote:
profi200 wrote:
There was no need to reverse engineer the GPU/LCD init code. It has been figured out long ago. Most of the register names are missing but it works well: https://github.com/derrekr/fastboot3DS/ ... gfx.c#L249 boot9strap has very similar code.

Those tables contain only one halfword each. But the bootrom tries to read more than one halfword from each table, and then does weird squaring and interpolation on those table value(s). I guess all that code could make sense with bigger tables, but with the 1-entry-only tables it's just crazy nonsense.

I have not reverse engineered that but usually everyone just dumps the backlight levels from HOME menu. Careful with these since there is apparently no safety limit on the backlight. In the early days someone caused his 3DS to heat up by setting the backlight regs very high.

nocash wrote:
profi200 wrote:
When i was measuring how much time/cycles the CPU spends waiting for a single byte I2C transfer (switched to using interrupts since) i got far over 10000 cyles on ARM11 (measured using the MPCore performance monitor)...
I had no problems at all with the power LED but i only use it as sleep indicator anyway.
Do you know what frequency that MPCore timer counts at? Bootrom code looks like... 134MHz?
And is that 10000 cycles for one raw I2C byte? Or a whole "Device+Index+Databyte" sequence with 3 bytes in total?
The delay is needed only after the last Databyte of each transfer. If you were doing only one transfer per frame, then you have had more than enough delay time.
Btw. I have edited the I2C delay stuff in previous post. The bootrom seems to aim at 2*188 cycles delay after last byte... although my early tests included a much longer DSi-style delay before each byte - which should have worked, too (theoretically, but somehow it didn't work in practice).

You should really take a look inside the ARM11 MPCore TRM. It's half the frequency of the CPU core so 134 MHz.
Frequency formula: http://infocenter.arm.com/help/topic/co ... JJEHG.html
General registers: http://infocenter.arm.com/help/topic/co ... 02s02.html
The performance monitor actually counts all cycles minus a few missed ones at start/reset so it runs at core frequency.

If i recall correctly it was the entire transfer including device and register select. Still very slow for a single byte reg write. In the very early days we polled the MCU from ARM11 (which of course was not a good idea). It worked fine without any delays (with the ARM11 having all caches on so it's really fast). It caused RTC drifts though which we did not notice until later.

nocash wrote:
profi200 wrote:
Everything detects modified FIRM partitions by looking for the sighax signatures. That's it.
That's not so very suitable for detection. It would require to (RSA-)decrypt the signature and then examine if it contains normal padding bytes (or have a database with all currently known used sighax signatures (which could run into billions if somebody likes bruteforcing more and more variants).
And worst, the FIRM cannot by (AES-)decrypted without OTP dump, so impossible to examine the signatures at all (like, when you get a console, don't have a OTP dump, and want to patch it via hardmod - one could do that only with original FIRM, or with a backup-copy of the original FIRM stored in some unused eMMC sectors). But well, not so much of a problem if there's no standard for backups yet.

There are only 2 known FIRM partition sighax signatures in the wild. Ours and the one boot9strap uses. It's enough to check hashes. Of course someone could bruteforce more but everyone is using these 2 only. Bruteforcing more is kinda pointless.
There are 2 different types of backups being made currently. Either full 1:1 eMMC copies or the most important files like OTP, sector one, movable.sed...
The tool almost everyone uses for this is: https://github.com/d0k3/GodMode9

nocash wrote:
Yeah, the MMU is keeping me away from adding 3DS support in no$gba, too. At the moment, I don't even know what page-size it is using. I have no clear picture of what needs to be done for emulating it.

It's actually not so hard. It's a massive step up from MPUs but it really is just a lookup table with attributes/permissions. 2 levels for <section (1 MiB). Then there are supersections which are basically just 16 sections (16 MiB).
Example code (not the nicest but works): https://github.com/derrekr/fastboot3DS/ ... ware/mmu.c
Documentation: http://infocenter.arm.com/help/topic/co ... BHIGI.html

Should be noted that the tables require quite some alignment for the MMU to perform well (all explained in the TRM and the ARM ARM (architecture reference manual).


Btw: A reminder on the #3dsdev IRC channel.
Re: 3DS reverse engineering
by on (#239054)
I am having troubles to extract the Wifi Firmware from the "NWM" module. Here, http://4dsdev.kuribo64.net/thread.php?pid=470#470 plutoo mentioned "Having a quick glance at NWM, it looks like it contains 3 different versions of wlan firmware, labeled 1, 4 and 5."

I have extracted the safe mode NWM .code file (and decompressed it). And had several quick glances (and longer glances) at the file, but I can't see anything "labeled 1, 4 and 5". Is there some table of contents with those 1,4,5 numbers/labels?

What I can find is this:
Code:
  Offset    Content
  3C879h    main code (with "A_INIT" string)
  3D96Ah    main code (with "A_INIT" string)
  451ADh    main code (with "A_INIT" string)
  4F380h    stub code (len 316h) (bytes 36 61 00 21 04 63 .. 1D F0)
  4F698h    stub data (len 38h?)
So there seem to be 3 different main versions (maybe for DSi, 3DS, and 3DS-local-multiplayer?), and, apparently only 1 version for the eeprom-loading stub. Additionally to main/stub, there might be also 1-3 database versions somewhere in the file.
Without table of contents it's hard to guess the exact start address, size, and target address of the above sections. The stub size seems to be 316h bytes... but I can't even find that size value in the .code file. Am I missing something obvious?
Re: 3DS reverse engineering
by on (#239064)
Okay, I've found the DSi-style "00524C00h" load address, and alongsides also found all the other stuff at nearby addresses, including CMP opcodes for the "label 1,4,5" part. Instead of a table of contents, the addresses are just hardcoded constants in the literal pool. Base address seems to be 100000h, ie. ARM address 13D84Ch means file offset 3D84Ch.
Code:
  Offset
  07248h    value 00524C00h   ;dst for stub.data and/or main.code?          ;\
  0724Ch          00145142h ;src.end  ;\len 78F6h  (2nd main) (aka label 5) ;
  07250h          0013D84Ch ;src      ;/                                    ;/
  ...
  097C4h    cmp r0,1h         ;\
  097C8h    cmp r0,4h         ; "labels" for different main's
  097CCh    cmp r0,5h         ;/
  ...
  098E8h    value 00524C00h ;dst for stub.data and/or main.code             ;\
  098ECh          00145142h ;src.end  ;\len 78F6h  (2nd main) (aka label 5) ;
  098F0h          0013D84Ch ;src      ;/                                    ;/
  098F4h    value 0053FE18h ;dst for database?                          ;\
  098F8h          0014F380h       ;\len 1E8h (probably database?)       ;
  098FCh          0014F198h       ;/                                    ;/
  09900h    value 00527000h ;dst for stub.code (aka 927000h)            ;\
  09904h          0014F696h ;src.end ;\len 316h (stub.code)             ;
  09908h          0014F380h ;src     ;/         <-- file.offs = 4F380h  ;/
  0990Ch          0014F6D0h ;src.end ;\len 38h (stub.data)
  09910h          0014F698h ;src     ;/
  0991xh          ..
  09920h          0013D84Bh       ;\len FD3h (1st main) (aka label 1)
  09924h          0013C878h       ;/
  09928h          0014F197h       ;\len A053h (3rd main) (aka label 4)
  0992Ch          00145144h       ;/
Well, with that... I guess I could now try to upload the wifi firmware to the Xtensa CPU, and see what happens.
Re: 3DS reverse engineering
by on (#239065)
bürp

so I see you're attempting to emulate the 3DS, good luck with this project

I have a few things to say, tho

nocash wrote:
Yeah, the MMU is keeping me away from adding 3DS support in no$gba, too. At the moment, I don't even know what page-size it is using. I have no clear picture of what needs to be done for emulating it.

Another small obstacle is that no$gba is currently designed to map most I/O ports to only ARM7, or only ARM9. Whilst 3DS seems to allow to access (many) I/O ports from either ARM9 or ARM11 (or both). Well, that isn't a major problem, but I may need to rewrite a bunch of code, instead of just re-using the old DSi emulation for 3DS.

The good thing about 3DS is that the bootroms are dumped meanwhile, so one can start emulation & research at power-up time. For the DSi, the bootroms are still undumped. And, when I had starting to emulate DSi, it wasn't even known how to decrypt the eMMC bootsectors, so emulation had to start excecution after the yet unknown boot process (that wasn't so funny to work that way).

if I were you, I would make a separate no$3ds/whatever emulator for this. the 3DS may share a lot of hardware with the DSi for backwards compatibility purposes, but for the purpose of running 3DS software, most of the underlying hardware is completely different.

I'd just worry that cramming all these consoles into one project would result in a bloated codebase, but eh, your choice.

other than that, well, have fun! emulating the 3DS at low level sounds like an interesting challenge.

--

also, if you're ever interested into updating the DS documentation: I have a whole pile of errata/additions sitting at the melonDS forum (I would link to the thread, but I'm afraid I might get hit by some spam protection, seeing as I'm a newb here)

there's also quite a bunch of low-level research on the 3D GPU thing it uses, but enough offtopicness
Re: 3DS reverse engineering
by on (#239066)
Go ahead and post the link. We don't have a "no external links for new users" policy.
Re: 3DS reverse engineering
by on (#239067)
'aight

general GBAtek addendum/errata
the development forum for more
3D GPU info here and here
Re: 3DS reverse engineering
by on (#239176)
profi200 wrote:
If i recall correctly it was the entire transfer including device and register select. Still very slow for a single byte reg write
Well, about 10000 cycles at 134MHz for 24bits... would be 3us per bit. Maybe not so fast for modern hardware, but also not too slow.

profi200 wrote:
There are only 2 known FIRM partition sighax signatures in the wild. Ours and the one boot9strap uses. It's enough to check hashes.
Yes, except, from my "hardmod without OTP dump" perspective: I couldn't decrypt the FIRM sectors without OTP, and thus couldn't check what kind of hashes are in there (and if I had OTP dump then I wouldn't need to check the hashes because I could just overwrite everything with my own FIRM code/header).
But well, my hardmod approach is probably quite uncommon, and most other people use softmod/exploits. On the other hand, there are probably a bunch of people with bricked consoles, then they would need hardmods (but yeah, I guess they would rarely know how to repair even simple issues like deleted files, so the hardmod won't really help in most cases).

---

I haven't looked into 3DS MMU yet, but "page walking" sounds a bit familar. As far as I remember, 80386 is having one table for larger memory blocks with pointers to tables for the smaller 4Kbyte page addresses (and access rights). I guess 3DS works similar.

PSI wrote:
To actually get a firmware or payload to boot is more involved. You need AES, SHA, and RSA hardware all implemented, and the eMMC protocol must obviously be implemented too. You will also need the OTP and the NAND CID: OTP is used to derive the console-unique keys to decrypt the NAND, and the CID is also used for decryption.
I already have all that program code from the DSi emulation (plus a newer SHA256 function for 3DS eMMC decoding). It would be quite some work to map that functions to the 3DS memory map - but at least I do have the code, and more or less know what to do with it.

Arisotura wrote:
if I were you, I would make a separate no$3ds/whatever emulator for this. the 3DS may share a lot of hardware with the DSi for backwards compatibility purposes, but for the purpose of running 3DS software, most of the underlying hardware is completely different.
I'd just worry that cramming all these consoles into one project would result in a bloated codebase, but eh, your choice.
Yeah, I had (originally) thought that 3DS emulation would require new emulator instead of adding 3DS support no$gba. But then... the 3DS does support GBA/NDS/DSi modes, so it would be contraproductive to start a new project with all that features removed.

At 1st glance the 3DS I/O map looks fairly different than DSi, but at 2nd glance it's merely using new base addresses for the old I/O ports. Well, and at 3rd glance there might be hundreds of other subtle differences that I am not aware of yet - but for now, I think I would start with expanding no$gba instead of starting a new emulator, I could still split projects later if needed.

The nastiest part is the MMU. Even if it's relative easy to emulate - it will slowdown the whole CPU emulation. It will require to translate all addresses, and also to check if sequential opcodes fetches are crossing into a new memory page. There it'll really make sense to use two different code versions: fast emulation without 3DS support, and a slower version with 3DS support.

But I am still miles away from emulating MMU or GPU. Before going there, I will first need to emulate the bootrom, and/or basic FIRM code.

Arisotura wrote:
also, if you're ever interested into updating the DS documentation: I have a whole pile of errata/additions
Thanks, yes, I am interested! Ah, on the other hand I am busy with 3DS at the moment (and for some of the older NDS specs I don't even remeber what I had written there years ago). Maybe I can go through the errata step-by-step, and post questions/comments in a separate thread... at times when I need a break from 3DS stuff : )

---

At the moment I am looking into porting Wifiboot from nds/dsi to 3ds. That does also require hundreds of subtle changes (memory map, I/O map, missing SWI function on 3DS, missing NDS-style 16bit DMA channels, different video hardware, and so on). But it should be doable, in 1-2 weeks or so.
The nice thing would be that it would allow to upload FIRM files directly without needing the 3DS OS at all. I guess that's something that wasn't done by anybody yet?
Currently I am still wifi-uploading my FIRM code to DSi, and then use the DSi to rewrite the hardmodded 3DS FIRM. It's working fine, except that I need to plug/unplug the 3DS from the DSi's SD/MMC slot for each upload (plus, I have only one battery charger, so one of two console regularily dies if I forget to switch them off after uploading).
Re: 3DS reverse engineering
by on (#239181)
A bit off topic but

nocash wrote:
Currently I am still wifi-uploading my FIRM code to DSi, and then use the DSi to rewrite the hardmodded 3DS FIRM. It's working fine, except that I need to plug/unplug the 3DS from the DSi's SD/MMC slot for each upload (plus, I have only one battery charger, so one of two console regularily dies if I forget to switch them off after uploading).


1) Isn't it cool to upload things through WIFI to DS(i)? That speeds up the development time testing a lot. (https://bitbucket.org/Coto88/toolchaing ... server/src)

2) Also you are one the few DIY guys I know, I thought you already had a DIY male USB connector, by ripping the data cables and soldering the positive (+) and negative (-) ends with two DSi-3DS charger port connectors

I have two of these, one for plugging GBA/NDS/DSlite/DSi and the other exactly as above for DSi/3DS

edit:
nocash wrote:
The nastiest part is the MMU. Even if it's relative easy to emulate - it will slowdown the whole CPU emulation. It will require to translate all addresses, and also to check if sequential opcodes fetches are crossing into a new memory page. There it'll really make sense to use two different code versions: fast emulation without 3DS support, and a slower version with 3DS support.


3) the MPU emulation is very similar to MMU emulation (MPU stalls/changes CPU into dataabort/instruction abort if desired), except there is no translation tables but the region protector behaves the same. I planned to support MPU emulation in gbaemu4ds but I dropped the project.

The slowdown happens during CPU Read/Writes and checking the current MPU/MMU state. The problem is somewhat solved by saving up to n MPU/MMU "states". Also there is to consider the current AMBA 2.0 (AHB Bus Protocol) --> NDS(i)

and
AMBA 3 (AXI Bus Protocol) --> 3DS

implementation. Since the MPU/MMU will halt the processor(s) by an exact cycle duty depending on the ARM bus.

AMBA 2.0 (AHB Bus Protocol) vs AMBA 3 (AXI Bus Protocol):
http://tiny.cc/4aclvy
Re: 3DS reverse engineering
by on (#239191)
nocash wrote:
Well, about 10000 cycles at 134MHz for 24bits... would be 3us per bit. Maybe not so fast for modern hardware, but also not too slow.

134 MHz is half of the ARM11's core clock. On New 3DS cores can even run up to 804 MHz (clock multiplier 1, 2 or 3).

nocash wrote:
At the moment I am looking into porting Wifiboot from nds/dsi to 3ds. That does also require hundreds of subtle changes (memory map, I/O map, missing SWI function on 3DS, missing NDS-style 16bit DMA channels, different video hardware, and so on). But it should be doable, in 1-2 weeks or so.
The nice thing would be that it would allow to upload FIRM files directly without needing the 3DS OS at all. I guess that's something that wasn't done by anybody yet?

No one has attempted this yet due to differences in hardware/WiFi module firmware and because it's super complex writing a driver and network stack for this monster. All that must be done on ARM11 since the IRQs are only routed to the ARM11 GIC[1] (generic interrupt controller).


[1] ARM doesn't actually call it GIC (for ARMv6 it seems to have no name at all?) but it's almost identical to the very first (official) GIC that was introduced in ARMv7. Really the only real difference seem to be the TrustZone support and a few changed registers. It's way more advanced than any the IRQ hardware used on 3DS ARM9 and on GBA/DS(i).
Re: 3DS reverse engineering
by on (#239409)
coto wrote:
1) Isn't it cool to upload things through WIFI to DS(i)? That speeds up the development time testing a lot.
Yup, wifi is very useful for testing things. Only, there seem to be fewer and fewer people wanting to test anything. Some years ago there've been at least a few people saying "generally interested, but don't know how to use WEP". And after adding WPA/WPA2 support... the scene reply has been a massive wall of silence : )

coto wrote:
The slowdown happens during CPU Read/Writes and checking the current MPU/MMU state. The problem is somewhat solved by saving up to n MPU/MMU "states".
You mean caching the MMU page addresses for the most recent memory pages... in emulation?
Hmmmm, hardware-caches should have zero overload, but I would think that searching for cache hits is very when doing it by software.
On the other hand, if there's a 90% chance for cache hits to occur on the first cache entry... then it might be relative fast, even in software.

coto wrote:
AMBA 2.0 (AHB Bus Protocol) vs AMBA 3 (AXI Bus Protocol): http://tiny.cc/4aclvy
What is that AXI stuff that everybody is talking about??? Is that really a thing?
The above doc doesn't look too useful, it doesn't have tech specs. And, giving it quick glance, it doesn't even help on getting a glimpse of an idea on what it is all about (except that it's a new and innovative name for memory addressing, or so).
What I have found out (in another document) is that AXI is supposed to stand for "Advanced eXtensible Interface".
The 3DS is said to have "AXI" registers at 1020F000h, and "AXI" WRAM at 1FF80000h. I've no idea what that means (the WRAM area seems to be just normal RAM mapped to both CPUs, so it looks about same as normal Main RAM, except that it's smaller, and perhaps a bit faster than Main RAM).

PSI wrote:
and of course you need PXI (aka IPC).
That! There, too! Why is everybody calling that PXI??? And what does PXI mean? Did Nintendo drop the original name, and rename it from IPC to PXI at some point?
It seems to have started on dsibrew. And now I am feeling surrounded by AXI and PXI, and I wouldn't be surprised if Dixie and Trixie were joining in soon.

profi200 wrote:
No one has attempted this yet due to differences in hardware/WiFi module firmware and because it's super complex writing a driver and network stack for this monster. All that must be done on ARM11 since the IRQs are only routed to the ARM11 GIC[1] (generic interrupt controller).
I think (or hope) that ARM9 interrupts registers have Wifi IRQs in bit18/bit19. Or well, if that isn't the case, then one could still forward IRQs from ARM11 to ARM9 if neccessary.

But yeah, tiny details like interrupts & timers are a "problem" when porting from NDS/DSi to 3DS. Well, not a real problem, but it was more work than expected to get that little boring details working. I spend the last some days on figuring out how 3DS IRQs are working, and adjusting about hundred NDS-specific parts in the wifiboot source code. I think I am now having most of the timer/irq stuff working. The wifiboot code is now booting up, with timers/irq's enabled, and then hangs in the SDIO init function (which is good, because I just wanted to reach that stage for now, so I can begin with the actual SDIO related coding).

ARM9 Interrupts:
There's this https://www.3dbrew.org/wiki/IRQ_Registers on 3dbrew. That looks straight like GBA/NDS/DSi. The problem is that the meaning of the separate bits is rather unclear. I assume that the abbreviations were ripped from some leaked devkit info, and nobody really means what they mean?
I can guess most bits. Except, what the fuck is a CGC??? And a CGC_DET? I've found some possible meanings on http://acronyms.thefreedictionary.com/CGC but even then... is it for crypto-graphic-cancer detection?

ARM11 Interrupts:
There's this https://www.3dbrew.org/wiki/ARM11_Interrupts on 3dbrew. There's the oppoite problem: The IRQ numbers are more less well described, but the registers aren't described at all (the weird InterruptData structure seems to refer to kernel RAM or so, not to the hardware registers).
What is relative obvious is that ARM11 bootrom handles interrupts via 17E00000h and up. And the wiki mysteriously refers to 17E00000h as "MPCore private memory region".
profi200 wrote:
You should really take a look inside the ARM11 MPCore TRM. It's half the frequency of the CPU core so 134 MHz.
Frequency formula: http://infocenter.arm.com/help/topic/co ... JJEHG.html
General registers: http://infocenter.arm.com/help/topic/co ... 02s02.html
Okay, thanks. I've downloaded the http://infocenter.arm.com/help/topic/co ... p0_trm.pdf linked on that pages, that seems to contain all info needed for ARM11 timers & interrupt registers. I've spend some days on copying the MPCore description into gbatek (and fixing the table formatting). I'll still need to erase all the trash: It's currently about 1100 lines for a few dozen of registers, including utterly useless references to tables and figures:
Code:
This section contains the information that you were looking for.
See Figure 1.2.4 for the information about what you are looking for.
Figure 1.2.4: The information that you were looking for.
  Bit  Name                Type  Description
  [0]  Aviation Disasters  R/W   0'b0 Disable
                                 1'b0 Enable
I don't know why anybody would create such documents. Is that some legal/warranty/safety thing? Like, the document most contain "Figures" for everything, and to be on the safe side, it must also assign a number like 1.2.4 to each figure, and it must explicitely state that the information is contained in figure 1.2.4? Hmmm, or maybe ARM just didn't know how to disable the "auto-generate figures" in their document editor. Personally, I think that the actual information gets lost among all those figure numbers.
PS. Going by the glossary, the meaning of MPCore is not defined. But, reading between the lines, I assume that MP stands for Multi Processing?
Re: 3DS reverse engineering
by on (#239417)
nocash wrote:
The above doc doesn't look too useful, it doesn't have tech specs. And, giving it quick glance, it doesn't even help on getting a glimpse of an idea on what it is all about (except that it's a new and innovative name for memory addressing, or so).


Dude. Just google around :

ARM AXI BUS (3DS)

ARM AHB BUS (NDS)
(reference:
http://www.eecs.umich.edu/courses/eecs3 ... e_SPEC.pdf)

The doc explains how to build devices from the outter (IDE-protocol) perspective. It´s the ARM bus. Also IIRC these use(d) master-slave setups and a legacy AXI-to-AHB unit which allows to add AHB devices onto AXI bus. If you search about it, things like MMU and the CPU require the ARM (current bus implementation used through it) bus to be understood first and then these will be emulated properly. (unlike relatively "wired" or "single" control bus, where glued hardware only looks up through a single master clock (CLK) signal and split activity through address and data bus-es). The ARM cores have control bus units for each masters-slave device hooked up to the ARM bus.

(Single) Control Bus definition:
https://en.wikipedia.org/wiki/Control_bus
Re: 3DS reverse engineering
by on (#239420)
nocash wrote:
You mean caching the MMU page addresses for the most recent memory pages... in emulation?

Practical MMU hardware caches page addresses for recently accessed memory pages as a third specialized cache alongside the data and instruction caches. It's called a translation lookaside buffer (TLB). MIPS and some SPARC processors have only a TLB; software must move page table entries in and out of the TLB.
Re: 3DS reverse engineering
by on (#239426)
nocash wrote:
Only, there seem to be fewer and fewer people wanting to test anything. Some years ago there've been at least a few people saying "generally interested, but don't know how to use WEP". And after adding WPA/WPA2 support... the scene reply has been a massive wall of silence : )

It's not about testing. It's getting increasingly more complicated and no one wants to spend the time + digging through huge docs or existing driver code like in the Linux kernel.

nocash wrote:
The 3DS is said to have "AXI" registers at 1020F000h, and "AXI" WRAM at 1FF80000h. I've no idea what that means (the WRAM area seems to be just normal RAM mapped to both CPUs, so it looks about same as normal Main RAM, except that it's smaller, and perhaps a bit faster than Main RAM).

These regs seem to be for prioritising. You can give certain bus masters more priority over others. AXIWRAM is probably used because that's what it is. It's attached to the AXI bus. I don't know where the term originated.

nocash wrote:
That! There, too! Why is everybody calling that PXI??? And what does PXI mean? Did Nintendo drop the original name, and rename it from IPC to PXI at some point?

It's the new official name. It was first found in symbols left in code iirc. Same for most other obscure names.

nocash wrote:
I think (or hope) that ARM9 interrupts registers have Wifi IRQs in bit18/bit19. Or well, if that isn't the case, then one could still forward IRQs from ARM11 to ARM9 if neccessary.

Forwarding IRQs would be pretty inefficent. The ARM11 is meant to handle applications, network and more. Fun fact: The WiFi bottleneck is in part due to the slow CPUs. Where i know this from? WiFi speed increased on New 3DS with higher clock :wink: The ARM9 would slow that down a bit more.

nocash wrote:
But yeah, tiny details like interrupts & timers are a "problem" when porting from NDS/DSi to 3DS. Well, not a real problem, but it was more work than expected to get that little boring details working. I spend the last some days on figuring out how 3DS IRQs are working, and adjusting about hundred NDS-specific parts in the wifiboot source code. I think I am now having most of the timer/irq stuff working. The wifiboot code is now booting up, with timers/irq's enabled, and then hangs in the SDIO init function (which is good, because I just wanted to reach that stage for now, so I can begin with the actual SDIO related coding).

ARM9 Interrupts:
There's this https://www.3dbrew.org/wiki/IRQ_Registers on 3dbrew. That looks straight like GBA/NDS/DSi. The problem is that the meaning of the separate bits is rather unclear. I assume that the abbreviations were ripped from some leaked devkit info, and nobody really means what they mean?
I can guess most bits. Except, what the fuck is a CGC??? And a CGC_DET? I've found some possible meanings on http://acronyms.thefreedictionary.com/CGC but even then... is it for crypto-graphic-cancer detection?

It's the same IRQ hardware on ARM9 as on DS(i). Only the master enable is missing but the CPSR I bit of the CPU does the same job. Where the weird names come from i explained above. It's from symbols left in the code. We don't touch SDKs and add that straight to 3dbrew since that can get 3dbrew in trouble (NDA breach and shit).

nocash wrote:
ARM11 Interrupts:
There's this https://www.3dbrew.org/wiki/ARM11_Interrupts on 3dbrew. There's the oppoite problem: The IRQ numbers are more less well described, but the registers aren't described at all (the weird InterruptData structure seems to refer to kernel RAM or so, not to the hardware registers).
What is relative obvious is that ARM11 bootrom handles interrupts via 17E00000h and up. And the wiki mysteriously refers to 17E00000h as "MPCore private memory region".
profi200 wrote:
You should really take a look inside the ARM11 MPCore TRM. It's half the frequency of the CPU core so 134 MHz.
Frequency formula: http://infocenter.arm.com/help/topic/co ... JJEHG.html
General registers: http://infocenter.arm.com/help/topic/co ... 02s02.html
Okay, thanks. I've downloaded the http://infocenter.arm.com/help/topic/co ... p0_trm.pdf linked on that pages, that seems to contain all info needed for ARM11 timers & interrupt registers. I've spend some days on copying the MPCore description into gbatek (and fixing the table formatting). I'll still need to erase all the trash: It's currently about 1100 lines for a few dozen of registers, including utterly useless references to tables and figures:
Code:
This section contains the information that you were looking for.
See Figure 1.2.4 for the information about what you are looking for.
Figure 1.2.4: The information that you were looking for.
  Bit  Name                Type  Description
  [0]  Aviation Disasters  R/W   0'b0 Disable
                                 1'b0 Enable
I don't know why anybody would create such documents. Is that some legal/warranty/safety thing? Like, the document most contain "Figures" for everything, and to be on the safe side, it must also assign a number like 1.2.4 to each figure, and it must explicitely state that the information is contained in figure 1.2.4? Hmmm, or maybe ARM just didn't know how to disable the "auto-generate figures" in their document editor. Personally, I think that the actual information gets lost among all those figure numbers.
PS. Going by the glossary, the meaning of MPCore is not defined. But, reading between the lines, I assume that MP stands for Multi Processing?

The regs are already documented so why copy the official doc from ARM? Don't get me wrong the ARM docs are confusing sometimes but it's all already documented in detail. And i don't know why it's formatted that way. Probably the usual bloated buisiness "it must look perfect" thing. Why we call it MPCore private memory region you probaly already figured out. It's ARM's official name. MPCore seems to be their name for multi core CPUs but they dropped it in ARMv7(?).


And regarding AXI:
It really doesn't matter. You don't need to know all of it unless you want to emulate on the transistor level. Only the delays/stalls and the prioritizing stuff is interesting for the average low level emu.
Re: 3DS reverse engineering
by on (#239463)
Thanks for the background info on where the abbreviations came from! In some cases I would have wished that the 3dbrew wiki would be more clear on the meaning of that abbreviations, like "MPCore = ARM's interrupt controller". Or just mark unknown meanings as such, like "CGC = Unknown purpose".

profi200 wrote:
The regs are already documented so why copy the official doc from ARM?
The MPCore stuff is already documented? Do you mean elsewhere than in official docs from ARM?

profi200 wrote:
It's not about testing. It's getting increasingly more complicated and no one wants to spend the time + digging through huge docs or existing driver code like in the Linux kernel.
Yeah, I have probably really spent lots time and digged through tons of atheros driver code.
Well, and after all that work, I hoped that SDIO/WPA/WPA2 support in the DSi wifiboot tool would allow hordes of homebrew DSi devr's to test their own code on real hardware - but somehow those hordes of devr's never showed up (the feedback was a bit disappointing: I know of only one person who had downloaded my wifiboot tool - and apparently didn't even got it working).
I am wondering if the feedback on other wifi tools (like FTP for nds/dsi/3ds) is equally rare?

profi200 wrote:
Forwarding IRQs would be pretty inefficent. The ARM11 is meant to handle applications, network and more. Fun fact: The WiFi bottleneck is in part due to the slow CPUs. Where i know this from? WiFi speed increased on New 3DS with higher clock :wink: The ARM9 would slow that down a bit more.
I guess that's more poorly written driver code, not the hardware being too slow. IRQ forwarding would probably cost only 100 cycles per packet.
The homebrew NDS/DSi wifi code is using ARM7+ARM9, so a 3DS port would run on ARM9+ARM11 accordingly (ARM9 for low-level SDIO, and ARM11 for high-level TCP/UDP etc). Of course, it could be more straight-forward to handle everything on one CPU, but it would be some extra work to modify the existing code.

The homebrew DSi code reached only 400-600 Kbyte/s (the difference between 400 and 600 Kbyte/s depends on the access point). I don't know why it doesn't reach 5-6 Mbyte/s, I think it might be an atheros-hardware issue, or just messy TCP flow in software, not just the DSi CPU being too slow.

One cpu/memory related bottleneck is that the packet body isn't word-aligned (the packet header has an odd amount of halfwords). That's a problem when copyting data from from "packet_buffer" to actual "target_address".
On NDS/DSi, I have solved by using the old NDS DMA registers with 16bit transfer units (which work with halfword aligned SAD/DAD addresses). Does the 3DS support anything similar?

coto wrote:
Dude. Just google around : ARM AXI BUS (3DS)
I tried to, but at that time I only knew that the "3DS has AXI" what does that mean? That didn't yield any meaningful search results.
Well, that was some weeks ago - before you had mentioned that it's an ARM BUS, which really good to know, thanks!
At the moment, I think it isn't so important to understand the differences between AXI and AHB. Or is there something really important to know? Like 3DS memory accesses being fundamentally incompatible with DSi-style memory accesses? (So far, my code and stacks and variables seem to be more or less working).

But a more general memory/cache question: NDS/DSi is having some issues with caches (ARM9 cache not updated when DMA or ARM7 changes memory). Does 3DS have similar issues?
I hope that the ARM11 cores are all sharing the same cache (or otherwise, that they can notify each other of memory changes & automatically update their caches)?
With the CDMA/XDMA being made by ARM, I hope that these DMA's are integrated with the corresponding CPU caches?
On the other hand, I guess nintendo's NDMA isn't aware of CPU caches?
And ARM9 cache isn't aware of ARM11 cache?

Oh, and ARM9 is having DTCM and ITCM. Does ARM11 have that kind of memory, too?


Problem!
My wifi init code starts with sending SDIO CMD5 (the IO_SEND_OP_COND command assigning/detecting the supported SDIO bus voltages). That's working fine on DSi. But on 3DS I am just getting a transfer timeout (reading the SDIO irq/status register returns [1012201Ch]=20C00631h, with bit22 meaning CMDTIMEOUT).
I suspect that the problem is caused by some 3DS control register holding the atheros chip in reset state, or disabling some clock signal.
On the DSi, there are these wifi-related config registers:
Code:
 - SCFG_EXT7.bit19 needed for SDIO controller (else 4004Axxh-4004Bxxh disabled)
 - SCFG_CLK7 seems to be NOT needed for SDIO clock enable (unlike as for SDMMC clock)
 - SCFG_WL.bit0 seems to be wifi-related (but effect is unknown)
 - GPIO_WIFI.bit8 needed for AR6013G chips (else SDIO Function 1 fails)
 - I2C register BPTWL[30h] needed for LED and SDIO (else SDIO fails badly)
 - RTC.FOUT pin as configured by firmware (else WMI commands/events fail)
For 3DS, there are some registers that may have similar purposes:
Code:
 - CFG11_WIFIUNK.bit4 should be set
 - CFG11_WIFICNT.bit0 should be set or cleared?
 - I2C register MCU[2Ah] should be whatever?
I have tried to init the above registers (and tried to set almost all unknown CFG9/CFG11 bits, and to set/clear all GPIO registers), but that didn't help.
Any ideas what else to try?
The NWM driver does directly access the two CFG11_WIFIxxx registers. Maybe it's also accessing further I2C, MCU, RTC or GPIO or other stuff (but if so, then it's probably done via OS functions instead of via direct I/O addressing, and I don't know enough about the 3DS OS to figure out if or how it's doing that).
Re: 3DS reverse engineering
by on (#239465)
nocash wrote:
At the moment, I think it isn't so important to understand the differences between AXI and AHB. Or is there something really important to know? Like 3DS memory accesses being fundamentally incompatible with DSi-style memory accesses? (So far, my code and stacks and variables seem to be more or less working).


Of course it is important, but I think it requires a rather mature Nintendo DS emulator that is able to run NDS titles fully. As the earlier document describes thoroughly how to emulate the MPU (on AHB, being the NDS), which is useful for GBA virtualization as seen in open source GBA "hypervisors" for NDS. There's no other workaround for running GBA code (at least when a data abort/instruction abort happens due to unmapped memory read/written)


On the 3DS I don't know. Since GBA VC games are able to run from 1:1 GBA images, that leads me to believe there is some sort of Memory Mapping scheme in the GBA VC emulator using the MMU "ARM demand paging" feature, described in these two docs:

(1: armv7 doc, but still useful info to understand the 2: armv6 doc)

1)
http://liacs.leidenuniv.nl/~rietveldkfd ... rm-mmu.pdf (Page 36 onwards, the "2 level page tables." will help to understand

2)
this
Re: 3DS reverse engineering
by on (#239468)
Got it going a step farther!
The hardware specs on https://www.3dbrew.org/wiki/GPIO_Registers are rather meaningless. But the software specs on https://www.3dbrew.org/wiki/GPIO_Services are revealing a bit more info (including on hardware bits). Namely, this GPIO setting "[10147028h]=1" fixes the SDIO timeout issue.
The parts that I am still concerned about are the 3DS equivalents to BPTWL[30h] and especially RTC.FOUT. But those will be needed only later in wifi init... I don't know yet if there will be really any problems with that stuff.

coto wrote:
On the 3DS I don't know. Since GBA VC games are able to run from 1:1 GBA images, that leads me to believe there is some sort of Memory Mapping scheme in the GBA VC emulator using the MMU "ARM demand paging" feature, described in...
I would assume that they are loading the GBA ROM-image to Main RAM, and then map the RAM to the GBA's physical ROM-address space. Using vitual MMU addresses for GBA mode would be very unexpected. But if they do, then I promise that I will read all the AXI and AHB docs ; )
Re: 3DS reverse engineering
by on (#239477)
Almost there. Uploading the four firmware blocks seems to work fine, and I am getting meaningful responses for the chip_id, eeprom_id, and rom_version.

The part where I am stuck now is the final "handshake" after firmware upload, the first handshake message (from the wifi chip) seems to arrive... but my code is using NDMA for transferring that kind of messages... and it does look as if 3DS doesn't have any WifiSDIO startup mode for NDMA (I've tried all unknown modes: 06h,07h,0Dh,0Eh, but none worked).

The other option on ARM9 side would be XDMA, currently there seem to be only two known XDMA startup modes (00h and 07h).
Does somebody have a list with more XDMA modes? That would be very useful! : )

Well, and otherwise I am in the unfortunate situation of having a (supposedly) perfectly working wifi engine, but on the wrong CPU : /

Then I could try port the whole ARM9 code to ARM11 side (lots of work). Or go dirty, and forward a "please do a CDMA for me" message from ARM9 to ARM11 via IPC interrupts (ugly, but it might be the fastest way to get things working, and it would help to implement a better solution later on).
Re: 3DS reverse engineering
by on (#239535)
The wifi hardware interface seems to be working fine now. The firmware upload/handshake is passing okay, and wifiboot then goes into channel scanning mode. For testing, I've made it to display the names of all access points in the neighborhood, which is working pretty well.

With NDMA didn't work. There seems to be no SDIO startup mode (for auto-starting on each block of a multiblock transfer). So I've tried to manually start NDMA on each separate block (with polling the SDIO_IRQ32 register). That is actually working okay on DSi - but doesn't work on 3DS (it passes through the NDMA's, but then hangs when waiting for the final SDIO DATAEND flag). I don't know what is wrong there. It almost looks as if some SDIO or NDMA bits are slightly different on 3DS? Or it's some sinister timing issue.

Without NDMA does work. The DSi wifiboot code did already have an option for using DATA16 with LDRH/STRH (instead of DATA32 with NDMA), so I just had to enable that option. The downside is that manually reading 16bit data tends to be slower (or, when using faster/cached memory or 16bit DMAs, then it can become too fast: I had problems with that on DSi, it became unstable when reading multiple blocks without delays at block boundaries).
Anyways, for now, the DMA-less 16bit access seems to be working well enough.

Still missing is overall software stuff for handling files with FIRM headers, ie. loading them into no$gba, sending them with the no$gba wifi upload function, and receiving them with the 3ds wifiboot code, well, and then jumping to the entrypoints. And, alongsides I will need to rearrange my memory map (wifiboot is currently executing in AXI RAM, where it would get overwritten by the uploaded file).
I guess moving wifiboot into Main RAM should work (FIRM's don't seem to be allowed to be loaded to Main RAM; but Main RAM might be slower than preferred).
Or I could try to execute code in VRAM, if that's working and faster? Theoretically FIRM blocks could be loaded into VRAM, so that could be a conflict - but the conflict is already there because of the screen output during wifi transfers).
But before continuing with that stuff, I will probably pause for a week & enjoy some summer days.
Re: 3DS reverse engineering
by on (#239597)
I've made some more progress on my own emulator. I hit a wall in getting Process9 to work, so I implemented the ARM11 MMU to get Kernel11 further. It's very basic and will break once we hit userland, but it'll have to do for now. I also had to redesign my ARM11 interrupt handling to support more than a single core.

With this, both the appcore and syscore are active, and I was able to get rid of some hacks I used to get Process9 to boot. It now crashes because Kernel11 reads from DSP memory, which is unimplemented. This is where the sysmodules are located. I need to implement ARM11 timers and improve my MMU emulation before I go further.

AXI seems to be a way for the cores to synchronize with each other. The cores share kernel code and data in AXI WRAM, so they use "load exclusive" and "store exclusive" operations as some sort of mutex/semaphore. These operations only work properly when the memory system has a monitor for those exclusive operations.
Re: 3DS reverse engineering
by on (#239772)
Another progress report! After fixing countless CPU, MMU, DMA, eMMC, and PMR bugs, we finally have sysmodules running on the emulator. Kernel11 manages to load these modules: PXI, FS, PM, and SM. All four modules are running as their own processes mapped in userland. Process9 initialization is complete, and the ARM9 can accept PXI commands from the ARM11.

PM tries (and fails) to load the NS module. Process9 is unable to find NS for some reason, which I'm currently investigating. I'm also starting to do some optimization, since we're currently only able to run about 10 million instructions every second when all three cores are active. There's a lot of low-hanging fruit, and we should be able to get reasonably decent speeds even with just an interpreter.
Re: 3DS reverse engineering
by on (#239792)
I got the 3DS wifi uploader working and booting the uploaded FIRM file!
Altogether it wasn't too difficult to implement the missing stuff since last post. Apart from two bugs that had delayed things:

I spent almost a whole day on finding a bug related to a misaligned memory access (the bug did exist in nds/dsi version, too, but the 3DS does apparently default to trigger an exeption in such situations).

And then I've spent a whole day on trying to get bloody IPC_SYNC messages working, which shouldn't have been an issue at all - but it didn't work no matter what.
The problem was that the send-value is write-only on 3DS. Unlike as on NDS/DSi (and unlike as what is said on 3dbrew wiki), the 3DS send-value isn't R/W, and does merely return zero when trying to read it!
My code was using 32bit "LDR+SetBit31+STR" to enable IPC IRQs (and thereby unintentionally replaced the send-value by zero). As work-around, I am now using 8bit "LDRB+SetBit7+STRB".

I'll still need to fine-tune the transfer protocol, and perhaps improve the transfer speed, but at least I can now do that stuff via wifi, without needing to plug/unplug SD/MMC stuff any longer : )

It would be also nice to support uploading NDS/DSi and GBA files to 3DS. Are there already homebrew tools that can switch to GBA/NDS/DSi mode (without using the 3DS operating system)?
For now, it would be easier to implement GBA/NDS/DSi as than trying to upload 3DS .code files (which would require to boot the OS, or even write a complete OS clone).

PSI wrote:
I've made some more progress on my own emulator.
Cool! I am still far away from emulating anything myself. I will probably first do some tests on how the hardware is working (there are some things that I wanted to know for years, and now I can finally test them).
Well, and I am a bit afraid of trying to allocate 128Mbytes of MainRAM in no$gba... I am not too sure if my PC can handle that.
Re: 3DS reverse engineering
by on (#239805)
nocash wrote:
profi200 wrote:
The regs are already documented so why copy the official doc from ARM?
The MPCore stuff is already documented? Do you mean elsewhere than in official docs from ARM?

I mean the official documentation.

nocash wrote:
Well, and after all that work, I hoped that SDIO/WPA/WPA2 support in the DSi wifiboot tool would allow hordes of homebrew DSi devr's to test their own code on real hardware - but somehow those hordes of devr's never showed up (the feedback was a bit disappointing: I know of only one person who had downloaded my wifiboot tool - and apparently didn't even got it working).
I am wondering if the feedback on other wifi tools (like FTP for nds/dsi/3ds) is equally rare?

The DSi never caught much interest is why. It's really just a more powerful DS unlike the 3DS which is an entirely new platform (but with backwards compatibility).
Feedback for FTPd was always there but recently it's quiet because most people moved on to the Switch.

nocash wrote:
The homebrew DSi code reached only 400-600 Kbyte/s (the difference between 400 and 600 Kbyte/s depends on the access point). I don't know why it doesn't reach 5-6 Mbyte/s, I think it might be an atheros-hardware issue, or just messy TCP flow in software, not just the DSi CPU being too slow.

One cpu/memory related bottleneck is that the packet body isn't word-aligned (the packet header has an odd amount of halfwords). That's a problem when copyting data from from "packet_buffer" to actual "target_address".
On NDS/DSi, I have solved by using the old NDS DMA registers with 16bit transfer units (which work with halfword aligned SAD/DAD addresses). Does the 3DS support anything similar?

[...]

But a more general memory/cache question: NDS/DSi is having some issues with caches (ARM9 cache not updated when DMA or ARM7 changes memory). Does 3DS have similar issues?
I hope that the ARM11 cores are all sharing the same cache (or otherwise, that they can notify each other of memory changes & automatically update their caches)?
With the CDMA/XDMA being made by ARM, I hope that these DMA's are integrated with the corresponding CPU caches?
On the other hand, I guess nintendo's NDMA isn't aware of CPU caches?
And ARM9 cache isn't aware of ARM11 cache?

Oh, and ARM9 is having DTCM and ITCM. Does ARM11 have that kind of memory, too?

It's probably so slow because it still uses the old propritary interface (? not familiar with libnds code) instead of SDIO and lots of overhead in old, poorly written code. I don't know.

The only DMA controllers that may be able to do unaligned accesses and halfwords are the CoreLink DMA-330 controllers (C/XDMA) which are a bit of a pain since you need an assembler/runtime translation code for them (ARM only provides one for paying customers but at least the instruction encoding is public). And no, there is no coherency at all between CPU and any periphals not part of the CPUs. That feature was added in ARMv8 i think.
CPU caches are separate between CPU clusters. The ARM9 could not access the ARM11 caches even if Nintendo wanted that since it would require a heck of hackjob that would break ARM's specs. The 2/4 ARM11 cores all have their own L1 cache but coherency between them is guaranteed in SMP mode (if you give the CPUs a bit of a helping hand by using ldrex/strex and such). The L2 cache on N3DS is shared by all 4 ARM11 cores.

There are no TCMs at all on the ARM11 side (implementation defined but Nintendo did not include TCMs for ARM11).



nocash wrote:
I would assume that they are loading the GBA ROM-image to Main RAM, and then map the RAM to the GBA's physical ROM-address space. Using vitual MMU addresses for GBA mode would be very unexpected. But if they do, then I promise that I will read all the AXI and AHB docs ; )

The ROM is stored in FCRAM and the remaining is some sort of physical memory mapping stuff. There is actual DS and GBA hardware in there. No emulation. This has not been looked into much at all but the mode switch + turning on the ARM7 was archived. Without the "twlbg" process on ARM11 you can't get DS(i) mode working since it does at least display and sound.



nocash wrote:
...it does look as if 3DS doesn't have any WifiSDIO startup mode for NDMA (I've tried all unknown modes: 06h,07h,0Dh,0Eh, but none worked).

The other option on ARM9 side would be XDMA, currently there seem to be only two known XDMA startup modes (00h and 07h).
Does somebody have a list with more XDMA modes? That would be very useful! : )

The ARM9 is not meant to handle WiFi in 3DS mode so it doesn't have startup modes or IRQs for any of the WiFi/SDIO hardware. The startup modes on 3dbrew are the only known ones.



nocash wrote:
I guess moving wifiboot into Main RAM should work (FIRM's don't seem to be allowed to be loaded to Main RAM; but Main RAM might be slower than preferred).
Or I could try to execute code in VRAM, if that's working and faster? Theoretically FIRM blocks could be loaded into VRAM, so that could be a conflict - but the conflict is already there because of the screen output during wifi transfers).

FCRAM is pretty slow. VRAM behaves exactly like all the others unlike on GBA/DS(i). Code can be executed there and non-word accesses work.



PSI wrote:
Another progress report! [snip]

But what about the other platforms? firm0/1 verification is still broken on Windows and Linux. A working bare metal emu that can emulate ARM9/11 well enough to run the fastboot3DS codebase would be very helpful for my own kernel project (based on that fb3DS code).



nocash wrote:
I spent almost a whole day on finding a bug related to a misaligned memory access (the bug did exist in nds/dsi version, too, but the 3DS does apparently default to trigger an exeption in such situations).

My code was using 32bit "LDR+SetBit31+STR" to enable IPC IRQs (and thereby unintentionally replaced the send-value by zero). As work-around, I am now using 8bit "LDRB+SetBit7+STRB".

It would be also nice to support uploading NDS/DSi and GBA files to 3DS. Are there already homebrew tools that can switch to GBA/NDS/DSi mode (without using the 3DS operating system)?
For now, it would be easier to implement GBA/NDS/DSi as than trying to upload 3DS .code files (which would require to boot the OS, or even write a complete OS clone).

Well, and I am a bit afraid of trying to allocate 128Mbytes of MainRAM in no$gba... I am not too sure if my PC can handle that.

ARM9 should have the old unaligned access behavior where it rotates stuff around. ARM11 can do proper unaligned access depending on the control register config.

Nintendo accesses that reg with ldrb/strb after initialization.

There is no AGB-/TWL_FIRM replacement at all. Trust me it's more complicated than you think (LGCY regs, GPU, sound and more...).
And for 3DS userland there is already a homebrew SDK. Otherwise there is plenty of working bare metal code.

I can't resist to ask but is that a joke? Barely anyone has <4 GiB RAM these days. I have 16 GiB.
Re: 3DS reverse engineering
by on (#239811)
profi200 wrote:
nocash wrote:
Well, and I am a bit afraid of trying to allocate 128Mbytes of MainRAM in no$gba... I am not too sure if my PC can handle that.

I can't resist to ask but is that a joke? Barely anyone has <4 GiB RAM these days. I have 16 GiB.

He appears to still use a PC running Windows 9x.
Re: 3DS reverse engineering
by on (#239812)
nocash wrote:
Cool! I am still far away from emulating anything myself. I will probably first do some tests on how the hardware is working (there are some things that I wanted to know for years, and now I can finally test them).
Well, and I am a bit afraid of trying to allocate 128Mbytes of MainRAM in no$gba... I am not too sure if my PC can handle that.

I've encountered a couple of unknowns already - in particular, some of the poorly defined NDMA startup modes are still used.

It only gets worse with New3DS, as there's an additional 128 MB of FCRAM (256 MB total), as well as two new cores and other features. That being said, I don't think the boot ROMs access FCRAM at all, so you can at least use those for testing.

profi200 wrote:
But what about the other platforms? firm0/1 verification is still broken on Windows and Linux. A working bare metal emu that can emulate ARM9/11 well enough to run the fastboot3DS codebase would be very helpful for my own kernel project (based on that fb3DS code).

Of course I'd like Corgi3DS to be cross-platform, and in theory it should be. In practice, the library I'm using for RSA (libgmp) seems to easily expose various compiler bugs. Someone has made a PR to use polarssl instead which should be more portable, but I haven't had time to look at it (and there's various merge conflicts on it now).

I haven't tested fastboot3DS at all, only NATIVE_FIRM and Luma3DS. Could you give more details on your kernel project?
Re: 3DS reverse engineering
by on (#239814)
tepples wrote:
He appears to still use a PC running Windows 9x.

Yeah, i knew that but i would at least expect 1 or 2 GiB. 98 or XP takes next to nothing on resources.

Btw something this forum really needs is a multi quote function.



PSI wrote:
That being said, I don't think the boot ROMs access FCRAM at all, so you can at least use those for testing.

As long as the bootroms are unlocked (sysprot regs) FCRAM is not accessible at all. 3dbrew may be missing this little detail.

PSI wrote:
Of course I'd like Corgi3DS to be cross-platform, and in theory it should be. In practice, the library I'm using for RSA (libgmp) seems to easily expose various compiler bugs. Someone has made a PR to use polarssl instead which should be more portable, but I haven't had time to look at it (and there's various merge conflicts on it now).

I haven't tested fastboot3DS at all, only NATIVE_FIRM and Luma3DS. Could you give more details on your kernel project?

Meh, i may look into porting the code over to mbedtls (which is the successor of polarssl and has proper hardware acceleration).

I have been working privately on it for a while. It's a cooperative library kernel that's linked directly with the application. Currently there is a bug where it corrupts the console for a moment and i could not figure out what causes it yet. Emulation may help here.
Re: 3DS reverse engineering
by on (#239873)
Cameras: I've dumped the 3DS camera chip IDs. They are 2280h (Aptina MT9V113). So, all three New3DS cameras are having same chip ID as the two DSi cameras. That was one of big unanswered questions that I've been wondering about ever since 4-5 years ago.
But then, I've also had a look at Nintendo.com, and there they are saying that the New3DS has "Improved Cameras" with support for brighter pictures in dark environments. I don't know what's that about, maybe they have just improved the shutter time in software, or the hardware is actually using different camera revisions despite of the same chip IDs.

Eye-tracking: How does that work, and what is it good for?
Is that simply using the internal camera, and running image-recognition software on ARM11 for eye-tracking? Or is there some extra hardware component that spits out eye-tracking coordinates?
Reportedly there is a "IR LED" (not an IR sensor, nor IR camera) next to the internal camera, said to improve eye-tracking, but I don't understand how an IR light source code improve anything... unless the camera were able to receive IR alongsides with the usual RGB/YUV image... and even then, I would have assumed that IR cameras worked best by picking up body temperatures, without needing an external IR light source.
And finally, going by 3dbrew, there is a "parallax barrier" to separate left/right stereoscopic pixels. Does the eye-tracking thing allow to shift the direction of that parallax barrier?

profi200 wrote:
There are no TCMs at all on the ARM11 side (implementation defined but Nintendo did not include TCMs for ARM11).
Good to know! Reminds me of another basic beginners question:
Does 3DS/ARM11 support THUMB2 instruction set?

Oh, and DSi CPU chip did support two NDS-cartridge slots (a prototype relict, the actual mainboards did have only one cart slot).
The 3DS CPU chip seems to have completely ditched that feature (eg. 3DS Port 10000010h seems to be equivalent to SCFG_MC on DSi, but without the extra bits for 2nd slot in bit4-7 and bit15). And there seems to be only one set of "Ntrcard" registers for accessing the cart slot in NDS mode.
But then, there are two sets of "Ctrcard" registers for accessing the cart slot in 3DS mode - what is that good for?

profi200 wrote:
It's probably so slow because it still uses the old propritary interface (? not familiar with libnds code) instead of SDIO and lots of overhead in old, poorly written code. I don't know.
No, libnds probably doesn't support SDIO yet. But for my own wifiboot uploader, I've rev-engineered SDIO and WPA/WPA2 some months ago: viewtopic.php?f=23&t=18065 - The 400-600 Kbyte/s was for SDIO on DSi. I don't know either why it won't get faster (the source code is included in the wifiboot package, just in case somebody wants to try to improve the transfer speed, or port it to libnds).
For SDIO on 3DS, I am only getting 150 Kbyte/s yet (probably because packets are merely polled via 60Hz timer IRQ, that could be fixed by forwarding the actual wifi IRQs from ARM11 to ARM9) (and I should someday enable data caches for improving 3DS memory timings). But I am currently uploading only small .firm files with 20-60 Kbytes, so 150K/s is more than fast enough.

profi200 wrote:
The only DMA controllers that may be able to do unaligned accesses and halfwords are the CoreLink DMA-330 controllers (C/XDMA) which are a bit of a pain since you need an assembler/runtime translation code for them (ARM only provides one for paying customers but at least the instruction encoding is public).
The CDMA/XDMA controllers have their own instruction set??? Though I don't see that when looking at the CDMA/XDMA functions in bootrom.

profi200 wrote:
ARM9 should have the old unaligned access behavior where it rotates stuff around. ARM11 can do proper unaligned access depending on the control register config.
Well, then I could also use non-DMA for fast unaligned memory transfers, on ARM11 side at least. Or, otherwise, it might also work with LDR/STR (or LDMIA/STMIA) on ARM9, when manually shifting the misaligned words; that would be a bit complicated, but probably faster than looping through hundreds of LDRH/STRH opcodes.

profi200 wrote:
Without the "twlbg" process on ARM11 you can't get DS(i) mode working since it does at least display and sound.
Is that just some initialization stuff for preparing the 3DS-to-DS(i) mode switch, or is there code running on ARM11 while in DS(i) mode?
Hmmmm, yeah, mode switching might require some months of research (switching from DSi-to-DS mode wasn't so easy either; it did require several small functions for the different hardware components, nothing really complicated, but it did sum up to get everything working).

profi200 wrote:
FCRAM is pretty slow. VRAM behaves exactly like all the others unlike on GBA/DS(i). Code can be executed there and non-word accesses work.
Yeah, I am running my code in VRAM meanwhile. DSi did support 8bit VRAM-writes, too.

PSI wrote:
I've encountered a couple of unknowns already - in particular, some of the poorly defined NDMA startup modes are still used.
One further mode is mode=12 for NTRCARD, used by bootrom:
Code:
FFFF31AA 0689     lsls    r1,r1,1Ah     ;2Ch shl 24 ;startup=0Ch and bit29=1
Some things that could be more clear on the 3dbrew NDMA page are the difference between "INFIFO" and "INFIFO", and which of the MMC modes is refering to the actually used SD/MMC hardware. And mode 13 and 14 might be something unknown yet.
And I guess XDMA might also support more modes (possibly even SDIO Wifi). But it would require some trial and error testing to find out if any of the XDMA modes responds to this or that hardware events.

PSI wrote:
It only gets worse with New3DS, as there's an additional 128 MB of FCRAM (256 MB total), as well as two new cores and other features. That being said, I don't think the boot ROMs access FCRAM at all, so you can at least use those for testing.
Yup, there I could really get away without FCRAM for now. Or brew up something that allocates only as much RAM as currently used (and re-allocates more if needed).

PSI wrote:
I haven't tested fastboot3DS at all
I haven't tried it yet, too, but I'll test it next some days. I am curious if my wifiboot tool can upload and boot it (and if there are some other useful tools in it (I still need an OTP dumper, which might be in there? and an atheros wifi ROM dumper, which probably doesn't exist yet?)).
As far as I know, fastboot uses the same LCD framebuffer video output as bootrom, so that might be a pretty nice thing to test if you don't have GPU video emulated yet.

profi200 wrote:
I can't resist to ask but is that a joke? Barely anyone has <4 GiB RAM these days. I have 16 GiB.
I think that I have 256Mbyte in my PC. But I am more fond of having written a Color Gameboy emulator on a monochrome VGA monitor : )
Re: 3DS reverse engineering
by on (#239875)
nocash wrote:
Does 3DS/ARM11 support THUMB2 instruction set?

They do not. All ARM11 kernel/process code I've seen thus far only uses ARM mode as well. The ARM9 mainly uses Thumb mode.

nocash wrote:
The CDMA/XDMA controllers have their own instruction set??? Though I don't see that when looking at the CDMA/XDMA functions in bootrom.

Indeed they do. The XDMA functions take a set of parameters and then create the bytecode based upon those parameters.

nocash wrote:
Some things that could be more clear on the 3dbrew NDMA page are the difference between "INFIFO" and "INFIFO", and which of the MMC modes is refering to the actually used SD/MMC hardware. And mode 13 and 14 might be something unknown yet.
And I guess XDMA might also support more modes (possibly even SDIO Wifi). But it would require some trial and error testing to find out if any of the XDMA modes responds to this or that hardware events.

Something I found completely mystifying is that when decrypting the FIRM, Boot9 sets two NDMA channels to mode 15 (eMMC->AES, AES->SHA). I use a hackish method to handle this, but I don't know how exactly these channels are supposed to be triggered.

Boot9 only seems to reset channels 0 and 7 on XDMA (CTRCARD and SHA). I have a feeling that's all the ARM9 supports, unlike the ARM11 which does have all eight channels.
Re: 3DS reverse engineering
by on (#240091)
I have dumped the AR6014 ROM and spent some days on searching differences in the ROM/RAM code for AR6014 vs AR6013 vs AR6002 (good way to get your head spinning). The most striking finding is that - apart from software revisions - there don't seem to be any relevant differences in the underlaying hardware...

hw2/hw4/hw6: Atheros source code exists for three hardware revisions (hw2/hw4/hw6), and I had expected AR6002/AR6013/AR6014 to use that hardware revisions accordingly. But it turned out that they are all using the old "hw2" variant. For example, they are all using the same ADDR_ERROR and TCAM registers.
There are some small differences on how the chips are wired up, especially between AR6002 and AR6013: The I2C EEPROM is wired to different GPIO pins (that originally made me think it were hw2 vs hw4, but actually it's both hw2). The other differences between that two chips are different ROM/RAM sizes, different package, different oscillator(s), and built-in MM3218 in AR6013.
On the other hand, there seem to be no differences between AR6013 and AR6014 (apart from minimal changes to the ROM, which could have been as well patched in the firmware RAM, one wouldn't have needed a new chip for that).

NWM variants 1/4/5: There are those three different variants labelled 1/4/5 in each NWM file...
Type1 is the smallest, and it seems to be working best for compatibility with DSi code (and I guess that it's probably actually intended for that purpose).
Type4 crashed my wifiboot code during the DHCP phase where it did throw an unexpected event number: 1025h (that whould be WMI_ACL_DATA_EVENT going by official source code; though they tend to change and mess up their numbering every once and then). I've changed the wifiboot code to ignore that event, and the upload is now working fine with it, too. (I guess Type4 is just same as Type1, plus some extra functions for use by 3DS titles).
Type5 doesn't work with wifiboot at all, it doesn't even find my access point. The Type5 code contains some ASCII strings saying "MACFilter" and "GameID", so that seems to be some nintendo-specific gaming stuff, probably for Local-Network-Multiplayer games (assuming that 3DS is no longer using the old NDS-wifi hardware for that purpose).

NWM revisions: There are several NWM revisions released with 3DS firmware updates (and a safemode NWM version that should be same most firmwares). I was wondering if they contain different ARM code and/or actual changes to the Xtensa code... so I have written a tool that loads the Xtensa code/data from the safemode NWM files, and then searches the same code/data in other NWM files. As by now I have compared only two files (the safemode thing, and another one extracted from 00000017.app). Unfortunately, there are differences:
Code:
 MainCodeDSi = ERROR   ;Type1 (dsi code?)
 MainCodeMac = ERROR   ;Type5 (3ds multiplayer code?)
 MainCodeAcl = ERROR   ;Type4 (3ds code?)
 DatabaseDat = OK      ;Database
 EepromStubC = OK      ;Eeprom loading stub code
 EepromStubD = OK      ;Eeprom loading stub data
Well, at least the database and eeprom stuff is same. Btw. the eeprom stuff is also almost same as in AR6013 (on AR6104 the code is 4 bytes bigger; the differences seem to be 5 new opcode bytes (and a removed padding byte), for setting a reserved word at index FCh in the host interest area to 00000003h).
And the other stuff... 3dbrew title list is listing 11 NWM versions (plus 3 safemode NWM versions), and if Type1/4/5 are changed in each version... then that would be up to 42 different code blocks. Hmmm, rev-engineering the exact differences in 42 versions wouldn't be so much fun.

Does somebody have a collection of those NWM files? Best as raw .code files (=extracted from the encrypted/compressed .app files). I could use my NWM comparision tool to check if there are at least some versions containing the same Xtensa code in them.

And some other news... the wifiboot code is getting better and hopefully ready for release soon. The SDIO IRQ is now forwarded from ARM11 to ARM9... that has raised the transfer speed to more than 300Kbyte/s (and I still have some ideas that should get it yet a bit faster). And I've finally added the feature for updating the console's RTC from PC's local time, so the console won't be stuck on 00:00:00 1st January 2000 after each battery removal.
Re: 3DS reverse engineering
by on (#240094)
PSI wrote:
Indeed they do. The XDMA functions take a set of parameters and then create the bytecode based upon those parameters.
Oops, okay, I'll need to look closer (I had looked only for "pre-compiled" code blocks, not for on-the-fly generated code).
Apropos: bytecode. ARM11 could also support "Jazelle" bytecode (additionally to ARM/THUMB/THUMB2). I forgot to ask if 3DS is supporting that Jazelle stuff... does it?

PSI wrote:
Something I found completely mystifying is that when decrypting the FIRM, Boot9 sets two NDMA channels to mode 15 (eMMC->AES, AES->SHA). I use a hackish method to handle this, but I don't know how exactly these channels are supposed to be triggered.

Ah, yes, looks as if they are both running in parallel with the same startup mode. To some level that might work if AES is so fast that AES->SHA can be started immediately after eMMC->AES. But that would work only if some priority/ordering stuff would ensure eMMC->AES to be executed first, but the bootrom code is doing it excactly the other way around (starting AES->SHA before eMMC->AES (unless I've missed something that might be manually transferring the first block elsewhere)).

How about this: Bit0-9 in NDMAxCNT registers were unused on DSi. But on 3DS, Bit0-4 are R/W (bit5-9 seem to be always 0). The bootrom is using bit3 and bit4 as so:
Code:
eMMC-->AES with startup=0Fh and bit3=1
AES-->SHA with startup=0Fh and bit4=1
I guess that explains how to distinguish between the two channels with same startup mode. I don't know what the bits are doing exactly though. Maybe some extra startup-condition flags? Or a whole set of further startup modes? Possibly used only when bit24-27 are set to 0Fh? Or whatever generic priority/order settings?

With some luck, there might be also a SDIO Wifi startup mode hidden in bit0-4, for use with my ARM9 wifi code : )
Re: 3DS reverse engineering
by on (#240120)
re: NDMA startup bits

probably, yeah. I guess this mechanism also allows to easily implement DSi compatibility (by simply disabling/masking out the extra bits). as in DSi mode, neither SD/MMC nor AES would be mapped to the ARM9.
Re: 3DS reverse engineering
by on (#240700)
Released wifiboot v2.6 and no$gba v2.9e
http://problemkaputt.de/wifiboot.htm
http://problemkaputt.de/gba.htm
The main news is allowing to upload 3DS .firm files from no$gba utility menu to 3DS consoles.

That is my first 3DS program : )
And it's even a useful one... at least for people whom are coding .firm files.
Which is probably meaning useful to 3-5 people, but anyways.

I've posted that in the wifi thread, too. See there: viewtopic.php?f=23&t=18065&p=240698 for release notes, and some new extra details on the 3DS (and DSi) wifi firmwares.

fastboot
Uploading fastboot via wifi seems to work fine. Maybe that can be useful for testing new fastboot versions.
The first & last fastboot options seem to hang though (continue booting & credits).
What is continue booting supposed to do? Continue where from, and where to?
In the fastboot filemenu I can see lots of eMMC folders, but don't know if there are any bootable files in any of the folders. Is it possible to boot the GBA/DSi firms? Or would that require further code (for selecting a GBA rom-image, or DSiware title before startingt the gba/nds firm).
It would be nice to be able to boot the 3DS native firm, either from firm1 partition, or from the firm folder (or is continue booting supposed to do that)?

profi200 wrote:
Pressing the power button will do nothing but trigger the MCU interrupt notifying the running OS. When you hold it for at least 3 seconds it will force poweroff after another ~7 seconds.
Yes, seems to work like that. But holding 3 seconds is a bit risky in practice (if you hold only 2.99 seconds then you can wait until your face turns blue and then start all over again), so it's better to try to hold 5 seconds.
I've meanwhile also added code for reading the button state via I2C bus from MCU, allow to power-off by tapping the power button. It's working - almost.

The nasty thing is that one must tap for at least 0.25 seconds or so, and, there seems to be a delayed power-led fade-out effect. It's just enough time that you can turn away without ever knowing if you have really successfully switched off the console, unless you take the time to control the result 1-2 seconds later.
I am normally not the kind of person who is returning home several times to double-check if the lights were really turned off. But this nasty nag-nag-nagging nag-nag-nintendo power button is driving me crazy : [ ; /

Reading between the lines on the I2C register page on 3dbrew, it sounds as if it were possible to dump & disassemble the MCU firmware? Is that right? And is it also possible to install a patched MCU firmware?

If yes, then one could adjust the power button tapping delay. I guess that would be the only way to get the undelayed button state (when displaying the MCU registers, there seem to be no bits getting toggled when pressing the button, unless it's pressed & held for about 0.25s).
Re: 3DS reverse engineering
by on (#240747)
Regarding NDMA startup modes: I did a few tests and and these new bits seem to be totally different startup modes probably primarily for device<-->device transfers. Initially i thought maybe they map 1:1 to the regular startup modes + the immediate bit but hey are different. That's all i know.

nocash wrote:
Released wifiboot v2.6 and no$gba v2.9e
http://problemkaputt.de/wifiboot.htm
http://problemkaputt.de/gba.htm
The main news is allowing to upload 3DS .firm files from no$gba utility menu to 3DS consoles.

That's nice. But my primary problem with the code of wifiboot is it's barely useful for the remaining devs working with bare metal since it's 100% asm which is comparable with reverse engineering code (except the symbols are known here) and it's tied to your codebase. So if i wanted to code a bare metal homebrew today that uses WiFi i would look at your code and immediately forget the idea. No offense but that's probably what many will do.


nocash wrote:
fastboot
Uploading fastboot via wifi seems to work fine. Maybe that can be useful for testing new fastboot versions.
The first & last fastboot options seem to hang though (continue booting & credits).
What is continue booting supposed to do? Continue where from, and where to?
In the fastboot filemenu I can see lots of eMMC folders, but don't know if there are any bootable files in any of the folders. Is it possible to boot the GBA/DSi firms? Or would that require further code (for selecting a GBA rom-image, or DSiware title before startingt the gba/nds firm).
It would be nice to be able to boot the 3DS native firm, either from firm1 partition, or from the firm folder (or is continue booting supposed to do that)?

It should not hang at all. Since it's working with every other known chainloader i'ts likely a bug on your end. Do you properly disable and flush caches before jumping to the FIRM entrypoints? Especially the ARM11 needs this since it apparently still has icache hits even after the icache is disabled(?). At least it behaves strangely if you don't do proper cache maintenance which i have seen many times in the past.

Continue is exactly what it says. If the bootloader got interrupted by holding HOME to show the menu it will continue booting the boot slot it would have booted without holding HOME. It will boot nothing by default. You need to configure the boot slots. And it can't boot anything but FIRM files (it can also boot from the second FIRM partition (firm1) but his is not normally enabled to protect noobs (hint: A special key combo on the credits screen)). As said GBA and DS(i) mode has not been looked into much and there is no known open source implementation of AGB/TWL_FIRM.

nocash wrote:
Yes, seems to work like that. But holding 3 seconds is a bit risky in practice (if you hold only 2.99 seconds then you can wait until your face turns blue and then start all over again), so it's better to try to hold 5 seconds.
I've meanwhile also added code for reading the button state via I2C bus from MCU, allow to power-off by tapping the power button. It's working - almost.

I don't understand your problem? Hold the button, slowly count up to 3 and done? Works 95% here.

nocash wrote:
The nasty thing is that one must tap for at least 0.25 seconds or so, and, there seems to be a delayed power-led fade-out effect. It's just enough time that you can turn away without ever knowing if you have really successfully switched off the console, unless you take the time to control the result 1-2 seconds later.
I am normally not the kind of person who is returning home several times to double-check if the lights were really turned off. But this nasty nag-nag-nagging nag-nag-nintendo power button is driving me crazy : [ ; /

???? For real i don't get it.

nocash wrote:
Reading between the lines on the I2C register page on 3dbrew, it sounds as if it were possible to dump & disassemble the MCU firmware? Is that right? And is it also possible to install a patched MCU firmware?

If yes, then one could adjust the power button tapping delay. I guess that would be the only way to get the undelayed button state (when displaying the MCU registers, there seem to be no bits getting toggled when pressing the button, unless it's pressed & held for about 0.25s).

Disclaimer: I'm not responsible if you permanently brick your 3DS. Yes IT IS THAT DANGEROUS! There are no checks whatsoever and if the firmware is bricked to the point the firmware upload fails there is no known way to recover it even externally.

MCU firmware images can be found in the MCU system module code (iirc). Upload is writing a magic value immediately followed by the entire image. I have never done it and you should neither. There is not even an emulator to test the MCU firmware. All the propritary ones are for different MCUs and not this apparently custom design (which is based on some other MCU but it's not the same!). Architecture is RL78.
Re: 3DS reverse engineering
by on (#240824)
Fastboot credits hangs, but it recovers when pressing B button. I assume that it is displaying something on the top screen during the hang? (which could be seen only when having working top screen backlight connector).
Continue booting just hangs. I didn't press HOME at all, but yes, I haven't selected anything, so if it is supposed to boot nothing by default, then the hang might just be the intended effect. For the caches, I am doing this on ARM9 and ARM11 before booting the uploaded .firm file:
Code:
for3ds_flushdisable_code_cache:
 mov  r0,p15,0,c1,c0,0                  ;\
 bic  r0,1 shl 12  ;code cache          ;
 mov  p15,0,c1,c0,0,r0                  ;/
 mov  r0,0                                                      ;\
 mov  p15,0,c7,c5,0,r0 ;=0 ;Invalidate Entire Instruction Cache ;/
 bx   lr
I hope that is properly disabling the 3ds code caches? For the data caches, I didn't even try to enable them yet since that would require setting up PU on ARM9, and MMU on ARM11.

NDMA registers SAD/DAD/TCNT/WCNT are having a weird effect: They "fail" when doing a R/W test on the I/O area (making it appear as if the registers were read-only, even when the DMA was stopped, but that can't be true).
That odd effect is caused by NDMAGNT.bit0=1, but it works as normal (=as on DSi) when clearing that bit. The bit affects "SAD/DAD/TCNT/WCNT register reading (0=Return written value, 1=Return current value)".
The written values are the "start/reload" values that remain unchanged during/after transfer. The current values are internal registers that get (re-)loaded at transfer start, and increase/decrease during transfer.

Source code I am familar with people saying that I am a non-free coder when not releasing my source code, this was the first time that somebody had objections when I did release the sources. The difference between bare metal and 100% asm is also new to me. You got me pretty shaken up emotionally yesterday ; )
With my source code with labels & gbatek dsi wifi specs, it might take 1-2 weeks to implement wifi. Without that, I don't know, it took me about 3 years to figure out how to use the sdio stuff, but maybe the workforce of the 3ds community could do it in less time.
Anyways - if there are really those remaining devs that want to use wifi - I could answer questions, and I can also add some comments about the source code structure...
The 3DS related stuff is marked as "target_3ds" (which should be a non-issue), the SDIO stuff is marked "with_dsi_wifi" (that's also pretty simple when knowing how to use which BMI and WMI commands; but it's getting a bit more complex because WPA/WPA2 EAPOL packets must be handled manually, but that's all documented in gbatek).
The source is organized in chapters with ;: markers (eg. load wificore.a22 in No$gba -> Utility -> Edit File, then press F6+C to see what I mean. If they really want to do C coding then they could use existing code for TCP/UDP/ARP/DHCP stuff (eg. use the dswifi arm9 code, or something else), and it appears to be common to use polarssl for MD5/SHA1/AES in dsi/3ds in scene, ie. they could just ignore more than 80% of my asm code. But my best recommendation would be to port their codebase to asm. NDS wifi is marked as "with_nds_wifi" one could omit that on 3DS (and DSi).

Wifiboot binary: Did somebody test the wifiboot.firm file on 3DS? It would be interesting if it's working over there, too, especially the WPA/WPA2 part (in the 3DS version, I've currently tested WEP only).
Of course, feedback on DSi wifiboot would be also nice, ie. feedback if it's working with other access points (other than the ones that I had used at home).

Power button: Part of the problem is that it's not just the LED refusing to go off immediatly, it's also the whole screen keeping to display a picture a while after power off. As workaround, I'll clear the framebuffer (or better disable backlights) before power-off, so the user gets some sense that the button was tapped long enough.
Ah, I just noticed that fastboot is using that trick, too. So I guess somebody there must have been struggling with the unresponsive button, too.
Hmmm, for a reboot without power-off, I should probably go into using the HOME button; assuming that it is sorts of intended for such purposes (*). The person who had donated the 3DS said the HOME button was a bit worn out... but it seems to be still working (in a more responsive way than the power button).
(*) as far as I remeber it does bring up a japanese message box (so I am still scared about fiddling with that button).

Architecture is RL78. Thanks, that's very useful to know! Alright, I've written a disassembler for it yesterday, and found an old message from somebody mentioning where to find the code block in the MCU .app files. The disassembly looks okay... except, there seem to be 1000h bytes missing in the middle of the code block (or is it two blocks?), the reset vector is fine, but the other exception vectors point to 4Axxh (whilst the actual handlers show up at 3Axxh).
The "custom design" thing is for the SFR hardware registers & things like I2C and GPIO bits? Is that part of the hardware already rev-engineered & documented on 3dbrew, or elsewhere?
EDIT: https://3dbrew.org/wiki/Hardware has two broken links for "RL78 ISA" and "RL78 hardware manual (registers)" are that docs still available somewhere?
If I can brick the console via MCU writes, that might be a nice way to get rid of it ; ) especially as the upper backlight is already broken anyways.

Btw. if somebody wants to donate a 3DS-console (or New3DS.XL-mainboard with intact top-screen connector): I would be very interested in both (two or three games would be also nice to get an idea about what the console is good for).
Doing rev-engineering with lower-screen-only is possible - but the viewing angle is terrible (I have put the console onto a cardboard box on the floor so I can see something; but with working top-screen I could just have it located in front of me on the table (and it might also become easier to reach for the power button that way)).
Re: 3DS reverse engineering
by on (#240825)
nocash wrote:
Fastboot credits hangs, but it recovers when pressing B button. I assume that it is displaying something on the top screen during the hang? (which could be seen only when having working top screen backlight connector).
Continue booting just hangs. I didn't press HOME at all, but yes, I haven't selected anything, so if it is supposed to boot nothing by default, then the hang might just be the intended effect. For the caches, I am doing this on ARM9 and ARM11 before booting the uploaded .firm file:
Code:
for3ds_flushdisable_code_cache:
 mov  r0,p15,0,c1,c0,0                  ;\
 bic  r0,1 shl 12  ;code cache          ;
 mov  p15,0,c1,c0,0,r0                  ;/
 mov  r0,0                                                      ;\
 mov  p15,0,c7,c5,0,r0 ;=0 ;Invalidate Entire Instruction Cache ;/
 bx   lr
I hope that is properly disabling the 3ds code caches? For the data caches, I didn't even try to enable them yet since that would require setting up PU on ARM9, and MMU on ARM11.

Yeah, duh when the topscreen is broken of course it appears as if it would hang but it's displaying on the topscreen. Continue should display an error (on the topscreen) if there is no slot configured.

On ARM11 there is a bit more to do than on ARM9 because the pipeline and stuff changed: https://github.com/derrekr/fastboot3DS/ ... art.s#L226
At the beginning of that file i embedded a bit of documentation for the control register bits.

nocash wrote:
NDMA registers SAD/DAD/TCNT/WCNT are having a weird effect: They "fail" when doing a R/W test on the I/O area (making it appear as if the registers were read-only, even when the DMA was stopped, but that can't be true).
That odd effect is caused by NDMAGNT.bit0=1, but it works as normal (=as on DSi) when clearing that bit. The bit affects "SAD/DAD/TCNT/WCNT register reading (0=Return written value, 1=Return current value)".
The written values are the "start/reload" values that remain unchanged during/after transfer. The current values are internal registers that get (re-)loaded at transfer start, and increase/decrease during transfer.

Not tested beyond what i said. The regs seem to be a bit buggy anyway. At least the CNT reg doesn't always keep the exact bits written for some reason. But i'm not sure since it was years ago i noticed this.

nocash wrote:
Source code I am familar with people saying that I am a non-free coder when not releasing my source code, this was the first time that somebody had objections when I did release the sources. The difference between bare metal and 100% asm is also new to me. You got me pretty shaken up emotionally yesterday ; )
With my source code with labels & gbatek dsi wifi specs, it might take 1-2 weeks to implement wifi. Without that, I don't know, it took me about 3 years to figure out how to use the sdio stuff, but maybe the workforce of the 3ds community could do it in less time.
Anyways - if there are really those remaining devs that want to use wifi - I could answer questions, and I can also add some comments about the source code structure...
The 3DS related stuff is marked as "target_3ds" (which should be a non-issue), the SDIO stuff is marked "with_dsi_wifi" (that's also pretty simple when knowing how to use which BMI and WMI commands; but it's getting a bit more complex because WPA/WPA2 EAPOL packets must be handled manually, but that's all documented in gbatek).
The source is organized in chapters with ;: markers (eg. load wificore.a22 in No$gba -> Utility -> Edit File, then press F6+C to see what I mean. If they really want to do C coding then they could use existing code for TCP/UDP/ARP/DHCP stuff (eg. use the dswifi arm9 code, or something else), and it appears to be common to use polarssl for MD5/SHA1/AES in dsi/3ds in scene, ie. they could just ignore more than 80% of my asm code. But my best recommendation would be to port their codebase to asm. NDS wifi is marked as "with_nds_wifi" one could omit that on 3DS (and DSi).

I'm not saying you should not release your source code. Rather the opposite. The only problem is it's not compatible with any other existing code which forces us to basically "reverse engineer" your code and write our own version. And bare metal doesn't mean writing everything in asm :wink: I would go as far as saying 95% of bare metal code written after 2000 is C and a little bit of C++. You can see we have only written small parts in asm in fastboot3DS because these parts are better handled that way than a higher level language.

polarssl is not needed. We have a full implementation of all the crypto hardware in https://github.com/derrekr/fastboot3DS/ ... e/crypto.c
For AES there is even DMA support. Software AES and SHA1/256 i tried many years ago and i can tell you you don't want that (it's slower than a slug). Also on a side note SHA combined with NDMA takes twice as long as with CPU for some reason. Possibly SHA has a bug slowing down DMA.

nocash wrote:
Wifiboot binary: Did somebody test the wifiboot.firm file on 3DS? It would be interesting if it's working over there, too, especially the WPA/WPA2 part (in the 3DS version, I've currently tested WEP only).
Of course, feedback on DSi wifiboot would be also nice, ie. feedback if it's working with other access points (other than the ones that I had used at home).

Not tried yet. Personally i wanted to make myself a hardware assisted FIRM uploader/debugger for a while using the SPI interface of the gamecard slot. That thing can go up to 16 MHz with the new "CARDSPI" interface and even supports "quad SPI" so it's plenty fast. CARDSPI has been fully figured out by the way and 3dbrew has been updated with all details including a little bug.

nocash wrote:
Power button: Part of the problem is that it's not just the LED refusing to go off immediatly, it's also the whole screen keeping to display a picture a while after power off. As workaround, I'll clear the framebuffer (or better disable backlights) before power-off, so the user gets some sense that the button was tapped long enough.
Ah, I just noticed that fastboot is using that trick, too. So I guess somebody there must have been struggling with the unresponsive button, too.
Hmmm, for a reboot without power-off, I should probably go into using the HOME button; assuming that it is sorts of intended for such purposes (*). The person who had donated the 3DS said the HOME button was a bit worn out... but it seems to be still working (in a more responsive way than the power button).
(*) as far as I remeber it does bring up a japanese message box (so I am still scared about fiddling with that button).

We always clear all framebuffers before turning on the screens. On poweroff we first turn off the screens because it will shutdown noticeably faster that way. The delay is there to make the screens go black before they turn off because otherwise they seem to show a bit of garbage until all pixels have reset themselfes. This is not a big deal in my opinion but derrek wanted that. It's not visible normally anyway until you shine a flashlight on the screens.

nocash wrote:
Architecture is RL78. Thanks, that's very useful to know! Alright, I've written a disassembler for it yesterday, and found an old message from somebody mentioning where to find the code block in the MCU .app files. The disassembly looks okay... except, there seem to be 1000h bytes missing in the middle of the code block (or is it two blocks?), the reset vector is fine, but the other exception vectors point to 4Axxh (whilst the actual handlers show up at 3Axxh).
The "custom design" thing is for the SFR hardware registers & things like I2C and GPIO bits? Is that part of the hardware already rev-engineered & documented on 3dbrew, or elsewhere?
EDIT: https://3dbrew.org/wiki/Hardware has two broken links for "RL78ISA" and "RL78 hardware manual (registers)" are that docs still available somewhere?
If I can brick the console via MCU writes, that might be a nice way to get rid of it ; ) especially as the upper backlight is already broken anyways.

Btw. if somebody wants to donate a 3DS-console (or New3DS.XL-mainboard with intact top-screen connector): I would be very interested in both (two or three games would be also nice to get an idea about what the console is good for).
Doing rev-engineering with lower-screen-only is possible - but the viewing angle is terrible (I have put the console onto a cardboard box on the floor so I can see something; but with working top-screen I could just have it located in front of me on the table (and it might also become easier to reach for the power button that way)).

There are some different/new hardware blocks/registers from what i heard but i never touched MCU reverse engineering. Only few ever tried to reverse engineer the MCU firmware and these people may still have these pdfs. I could not find them on a quick search.
Bricking to have a reason to throw away electronics. What a waste :roll:
Re: 3DS reverse engineering
by on (#240829)
If somebody buys me a new new3dsXL mainboard, then you can get the old one with the broken backlight connector and protect it from getting wasted.
Re: 3DS reverse engineering
by on (#240921)
profi200 wrote:
The [NDMA] regs seem to be a bit buggy anyway. At least the CNT reg doesn't always keep the exact bits written for some reason. But i'm not sure since it was years ago i noticed this.
One reason might be that NDMA registers are read-only during transfers (probably including most or all bits in NDMAxCNT register, except bit31). If there are other situations where NDMAxCNT doesn't contain the expected value... would be interesting to know when that happens (if you happen to come across the effect again).

Yes, using hardware for AES/SHA1 should work on 3DS, and it might save 2-3Kbyte code, but it's just needed for the EAPOL handshake so there's little performance gain. MD5 isn't possible via 3DS hardware (as far as I know), if you want to run wifi on ARM11 then you might also dig out your software libraries before tunneling the AES key wrap to the ARM9 hardware. Anyways, first step would be WEP or Open network, so EAPOL doesn't really matter for getting started.

profi200 wrote:
On poweroff we first turn off the screens because it will shutdown noticeably faster that way.
I am not really noticing that... the LED afterglow in fastboot looks about same as in wifiboot (but of course, the screen goes black earlier if you make it black; which is what I wanted to do in next wifiboot update, too).


RL78 SFR's: There are loads of "RL78 hardware manuals", the SFR register list is hidden in the "CPU Architecture, Processor Registers" chapter. The first hardware manual that I came across was "RL78/G13", so I spent a whole night on extracting the register list, converting it to ascii text, and then making the disassembler to display the SFR register descriptions automatically for each opcode.
The result looks more or less correct... but there are some differences: There can be 16 ports (0..15), but RL78/G13 doesn't have all of the corresponding registers defined (and 3DS uses some of the missing ones). And worse, there are registers at FFF3Ch, FFF9Fh, FFFBEh, FFFC0h, FFFC4h, F0017h, F00C0h, F00C4h, F00F2h, F0501h, F0510h-F0512h, F0538h, F0540h-F0542h, F0550h-F0554h, which don't match with RL78/G13 at all.

Searching for FFF3Ch, there are datasheets with various conflicting meanings:
Code:
  FFF3CH Multiplication data register B(L)
  FFF3CH Serial communication pin select register 0
  FFF3CH D/A conversion value setting register
  FFF3CH Input switch control register
Some datasheets have various registers moved to completely different addresses, looks as if I was lucky with RL78/G13, as it does appear to match up (roughly) with 3DS.
The 78K0R/K C3-L E3-L datasheet looks even more promising, as it's containing most of the unknown SFRs (and, btw, has different meaning for FFF90h, and lacks Timers 10-17 and lacks IICA 1 (aka 2nd I2C registers), and has ADPC moved to F0017h, which does all seem to match up with 3DS MCU firmware (it does have a lot of extra registers at F0540h and up, that part doesn't seem to exist on 3DS, fortunately)).

The 3DS special area is a F0501h..F0554h, which doesn't seem to match any datasheets. Of those, F0540h-F0554h appear to be simply the missing 2nd I2C port registers; and the other ones might be also standard registers moved that addresses...?

Comparing all those SFR lists & searching for subtle differences can be terrorizing. But I hope that I do now known the most probable meanings of most SFRs, so I can start with the actual MCU code disassembly.
Re: 3DS reverse engineering
by on (#240931)
Regarding waste: Search on ebay for a cheap, bricked 3DS where the description says the blue power LED shortly blinks. This is almost certainly a "arm9loaderhax/boot9sstrap brick" where it can't find the boot.firm on the SD card powering off as a result. There are many ignorant/uninformed people who let others mod their 3DS or they bought "pre-loaded/hacked" ones.


nocash wrote:
profi200 wrote:
The [NDMA] regs seem to be a bit buggy anyway. At least the CNT reg doesn't always keep the exact bits written for some reason. But i'm not sure since it was years ago i noticed this.
One reason might be that NDMA registers are read-only during transfers (probably including most or all bits in NDMAxCNT register, except bit31). If there are other situations where NDMAxCNT doesn't contain the expected value... would be interesting to know when that happens (if you happen to come across the effect again).

Yes, using hardware for AES/SHA1 should work on 3DS, and it might save 2-3Kbyte code, but it's just needed for the EAPOL handshake so there's little performance gain. MD5 isn't possible via 3DS hardware (as far as I know), if you want to run wifi on ARM11 then you might also dig out your software libraries before tunneling the AES key wrap to the ARM9 hardware. Anyways, first step would be WEP or Open network, so EAPOL doesn't really matter for getting started.

I would still use the AES engine even if you only need to use it once. It's much faster than software AES and not much harder to use.

nocash wrote:
profi200 wrote:
On poweroff we first turn off the screens because it will shutdown noticeably faster that way.
I am not really noticing that... the LED afterglow in fastboot looks about same as in wifiboot (but of course, the screen goes black earlier if you make it black; which is what I wanted to do in next wifiboot update, too).

You are not seeing this because there is a delay in the poweroff function as said. Trust me, powering off the screens and backlight speeds up shutdown a lot.


Regarding wifiboot: I tried it once and it was connecting fine it seems. Have not tried uploading anything (this is a bit annoying since i have to run No$GBA through wine). How is it even getting the AP SSID, security and key? NVRAM is separate from the WiFi slots configured in 3DS mode as far as i know. It can only be configured through the DS settings.

You are setting the brightness of the screens quite high. I would go much lower. It will be fine in practice. Also it triggers the famous screen init bug where one or both screens glitch out or show a blackscreen instead of the framebuffer. A few ones even shutdown. On my N3DS XL it's always the topscreen which doesn't quite want to work. Theoretically all 2/3DS models are affected but in practice it's almost always New 3DS consoles having this issue and even more so N3DS consoles with one or 2 IPS panels like mine (mine has an IPS topscreen). We still have not figured out why this is happening but 2 workarounds helped a lot preventing this: Directly after writing to the MCU reg for turning on LCDs and backlight wait 3 ms not doing anything. And the second thing that helps is not spamming the MCU with reg reads or writes (for example polling for the power/HOME button). Use IRQs instead.

edit:
I tried now to upload a firm file and it's hanging no matter what i do. No$GBA finds the right IP but that's about it. The entire thing hangs and i have to close it in the task manager. The 3DS side seems to hang aswell but the power button still works. Same with dslink except the PC side closes gracefully as soon as i poweroff the 3DS.

It seems connecting to the AP also fails after a failed upload attempt. Booting to HOME menu once fixes it (probably because nwm is reuploading the firmware blob?).
Re: 3DS reverse engineering
by on (#240959)
profi200 wrote:
I tried now to upload a firm file and it's hanging no matter what i do. No$GBA finds the right IP but that's about it. The entire thing hangs and i have to close it in the task manager.
Might be a network problem, or a problem with the .firm file.
Did you try uploading the wifiboot.firm file? So wifiboot will simply reboot itself. That's tested many times, and should work.
Does the progress bar in no$gba upload box show any progress?

With the IP shown in upload box it's apparently almost fully working (ie. connecting to access point & sending the UDP messages), and it's only the last step with the TCP messages that doesn't work. The only reason I could think of is that UDP is sent as broadcast from PC to 3DS, whilst TCP is sent directly to the local IP of the 3DS. Maybe your router/network/access point is somehow delivering broadcast messages only?

profi200 wrote:
Same with dslink except the PC side closes gracefully as soon as i poweroff the 3DS.
Dslink can't upload .firm files... I assume you were using it for uploading .nds/.dsi files to the 3DS in nds/dsi mode?
If that is having the same problem then it's apparently not a bug in my wifiboot/3ds code. At least if dslink is tested & working for other 3DS users.
Btw. there is also a "3dslink" for .3dsx files. I think that's using the 3DS OS function for wifi, so that would be using completely different code. If that doesn't work either, then it's definetly a problem with your network, not with the 3ds software.

profi200 wrote:
It seems connecting to the AP also fails after a failed upload attempt. Booting to HOME menu once fixes it (probably because nwm is reuploading the firmware blob?).
What is a HOME menu? The 3DS equivalent for DSi Launcher? Well, yeah, I guess so, I've just never seen that menu (except in japanese gui, and I guess it's called differently there).
Anyways - I don't know what is going wrong.
If you did power-off after failed upload, then wifiboot should re-upload the wifi firmware at next power-on, and everything should work fine.
If you know a way to reset without power-off after failed upload, then wifiboot would merely restart the wifi-firmware (without re-uploading it), and that should work fine, too.

profi200 wrote:
run No$GBA through wine
The protocol is (almost) same as dslink. If you want to, you could use dslink (host) source code, and change the two UDP strings, and replace the TCP transfer blocks by the FIRM header & FIRM blocks (might be possible in 5-10 minutes). The protocol's are described here: http://problemkaputt.de/gbatek.htm#dswi ... otprotocol

profi200 wrote:
How is it even getting the AP SSID, security and key?
The access point data is stored in Wifi-FLASH, same as on DSi, http://problemkaputt.de/gbatek.htm#dsfi ... cesspoints
Or is 3DS storing that data elsewhere? Even then, it would probably copy it to Wifi-FLASH for DSi compatibility.

profi200 wrote:
You are setting the brightness of the screens quite high. I would go much lower.
It should use the default brightness as in bootrom blue screen. But now that you mention it, if I would have the screens in front of my eyes, then I would probably prefer a lower setting, too. Hint: Put it on a cardboard box on the floor, then the viewing angle & backlight are nice : )
Or tweak the "arm11_lcd_set_reg_240h_level" function in lcd3ds.a22 to use a smaller value in "r1". The incoming "r1" value is calculated based on GPU register 244h, and then passed to GPU register 240h (as done in bootrom). I don't really understand why the bootrom is doing that... but I assume that one (or both) of that registers are backlight or brightness related?

profi200 wrote:
Also it triggers the famous screen init bug where one or both screens glitch out or show a blackscreen
I've never experienced that on my New3DS. But... there is a test screen pattern in the "arm11_fill_to_mem_words" function in lcd3ds.a22, that might look like a glitch on the top screen (if you have working top screen backlights).

If you should want to edit wifiboot source code: I am afraid that it works only if you store the source files in no$gba's "stuff" sub-directory. Then edit lcd3ds.a22 or whatever. Then use Utility/AssembleFile in no$gba for the main file (wifiboot.a22).
Re: 3DS reverse engineering
by on (#240961)
nocash wrote:
profi200 wrote:
I tried now to upload a firm file and it's hanging no matter what i do. No$GBA finds the right IP but that's about it. The entire thing hangs and i have to close it in the task manager.
Might be a network problem, or a problem with the .firm file.
Did you try uploading the wifiboot.firm file? So wifiboot will simply reboot itself. That's tested many times, and should work.
Does the progress bar in no$gba upload box show any progress?

It's not a network problem. I heard from others they have the exact same problem. I tried a freshly compiled fastboot FIRM file for this and i'm 100% sure that one is not corrupt since it boots fine from the SD card. Sending wifiboot.FIRM itself is also failing. With sending wifiboot itself it goes as far as showing reading FIRM sections on the 3DS side but hangs at 0%. No$GBA also hangs at 0%.

nocash wrote:
With the IP shown in upload box it's apparently almost fully working (ie. connecting to access point & sending the UDP messages), and it's only the last step with the TCP messages that doesn't work. The only reason I could think of is that UDP is sent as broadcast from PC to 3DS, whilst TCP is sent directly to the local IP of the 3DS. Maybe your router/network/access point is somehow delivering broadcast messages only?

Everything else does work fine. Just not wifiboot.

nocash wrote:
profi200 wrote:
Same with dslink except the PC side closes gracefully as soon as i poweroff the 3DS.
Dslink can't upload .firm files... I assume you were using it for uploading .nds/.dsi files to the 3DS in nds/dsi mode?
If that is having the same problem then it's apparently not a bug in my wifiboot/3ds code. At least if dslink is tested & working for other 3DS users.
Btw. there is also a "3dslink" for .3dsx files. I think that's using the 3DS OS function for wifi, so that would be using completely different code. If that doesn't work either, then it's definetly a problem with your network, not with the 3ds software.

I gave dslink a shot since your docs don't mention dslink will not work for FIRM files but knowing it may not work. 3dslink and everything else made for 3DS userland works just fine with the minor annoyance of connection problems (everyone has these and it's caused by Nintendos buggy socket implementation).

nocash wrote:
profi200 wrote:
It seems connecting to the AP also fails after a failed upload attempt. Booting to HOME menu once fixes it (probably because nwm is reuploading the firmware blob?).
What is a HOME menu? The 3DS equivalent for DSi Launcher? Well, yeah, I guess so, I've just never seen that menu (except in japanese gui, and I guess it's called differently there).
Anyways - I don't know what is going wrong.
If you did power-off after failed upload, then wifiboot should re-upload the wifi firmware at next power-on, and everything should work fine.
If you know a way to reset without power-off after failed upload, then wifiboot would merely restart the wifi-firmware (without re-uploading it), and that should work fine, too.

What you are seeing (and where you can start DS/3DS games) if you boot the regular firmware or rather OS since that's what it really is.
I checked again and this seems to be rather some sort of timeout. Booting quickly into HOS (horizon OS) and back into wifiboot makes the connection fail again but after a connection test in HOS it also goes away (and this connection test connects unusually fast to the AP aswell and succeeds).
Also of note is when it fails to connect it prints out some kind of hexdump and that's it.

nocash wrote:
profi200 wrote:
How is it even getting the AP SSID, security and key?
The access point data is stored in Wifi-FLASH, same as on DSi, http://problemkaputt.de/gbatek.htm#dsfi ... cesspoints
Or is 3DS storing that data elsewhere? Even then, it would probably copy it to Wifi-FLASH for DSi compatibility.

I thought that is stored somewhere else than NVRAM.

nocash wrote:
profi200 wrote:
Also it triggers the famous screen init bug where one or both screens glitch out or show a blackscreen
I've never experienced that on my New3DS. But... there is a test screen pattern in the "arm11_fill_to_mem_words" function in lcd3ds.a22, that might look like a glitch on the top screen (if you have working top screen backlights).

No, it's showing this weird pattern on another 3DS but on the N3DS XL it's showing a fading out glitched image of the bootloader instead of that pattern. This may happen on one or both screens. It's different for every (affected) 2/3DS. A few ones even just turn off completely
Re: 3DS reverse engineering
by on (#240991)
Wayback machine doesn't have the 3dbrew "RL78 hardware manual" document archived, but it was probably wrong anyways (the 3dbrew I2C Registers page contains some mistakes that could be explained only by using the wrong datasheet: It's mentioning an "ITMC" register and a "prohibited bit" in the RTC, that would hint on RL78/G13 datasheet. And it's also mentioning a "leap year" feature, which doesn't match up with any datasheets that I've seen).
The 78K0R/KC3-L, 78K0R/KE3-L datasheet seems to be a lot closer to the 3DS MCU registers. The ITMC is actually RSUBC, and there is no prohibited bit, and most likely also no leap year counter (other than the regular year counter itself). What is nice on the 3dbrew I2C page is that it mentions the "ticks" values for the power button timings, making it very easy to find & patch that values.

MCU firmware uploading appears to done by writing 3 ascii characters for unlocking, and then writing the 4000h bytes firmware image. There is a backup copy, so there should be little risk of bricking anything by transfer errors.
The two things that could brick are: Successfully uploading bugged code. And mixing old backup with incompletely uploaded new code (to avoid that, one should probably upload new/unique IDs to 1FF6h, 2000h, 4FF6h.
The MCU memory map is a bit odd...
Code:
00000h..00FFFh  Code part 1
01000h..01FFFh  Code part 1 copy    ;\uploaded firmware is
02000h..04FFFh  Code part 2         ;/written here
05000h..07FFFh  Code part 2 copy
EFFD0h..EFFD1h  Unknown
F0000h..F07FFh  Extra SFR's
F2000h..Fxxxxh  Partial mirror of Code part 2
Fxxxxh..FFFFFh  RAM and SFR's
After upload, if okay: part 1 should be swapped (via a hardware feature), and if failed: part 2 should be restored (via a software generated backup). Or so, I haven't tested that.

profi200 wrote:
It's not a network problem. I heard from others they have the exact same problem... Sending wifiboot.FIRM itself is also failing. With sending wifiboot itself it goes as far as showing reading FIRM sections on the 3DS side but hangs at 0%.
Okay, if it shows reading FIRM sections and 0%, then it does have passed through three TCP packets (for FIRM header, and Info Block, and response). And it does have set the RTC time from the Info Block, and it does have read the Length value of the first FIRM block. And it has sensed that the length of that block is nonzero (else it wouldn't show 0%).

It doesn't make sense that the above works differently when uploading wifiboot.firm than fastboot.firm (at that point it didn't even interprete the FIRM header contents, apart from checking if Length of 1st block is nonzero). Maybe the difference was just a random effect?
Some ideas for random effects...
  • Wine+no$gba doesn't work as it should? Would be nice to know if wine+no$gba works for uploading .nds/.dsi titles to .nds/.dsi consoles. I haven't found any tester that yet.
  • I2C bus is unstable on some consoles, and might hang when setting the RTC? If you reset the RTC time to 00:00:00, does wifiboot display the correct time (not the 00:00:00 setting), and does wifiboot update the MCU's RTC registers. so you can see the correct RTC time outside of wifiboot, too?
  • I am not doing too much memory/cache initializations. Could fastboot have something in different state than bootrom? Like caches, or memory access rights or the like.
  • As by now, only WEP is tested and working on 3DS. WPA/WPA2 and open network are still untested on 3DS (they should work, and UDP is apparently working in your network, there is a small chance that something goes wrong, eg. there might be a WPA bug causing memory corruption or the like).

profi200 wrote:
I checked again and this seems to be rather some sort of timeout...
Also of note is when it fails to connect it prints out some kind of hexdump and that's it.
That hexdump contains the error code, I would at least need the first two lines of that dump. And also the previous line before the dump, to know where it had occurred.

profi200 wrote:
No, it's showing this weird pattern on another 3DS but on the N3DS XL it's showing a fading out glitched image of the bootloader instead of that pattern. This may happen on one or both screens. It's different for every (affected) 2/3DS. A few ones even just turn off completely
Hmmm, I could try to add that delay that you mentioned. All those effects have been observed in wifiboot?
Not using I2C transfers because some people say that they can't get them working on their consoles isn't a good option.
I would need of the affected consoles, so I could try to identify and fix the issue.
Or, keep in mind that Nintendo is doing that 188*2 cycle delay between I2C transfer (between last data byte & following device number of next transfer). Maybe doing that fixes the issue.
And of course one should take care that IRQ handlers or other CPU/Cores don't use I2C while other I2C transfers are in progress.
Re: 3DS reverse engineering
by on (#241036)
Power button functionality is (almost) fully working - even without patching the MCU firmware!

Removing the 7s delay: This delay is actually variable, the insane default setting can be changed via MCU register 24h (which is, rather misleadingly, called the "watchdog" register on 3dbrew). Changing that value is very good (especially for rev-engineering that includes crashing once and then), one might need to restore the default before starting other titles though (in case some of them rely on the insane delay):
Code:
MCU[24h] - Forced Power Off delay
  Delay in 16 "tick" units (0=Never, 1=Fastest, 5Dh=InsaneDefault)


Removing the slowly dying led delay: The delay is because the power-off function in firmware decreases the current LED brightness downto zero. That means the delay can be eliminated by setting the LED brightness to zero before issuing power-off. This can be done by selecting Power Led mode 04h via MCU register 29h:
Code:
MCU[29h] - Power LED mode
  First byte (Power LED mode):
    00h   = fade to brightness MCU[28h] with battery check
    01h   = fade to brightness MCU[28h]
    02h   = pulsating fade on/off with battery check
    03h   = fade to brightness 00h
    04h   = instantly set brightness 00h
    05h   = instantly set brightness FFh
    06h   = Blinking RED (affects Power+Notification LEDs)
    Other = Same as 00h
  Further bytes (optional, if any written):
    Power LED Blink pattern (default is 55h,55h,55h,55h)


Removing the tap-holding delay: That was actually already documented on 3dbrew, I had just missed that detail. Reading 13h bytes from MCU register 7Fh returns some system info, including the "raw button states" in the last byte, so one can poll the power button directly - and power off immediately when it gets pressed. It's unfortunate that one needs to read/skip the preceeding 12h bytes to reach the relevant byte, but it's more than worth getting lag-less button support.

The only thing that would require MCU patching is the 3s button hold delay when the console has crashed, changing that to 1s or a bit less would be quite nice, I still planning to give it a try someday.

profi200 wrote:
Trust me, powering off the screens and backlight speeds up shutdown a lot.

Okay, I have tried - but I see no difference. You mean writing MCU[22h] with "push" and "backlight" off flags? A lot means many milliseconds? And the effect is visibile on screen/leds? Or do I need an amperemeter and oscilloscope the measure the shutdown? I am almost thinking that the speedup occurs only with OS code, or C libraries.

profi200 wrote:
I tried now to upload a firm file and it's hanging no matter what i do.

I've just tried booting wifiboot from SD card via fastboot. When doing that, the following wifi-upload hangs after 4%. I have never had that problem when booting wifiboot via bootrom. So that seems to be a bug in fastboot... something not cleaned up properly to restore that same state as for bootrom.

I've also tried booting another firm via fastboot, that hangs completely (while still showing the fastboot menu screen):
Attachment:
diag3ds.ZIP [6.81 KiB]
Downloaded 84 times

This file doesn't use and doesn't initialize any caches, and there is only one firm section (used for both arm9 and arm11). It's also lacking some further initializations (ie. IRQs and DMAs should be disabled before starting the file). The screen output is same as in wifiboot, so that part should work, but something else makes it hang when starting it via fastboot.
EDIT: That diag3ds file doesn't init ARM9 stack, so that might hang (I've loaded it via a bootstub that did init the stack). But, fastboot doesn't even seem to start the file, instead it waits for button B then "returns" to fastboot, that makes me think that it does display a "load error" message on top screen?

PS. uhm, why is the tool called fastboot? It looks more like being on the slowish side, especially when booting. There seems to be a 1s delay before showing the menu. I am sure that you could remove that delay (or get away with only 100ms or less).
Re: 3DS reverse engineering
by on (#241038)
nocash wrote:
It doesn't make sense that the above works differently when uploading wifiboot.firm than fastboot.firm (at that point it didn't even interprete the FIRM header contents, apart from checking if Length of 1st block is nonzero). Maybe the difference was just a random effect?
Some ideas for random effects...
  • Wine+no$gba doesn't work as it should? Would be nice to know if wine+no$gba works for uploading .nds/.dsi titles to .nds/.dsi consoles. I haven't found any tester that yet.
  • I2C bus is unstable on some consoles, and might hang when setting the RTC? If you reset the RTC time to 00:00:00, does wifiboot display the correct time (not the 00:00:00 setting), and does wifiboot update the MCU's RTC registers. so you can see the correct RTC time outside of wifiboot, too?
  • I am not doing too much memory/cache initializations. Could fastboot have something in different state than bootrom? Like caches, or memory access rights or the like.
  • As by now, only WEP is tested and working on 3DS. WPA/WPA2 and open network are still untested on 3DS (they should work, and UDP is apparently working in your network, there is a small chance that something goes wrong, eg. there might be a WPA bug causing memory corruption or the like).

profi200 wrote:
I checked again and this seems to be rather some sort of timeout...
Also of note is when it fails to connect it prints out some kind of hexdump and that's it.
That hexdump contains the error code, I would at least need the first two lines of that dump. And also the previous line before the dump, to know where it had occurred.

profi200 wrote:
No, it's showing this weird pattern on another 3DS but on the N3DS XL it's showing a fading out glitched image of the bootloader instead of that pattern. This may happen on one or both screens. It's different for every (affected) 2/3DS. A few ones even just turn off completely
Hmmm, I could try to add that delay that you mentioned. All those effects have been observed in wifiboot?
Not using I2C transfers because some people say that they can't get them working on their consoles isn't a good option.
I would need of the affected consoles, so I could try to identify and fix the issue.
Or, keep in mind that Nintendo is doing that 188*2 cycle delay between I2C transfer (between last data byte & following device number of next transfer). Maybe doing that fixes the issue.
And of course one should take care that IRQ handlers or other CPU/Cores don't use I2C while other I2C transfers are in progress.

It could have been by luck it got that far i don't know.

Not tested uploading DS(i) homebrew on a DS(i). On 3DS your wifiboot in DSi mode gets stuck at "connecting" and i could not find dslink since WinterMute has removed all releases and it doesn't compile. I'm not gonna change network security for this since open or WEP is pretty risky. It's WPA2-PSK (AES) here.

I don't know about any RTC problems and booting the wifiboot FIRM actually show the correct time. When it hangs the displayed time stops updating.

The only difference is it's disabling icache on ARM11 while boot11 leaves it on (as per the TRM icache can actually be on without the MMU) which doesn't make a difference. Leaving it off even reduces the chance of problems.

Not gonna do WEP as said. You should not use WEP or open either. You are responsible for everything someone does over your internet connection if it can be proven you have not secured WiFi properly.

Editing this later with the hexdump.
Quote:
...
CRYPT: WPA2-AES 00 48
DOMAIN: 0188 3FFE

00150201

01 02 15 00 08 00 03 10
00 00 34 31 C4 CD 87 6E
05 00 00 02 06 00 AA 00
...


It's happening as soon as wifiboot inits the screens. Delays don't prevent it 100% but make it far less likely. And MCU spamming increases the chance of it happening aswell.



nocash wrote:
profi200 wrote:
Trust me, powering off the screens and backlight speeds up shutdown a lot.

Okay, I have tried - but I see no difference. You mean writing MCU[22h] with "push" and "backlight" off flags? A lot means many milliseconds? And the effect is visibile on screen/leds? Or do I need an amperemeter and oscilloscope the measure the shutdown? I am almost thinking that the speedup occurs only with OS code, or C libraries.

I don't know what you are doing but here the time between fading blue LED and and button press noticeably decreases when turning off the screens beforehand. And i mean power button + no screen deinit at all vs power button + powering off the screens via MCU reg write and resetting the GPU/LCD hardware.

nocash wrote:
I've just tried booting wifiboot from SD card via fastboot. When doing that, the following wifi-upload hangs after 4%. I have never had that problem when booting wifiboot via bootrom. So that seems to be a bug in fastboot... something not cleaned up properly to restore that same state as for bootrom.

I've also tried booting another firm via fastboot, that hangs completely (while still showing the fastboot menu screen):
Attachment:
diag3ds.ZIP

This file doesn't use and doesn't initialize any caches, and there is only one firm section (used for both arm9 and arm11). It's also lacking some further initializations (ie. IRQs and DMAs should be disabled before starting the file). The screen output is same as in wifiboot, so that part should work, but something else makes it hang when starting it via fastboot.

Everything else works running it from fb3DS. Note that it's meant to be installed in a FIRM partition on the eMMC (ideally both firm0/1).

...you can't expect it to boot something that has broken section hashes. It won't boot anything that is not playing by the rules (hash checks must pass and all sections must be in whitelisted regions) and you are again not seeing the error displayed. Pressing B makes it go back. Fixing the section hash manually makes this FIRM power off immediately.

nocash wrote:
PS. uhm, why is the tool called fastboot? It looks more like being on the slowish side, especially when booting. There seems to be a 1s delay before showing the menu. I am sure that you could remove that delay (or get away with only 100ms or less).

Again you are not seeing what's going on. It's displaying a splash on the topscreen. The duration is configurable in Boot setup --> Change splash but it requires the topscreen to see what's going on. Alternatively add "SPLASH_DURATION = 500" (500 ms which is the minimum) to sdmc:/3ds/fastbootcfg.txt to make it a bit faster. There is also a boot mode selection which allows to disable booting to the menu or displaying a splash before trying to boot slots. Quiet for example will show nothing but errors (if any happen) and otherwise it will straight boot to the next best configured FIRM. In quiet mode with configured slot this is pretty damn fast (around 400 ms including loading a big FIRM file from the SD card).

edit:
Uploading the attached FIRM file using No$GBA hangs not even displaying 0%.
Re: 3DS reverse engineering
by on (#241052)
Ooops, yes, I didn't have the .fix directive in diag3ds for fixing the sha256's, thanks.
Immeditialy powering down in diag3ds happens if you have button a/b pressed (I guess you did so in fastboot menu).
Well, at least you do now know how immediately powering off looks like, without the led fade-out delay.

I've spent the whole day on trying to figure out why wifiboot doesn't work with fastboot. I didn't found the problem. But noticed some other issues.

Fastboot seems to destroy the "LDR PC,[$+4]" opcodes in the exception handlers. That's causing diag3ds to hang upon data aborts (in the memdump screens) (because it's setting only vector at address $+4, but not the LDR opcode in the preceeding word).

Fastboot seems to have some of the New3DS-only CFG11 registers set to nonzero values (unlike when booting from bootrom).
For example, reading 10141300h (CFG11_MPCORE_CLKCNT) returns 00018001h. That would be bit16=unknown?, bit15=busy???, bit0=enable something.
I've tried to reset the New3DS-related CFG11 registers to zero, but that didn't help (but I don't know if it's that easy, or if one must reset them in a specfic order).

Running out of ideas, I've tried to add a huge wait-by-loop delay in wifiboot (to see how fast the arm11 cpu is running; with code cache enabled). The delay takes 10s when booted from bootrom, but with fastboot it comes out as 15 second delay.

If you have hardmod, then you could simply install wifiboot as firm0, I am quite optimistic that it will boot perfectly (or if it doesn't work then you would need the hardmod to uninstall it).
Re: 3DS reverse engineering
by on (#241061)
nocash wrote:
Ooops, yes, I didn't have the .fix directive in diag3ds for fixing the sha256's, thanks.
Immeditialy powering down in diag3ds happens if you have button a/b pressed (I guess you did so in fastboot menu).
Well, at least you do now know how immediately powering off looks like, without the led fade-out delay.

Choosing A for poweroff is not a good idea. Very quickly pressing A makes that tool actually work.

nocash wrote:
I've spent the whole day on trying to figure out why wifiboot doesn't work with fastboot. I didn't found the problem. But noticed some other issues.

Fastboot seems to destroy the "LDR PC,[$+4]" opcodes in the exception handlers. That's causing diag3ds to hang upon data aborts (in the memdump screens) (because it's setting only vector at address $+4, but not the LDR opcode in the preceeding word).

You should not rely on the bootloader to setup things like that. You maybe can assume that when booted by the bootroms but not bootloaders running after the bootroms. fb3DS stubs the second exception vectors before it loads a FIRM to prevent it from jumping who knows where (in case of an exception). A few other FIRM loaders do this too because it's considered good practice.

nocash wrote:
Fastboot seems to have some of the New3DS-only CFG11 registers set to nonzero values (unlike when booting from bootrom).
For example, reading 10141300h (CFG11_MPCORE_CLKCNT) returns 00018001h. That would be bit16=unknown?, bit15=busy???, bit0=enable something.
I've tried to reset the New3DS-related CFG11 registers to zero, but that didn't help (but I don't know if it's that easy, or if one must reset them in a specfic order).

This reg is 16 bits wide and it's set to 1 to enable the other 128 MB RAM for FIRM files booted through it. It has no other (known) effect. To undo this you need interrupts enabled doing this: https://github.com/derrekr/fastboot3DS/ ... cpu.c#L134
This will hang if all the ARM11 cores don't enter wait for interrupt state. The part where it changes it is line 123.

nocash wrote:
Running out of ideas, I've tried to add a huge wait-by-loop delay in wifiboot (to see how fast the arm11 cpu is running; with code cache enabled). The delay takes 10s when booted from bootrom, but with fastboot it comes out as 15 second delay.

If you have hardmod, then you could simply install wifiboot as firm0, I am quite optimistic that it will boot perfectly (or if it doesn't work then you would need the hardmod to uninstall it).

You seem to make a lot of assumptions about the environment/hardware state your code is running under. For example you are sending an IRQ over PXI without doing any sort of handshaking after control is handed over to your code (= assuming ARM11 is not slower than ARM9 which may not be true depending on the FIRM loader) or you are assuming r0 is 0 on entry and passing this immediately to the cache mcr instructions when ARM states the register "SBZ" (should be zero). The bootroms only clear all the regs because of security reasons just like they are going insane clearing the cache lines manually. I would recommend you initializing absolutely every piece of hardware you use just like we and others do. It makes it far less likely to run into strange freeze errors taking ages to debug.

I have tried running it from firm0 and indeed it started working but it still gives this hexdump running it again. You are probably not disconnecting properly from the AP is my guess (in this case). And i don't need no boring hardmod anymore since ntrboot (flashcard) is way easier and faster :wink:
Re: 3DS reverse engineering
by on (#241087)
I've made a database with some of the most important initial bootrom register values, mostly AMR9 registers, plus ARM11 IRQ registers. And a selftest function that displays all mis-initialized registers (ie. showing addresss, correct, incorrect values):
Attachment:
diag3ds.ZIP [9.5 KiB]
Downloaded 162 times
The main issue that breaks wifiboot seems to be that fastboot is routing all ARM11 IRQs to "target=nowhere" (instead of "target=CPU0"). The IRQ priorities are also set to non-default values (but that shouldn't disturb in case of wifiboot).

Okay, if wifiboot is working when you boot it as firm0 (or change the IRQ targets mentioned above)... what is working exactly?

Uploading and starting .firm files is working, right?

Are the display glitches still occurring?
And if yes, does the bootrom's blue-screen have those glitches, too?
Asking because my code is based on the bootrom screen output.

The hexdump error is from an unexpected WMI_DISCONNECT_EVENT (with reason value AUTH_FAILED). I have never experienced that with my APs (except perhaps on bad WEP passwords, but not on simple re-connections) (well, and I do occassionally get disconnected after several minutes of inactivity, not sure why, the code should send dummy messages every once and then to prevent that).

I'll add a WMI_DISCONNECT_CMD after successful upload in next version, maybe that will convince your AP that it may process new re-connections thereafter.
Of course, I can't do that if wifiboot has crashed (that will hopefully no longer happen, when fixing the IRQ targets).
And, the very nature of mobile wifi is that connections can get lost without proper disconnection. If your AP is really insisting on disconnections, and refusing re-connection otherwise - that might be a bit frustating.

I could also add retries in the connect function, but if that works depends on how often or long your AP is refusing connections...
Does the hexdump error occur only ONCE, on the first reboot after the upload?
Or does it occur REPEATEDLY upon each and every reboot, until some timeout has ellapsed after some minute(s)?

In the latter case, automatic retries won't help too much.
Re: 3DS reverse engineering
by on (#241096)
nocash wrote:
I've made a database with some of the most important initial bootrom register values, mostly AMR9 registers, plus ARM11 IRQ registers. And a selftest function that displays all mis-initialized registers (ie. showing addresss, correct, incorrect values):
Attachment:
diag3ds.ZIP
The main issue that breaks wifiboot seems to be that fastboot is routing all ARM11 IRQs to "target=nowhere" (instead of "target=CPU0"). The IRQ priorities are also set to non-default values (but that shouldn't disturb in case of wifiboot).

This is not worth changing in my opinion. I spent quite a bit time to understand how the GIC works and getting it in a stable, initialized state. It's worth noting that the GIC causes issues to FIRM files booted through fb3DS if it doesn't reset it before jumping to the loaded FIRM. I don't know how that happens to FIRMs not using IRQs at all but it did. Initially i was setting the priorities all to 0xF which caused NATIVE_FIRM to hang on N3DS. Stuff like that pisses me off but i can't do anything but "fix" it on my side since Nintendo will not give a fuck fixing their code. This does a full reset on it and it works with everything else including Nintendos FIRMs: https://github.com/derrekr/fastboot3DS/ ... rupt.c#L31

nocash wrote:
Okay, if wifiboot is working when you boot it as firm0 (or change the IRQ targets mentioned above)... what is working exactly?

Uploading and starting .firm files is working, right?

It's uploading and running the FIRM as intended. Note: You should check the FIRM section hashes in wifiboot. It looks like it doesn't care currently but trust me, if you are dealing with noobs you want to be on the safe side and verify the FIRM.

nocash wrote:
Are the display glitches still occurring?
And if yes, does the bootrom's blue-screen have those glitches, too?
Asking because my code is based on the bootrom screen output.

Not tested on N3DS. I did all this on my test dummy old 3DS. The N3DS i'm using for playing games and i had to fix corrupted files on the SD card just a few days ago so i would rather not take any chance.

nocash wrote:
The hexdump error is from an unexpected WMI_DISCONNECT_EVENT (with reason value AUTH_FAILED). I have never experienced that with my APs (except perhaps on bad WEP passwords, but not on simple re-connections) (well, and I do occassionally get disconnected after several minutes of inactivity, not sure why, the code should send dummy messages every once and then to prevent that).

I'll add a WMI_DISCONNECT_CMD after successful upload in next version, maybe that will convince your AP that it may process new re-connections thereafter.
Of course, I can't do that if wifiboot has crashed (that will hopefully no longer happen, when fixing the IRQ targets).
And, the very nature of mobile wifi is that connections can get lost without proper disconnection. If your AP is really insisting on disconnections, and refusing re-connection otherwise - that might be a bit frustating.

I could also add retries in the connect function, but if that works depends on how often or long your AP is refusing connections...
Does the hexdump error occur only ONCE, on the first reboot after the upload?
Or does it occur REPEATEDLY upon each and every reboot, until some timeout has ellapsed after some minute(s)?

In the latter case, automatic retries won't help too much.

It's happening on every try until after a few minutes. Then it suddely works again. Something that also fixes it is doing the connection test in the system settings which succeeds even faster than usual after wifiboot ran. So nwm is not having any issues connecting even when wifiboot ran beforehand.
Re: 3DS reverse engineering
by on (#241104)
The ARM datasheet has this sentence -One consequence of the strict comparison is that a Pending interrupt with the lowest possible priority, 0xF, never causes the assertion of an interrupt request to MP11 CPUs, permitting an extra level of interrupt enabling
It isn't quite clear what they are trying to say about which strict comparision, but it might mean that priority 0Fh is disabling the interrupt. The default priority setting when booting firm files is 08h, so you must use that, too, for booting firm files. After all, you do already have code for cleaning up things, you just need to change that code to use the correct values in the cleanup. There are several good reasons for maintaining compatibility with the original bootrom.
Re: 3DS reverse engineering
by on (#241105)
nocash wrote:
The ARM datasheet has this sentence -One consequence of the strict comparison is that a Pending interrupt with the lowest possible priority, 0xF, never causes the assertion of an interrupt request to MP11 CPUs, permitting an extra level of interrupt enabling
It isn't quite clear what they are trying to say about which strict comparision, but it might mean that priority 0Fh is disabling the interrupt. The default priority setting when booting firm files is 08h, so you must use that, too, for booting firm files. After all, you do already have code for cleaning up things, you just need to change that code to use the correct values in the cleanup. There are several good reasons for maintaining compatibility with the original bootrom.


Here, "strict comparison" means that the priority of an interrupt must be lower than the priority mask in order to be asserted. Because the highest value of the priority mask is 0xF, this means that an interrupt with a priority of 0xF will never fire.

...

I've been reading through the last couple pages. nocash, I respect your work and what you've done for the NDS/DSi scene, so I'll try to say this as politely as possible. You are hitting your head against a brick wall if you expect current FIRM loaders to recreate the boot ROM environment. These tools have been around for several years, and they have already set the standards for homebrew FIRMs to follow. If you want wifiboot and any other software you write to be compatible with these loaders, you have to follow their standards, not try to get them to change. That means you must properly initialize all registers on the ARM11 and ARM9. It's a good idea to initialize your environment when writing bare-metal code no matter what the platform is anyway, but here, it's absolutely necessary.
Re: 3DS reverse engineering
by on (#241114)
Ah, okay, that comparision. Now that you mention it, they have that confusing sentence twice in the datasheet (once for the priority mask where it makes sense, and once for the priority values where it appears to out of context because it doesn't mention the relation to the mask thing). Hmmm, the term "mask" is confusing by itself, I guess it's meant to be a 4bit COMPARE value (not an AND-mask).

As for whose head is harder or softer, we will see. I am not srtrictly against proper initializations, but I do think other software - especially bootloaders - are responsible to initialize things properly, too. I hope that I've convinced 1-2 people in NDS scene about that, too (admittingly that wasn't easy). For bootloaders, initialization would be important because otherwise people might think that seemingly working .firm files could be safely installed as firm0, causing bricks. And vice-versa, people thinking that wifiboot didn't work, or that it wasn't properly tested on real hardware.

The goal of some of the conversation is a bit unlcear. It feels a bit like we are saying "my bugs will outperform your bugs" and everyone disagrees on fixing their own bugs, even when knowing about how and what to fix.
Or it looks like so. Behind the scenes: I didn't ignore all advice and I have fixed a couple of bigger and smaller details in my code. I would be glad if future bootloaders will recurse some of my findings, too.
That, even (or especially) if improved initialization accurracy breaks compatibility with older homebrew .firm files. The same problem exists for emulator devrs, too. If an emu can play bugged homebrews then it's an emulation inaccuracy (and potentially hard to fix).
Re: 3DS reverse engineering
by on (#241168)
I've found out why executing the same "wait-by-loop" did sometimes take around 10 seconds, and sometimes around 15 seconds. That effect was caused by the Branch Prediction bit in ARM11 CP15 Control register. Normally, a SUBS+BNE takes 4 clks per loop cycle, with the branch prediction enabled it does take only 2.5 clks per loop cycle

Ie. it looks as if the CPU predicts 75% of the jumps to be taken; maybe because somebody had estimated loops to repeat in multiples of 4 loop cycles, or whatever.
My test used SUBS r0,1, and BNE for the loop. The bootrom uses SUBS r0,5 and BCS. So, I've tested that, too: The prediction is producing the same timings of 2.5 clks per loop cycle there, too. That timings are all with code enabled, of course.

The two important findings are that: It might be good to enable ARM11 branch prediction to speed up things. And, one must recurse whether branch prediction is enabled when computing timings for "wait-by-loop" functions.

---

And, I have rev-engineered how the CPU clock/mode change register is working exactly:
Code:
10141300h - New3DS - CFG11_MPCORE_CLKCNT
  0-2    Desired Mode (0,1,2,3,4,5,6,7) (see below)                   (R/W)
  3-14   Unused (0)
  15     Mode Change IRQ Flag (0=None, 1=IRQ 58h) (write 1 to reset)  (R/ack)
  16-18  Current Mode (0,1,3,5,7) (see below)                         (R)
  19-31  Unused (0)
Mode values:
  Mode 0: Old3DS Mode, 268MHz (1x), 128MB FCRAM, no L2C cache
  Mode 1: New3DS Mode, 268MHz (1x), 256MB FCRAM, and L2C cache controller
  Mode 3: New3DS Mode, 536MHz (2x), 256MB FCRAM, and L2C cache controller
  Mode 5: New3DS Mode, 804MHz (3x), 256MB FCRAM, and L2C cache controller
  Mode 2/4/6 are same as Mode 0. Mode 7 is same as Mode 5
Mode changes are applied ONLY once when all ARM11 cores are in Wait for IRQ
state (eg. "WFI" opcode). At that point, the IRQ flag in bit15 is set, and IRQ
58h is triggered.
IRQs are triggered ONLY when changing to different modes:
  - Changing between mode 0/1/3/5/7 (because they are different)
  - Changing between mode 5/7 (although they appear to be same)
IRQs are NOT triggered when:
  - Rewriting the current mode value (because mode is already same)
  - Changing between mode 0/2/4/6 (because they are all same as mode 0)
In Old3DS mode, data abort occurs when trying to access the extra FCRAM at 28000000h, or the L2C cache controller at 17E10000h. The other "extra memory" at 1F000000h isn't affected by mode change?
Clock changes affect the ARM11 CPU clock, including the MPCore Timer/Watchdog registers at 17E00600h (if desired, one can change their prescalers to maintain them running at same speed despite of the higher CPU clock).
The 804MHz mode should be used only if CFG11_SOCINFO.bit2 indicates that it is supported.
The IRQ flag in bit15 should be acknowledge before (or alongsides with) writing the desired clock value (needed if it was still set from an older un-acknowledged clock change).
IRQ 58h should be enabled (to recover from WFI, or maybe anything like Vblank IRQ might work for that, too). CPSR.I flag does not need to be enabled, WFI does only wait for IRQs (but can recover without executing them). Using the old CP15 wait for IRQ opcode instead of WFI does work, too.
Re: 3DS reverse engineering
by on (#241190)
profi200 wrote:
CARDSPI has been fully figured out by the way and 3dbrew has been updated with all details including a little bug.

Thanks for pointing out! I've just checked the https://3dbrew.org/wiki/SPICARD_Registers page. It looks much than some months ago!
There are some small details that are still unlclear. And some general descriptions could also help to make easier to figure out what the registers & bits are good for.

The overall purpose is related to "savedate on SPI flash chips in game cartridges", right? Well, noob question (and the AUTOPOLL description does already answer the question). Anyways, it would be more clear if it were mentioned at the begin of the article.

The select flag in the DONE register might deserve another short sentence. I assume using (or not using) it between transfers allows to do multiblock transfers, including combined WriteCmd+ReadData transfers.

Some bits have only the purpose described, but not what they are doing on which specific value. Ie. many people only say "enable flag", and forget to say "1=enabled", or just say "length", but forget to say "in bytes" or "in bits".

For FIFO status, it isn't clear to me if it refers to Read-fifo, or Write-fifo, or both. I guess DMA is handling that stuff automatically. But for manual transfers, I am a bit lost how it works. For reading, there should be also a fifo empty flag? And what is the fifo size? And if the transfer length is less than the fifo size, does the fifo ever get "full"?
With the current description, it sounds as if reading would work as so:
- If fifo=full then read one word (or up to as many words that are known to fit into the fifo).
- If transfer=done then read any remaining words (even if fifo isn't full).
Not so sure if I am right there.

Timeout for AUTOPOLL brings up many questions (although that nasty details aren't sooo important).
There seems to be a pair of brackets missing in the "Tries = 31<<Baudrate + Timeout" formula?
If one wants to know the timeout duration, then one would compute "Duration=Baudrate*Time/Baudrate"?
Something like "Duration=Time" would be easier to read. Or is the baudrate technically relevant in that formula?
Of course, for the full formula, "Time" would be replaced by be something like "Duration=(xxx*(2^n)) microseconds".
If "Tries" means number of bytes (?) then I would assume that 4bit mode will cause earlier timeouts than 1bit mode?
EDIT: That is, if 4bit mode can be used for AUTOPOLL at all (most SPI FLASH chips are likely to support 4bit only for data transfers, not for mere status reads).
EDIT-EDIT: Or, if tries consists of command AND status bytes, then one try would be worth 16bits, perhaps with a small pause for toggling chipselect?

Small detail: "bit offset" is a bit confusing, "bit number" might be clearer.
EDIT: Ah, or is it the offset in respect to the transfer order, ie. 0 = first bit (MSB)?

A link/note on the card pinout would be also nice... the 3dbrew Pinouts page doesn't mention game cards, but I fould them mentioned here: http://www.3dbrew.org/wiki/Gamecards

PS. I've had troubles testing R/W for BLKLEN and INT_MASK. It seems that they become read-only(?) during active transfers (ie. when starting a transfer via CNT or AUTOPOLL registers). If there's no transfer, then they are R/W... and INT_MASK is 4bit wide (not 3bit).
The glitch with the lower 8bit of CNT appering shifted to upper bits didn't occur for me yet. Are you sure about the bug, and have some info how to reproduce it? And if lower 8bit are shifted... does that mean that bit0-7 are then read as zero, or do they still contain the intact value, too?
Re: 3DS reverse engineering
by on (#241230)
I've started doing 3DS memory allocation in no$gba & adding support for load firm files (for viewing them in the disassembler). My first attempts crashed because some firms load to VRAM and DSP RAM. Here's some run-down commonly used & unsupported areas:
Code:
Common FIRM Load areas are:
  08006000h 0.9M  ARM9-WRAM  (common for ARM9 code) (not first/last some bytes)
  18000000h 6.0M  VRAM       (eg. used by GBA/DSi firmwares)
  1FF00000h 0.5M  DSP Memory (eg. used by FIRM0, initially mapped to ARM9 side)
  1FF80000h 0.5M  AXI RAM    (common for ARM11 code)
With that areas, a FIRM file can be max 7.9Mbyte (if it is loaded as file, the
default size of the firm0/firm1 partitions is only 4Mbyte each).
There is a blacklist in bootrom preventing some memory regions:
  07FFB800h..07FFFBFFh  ARM9 ITCM part (otp, mbr, keys...)
  FFF00000h..FFF02FFFh  ARM9 DTCM (first 3000h) (arm9 data)
  FFF03000h..FFF03FFFh  ARM9 DTCM (last 1000h) (arm9 stack)
  080F8000h..080FFFFFh  ARM9 WRAM (last 8000h) (rom card related?)
  08000000h..0800003Fh  ARM9 WRAM (first 40h) (exception vectors, etc)
  20000000h..27FFFFFFh  FCRAM (whole 128MB)
  FFF00000h..1FFFFFFFh  Bugged (size of that area is negative/nonsense)
Moreover, the bootrom doesn't have Main RAM and New3DS memory enabled. And, the
bootrom PU has also disabled some memory areas (though those might pass when
using DMA for loading?).
Okay, with VRAM being 'officiallly used', I should really support that in wifiboot, too. It's already (almost) working because the code is loading firm sections to a temp buffer in main ram; the part that needs to be changed is to wait with the final code relocation until vram is no longer used for video output.

The ARM11 FIRMs are surprisingly starting with a seemingly undocumented opcode: F10C01C0. I could only find out that this opcode is said to be called "CPSID IAF". Plus some blurb on the syntax & parameters: http://infocenter.arm.com/help/topic/co ... hfdbhd.htm but that doesn't describe the binary opcode encoding. I have docs for other ARM11 opcodes like WFI or CLREX. But that CPS thing seems to be hard to get by : /
Does somebody know docs for that?

PS. I mean for ARM mode. The encoding for CPS in THUMB mode is officially documented.

Edit: Found it, https://developer.arm.com/docs/ddi0597/ ... e-pe-state (if the page isn't showing all 32 bits of the instruction: there is an invisible scrollbar for viewing the remaining bits). Of course that link is blocked for win9x browsers, but I've found a pdf that can be download (though not viewed) under win9x, but I have somehow got the text extracted from it:
DDI_0597_ARM_a32_t32_instruction_set_architecture.pdf wrote:
CPS, CPSID, CPSIE
Change PE State changes one or more of the PSTATE.{A, I, F} interrupt mask bits and, optionally, the PSTATE.M mode field, without changing any
other PSTATE bits.
CPS is treated as NOP if executed in User mode unless it is defined as being CONSTRAINED UNPREDICTABLE elsewhere in this section.
The PE checks whether the value being written to PSTATE.M is legal. See Illegal changes to PSTATE.M.
It has encodings from the following instruction sets: A32 ( A1 ) and T32 ( T1 and T2 ) .
A1
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1 1 1 1 0 0 0 1 0 0 0 0 imod M 0 (0) (0) (0) (0) (0) (0) (0) A I F 0 mode
CPS (imod == 00 && M == 1)
CPS{<q>} #<mode> // (Cannot be conditional)
CPSID (imod == 11 && M == 0)
CPSID{<q>} <iflags> // (Cannot be conditional)
CPSID (imod == 11 && M == 1)
CPSID{<q>} <iflags> , #<mode> // (Cannot be conditional)
CPSIE (imod == 10 && M == 0)
CPSIE{<q>} <iflags> // (Cannot be conditional)
CPSIE (imod == 10 && M == 1)
CPSIE{<q>} <iflags> , #<mode> // (Cannot be conditional)
if mode != '00000' && M == '0' then UNPREDICTABLE;
if (imod<1> == '1' && A:I:F == '000') || (imod<1> == '0' && A:I:F != '000') then UNPREDICTABLE;
enable = (imod == '10'); disable = (imod == '11'); changemode = (M == '1');
affectA = (A == '1'); affectI = (I == '1'); affectF = (F == '1');
if (imod == '00' && M == '0') || imod == '01' then UNPREDICTABLE;
Looks like crap, but it should be enough to decode the opcode. I just wished to be back in the days of 14kbit modems where information was blocked less strictly for older OSes. Or well, I guess I was just a teen with a brandnew PC those days.
Re: 3DS reverse engineering
by on (#241280)
Hmmmm, there are still unknown instructions popping up in the FIRM disassembly. But I think I might now have the relevant datasheets.

ARM DDI 0100I - the "Preface" lists new "ARMv6" opcodes (versus older ARMv5TE and ARMv5TEJ)
ARM DDI 0360F - the "Intruduction" lists new "MPCore" opcodes (versus the above ARMv6)

Are that the right two documents for figuring out differences between ARM9/NDS (with ARMv5TE) and ARM11/3DS?

Going by the above docs, Jazelle bytecode is automatically supported in all ARMv6 processors. Or are there are any ARMv6's that are excluding that feature? The instruction set name should be then something with "xJ" suffix to indicate excluded Jazelle support.

ARMv6 with the "MPCore" extension does probably also has an instruction set name? Ie. some one-letter suffix appended to the "ARMv6" string?

There is something called "ARMv6-M", but that is apparently referring to Cortex-M, unrelated to the MPCore stuff.
Re: 3DS reverse engineering
by on (#241502)
nocash, is there a special dumper you used to dump the WiFi ROM? I have started working on WiFi stuff in my 3DS emulator, and I'm running into problems with the handshake protocol - NWM hangs after I send a WMI_READY reply when it does a WMI_SYNCHRONIZE command. So I'd like to see what's different on the 3DS firmware + ROM.
Re: 3DS reverse engineering
by on (#241510)
a way you could go would be recording the data from BMI_LZ_DATA commands to a file, then decompressing that. the compression looks ass-stupid, but I'm not sure whether I got it right.

getting it disassembled and all is another deal tho. I found an IDA plugin for the Xtensa arch, but not sure whether it can be applied to this use case, as it looked rather specific.

otherwise, I figure you can abuse WINDOW_READ shito to dump the wifi memory. not sure there's homebrew code for using this wifi device (on the DSi side, libnds has nothing for it, and dswifi is for the old DS wifi device), but, libnds has a SD driver which is used for SD/NAND access, you can probably hijack that and change the base I/O address and have a working base for talking to the wifi device.
Re: 3DS reverse engineering
by on (#241512)
Yes, WINDOW_READ_ADDR and WINDOW_DATA can be used for dumping the ROM (and RAM, including the decompressed firmware, if it is already uploaded to RAM). The wifisdio.a22 file in wifiboot contains code for that (and also for SDIO init that you may need before using WINDOW_DATA). I've used some dirty/hacky unreleased wifiboot variant for getting the dump transferred to PC, I should still have the code if you need it, or else you could use whatever other method (like writing the dump the SD card).

The WMI_READY_EVENT contains the firmware version (and this is one of the things that are sent by the RAM firmware, not by the ROM). On 3DS, the event data is 10h-bytes in size (unlike DSi), and the firmware version number mentioned in gbatek (=230000B3h) is for a fairly old NWM version, your NWM is probably newer, and might require to send a newer version number. The version number does also differ on which of the three firmwares you have uploaded (ie. for the firmware with the "Mac Filter" feature, it would be 230000D8h instead of 230000B3h). You can probably find your version in the somewhere in the decompressed firmware... it's most probably 230000xxh.

I would have thought that WMI_SYNCHRONIZE would occur a bit later than WMI_READY_EVENT, but that might be timed a bit differently in NWM versus DSi Launcher (which doesn't use SYNCHRONIZE at all as it's only uploading the firmware). Anyways, the initialization should look as so: BMI commands, then a handful of "weird" handshakes (that are neither BMI nor WMI commands), and then the WMI stuff, with WMI_READY_EVENT and WMI_REGDOMAIN_EVENT, and then (I think thereafter?) WMI_BITRATE, WMI_FRAMERATES and WMI_SYNCHRONIZE etc.
Btw. There are also SDIO logs from DSi browser (in the "DSi Wifi rev-engineering" thread), maybe some of that data is helpful for 3DS, too. Ah, and the DSi wifi-firmware upload... that can be logged in no$gba when having SD/MMC(=and SDIO) logging enabled in the TTY Debug Message window.
Re: 3DS reverse engineering
by on (#241516)
The instruction set for ARM11 mpcore is ARMv6K. It isn't really mentioned in the mpcore docs, but it's mentioned here: http://infocenter.arm.com/help/index.js ... CDJCJ.html The new opcodes are mentioned to exist in the mpcore docs, but not described how they work, I think the only resource for that is peeking at the ARMv7 (or newer) architecture reference manuals. Fortunately there are only a few new opcodes in v6K (SETEND, CLREX, STREX/LDREX-with-new-B/H/D suffix, and the HINT opcodes (TrueNop, YIELD, WFE, WFI, SEV). And, they are all ARM-only (there were no new THUMB opcodes added in v6K).

I've meanwhile implemented all new opcodes in my assembler/disassembler.... disassembling FIRM isn't so much fun though : /
The New3DS FIRMs have that self-decrypting ARM9 code, that won't stop hacking, but it's a bit distracting.
The Old3DS FIRMs are a bit easier to get by. But even there, it looks as if some ARM9 code gets relocated (to other ARM9 addresses? Or ARM7 addresses?) after loading - so absolute addresses in the disassembly don't match up with initial load addresses.
Hmmm, and the ARM9/ARM11 code in the GBA FIRM file seems to lack some important things like I2C bus access. There is a .code file inside of the GBA FIRM file - does that contain the "missing" code? Or does the GBA FIRM even load further code/modules from other eMMC folders?

Going for some easier (plain hardware) stuff... here's some new info on the GPIO registers:
Code:
10147000h - GPIO_DATA0_DATA_IN (R?)
  0       Unknown (0=?, 1=Normal) HID-sysmodule, HID PAD state  ;\GPIO services
  1       Unknown (0=?, 1=Normal)                               ; bitmask 7h
  2       Hinge (0=Shell Open, 1=Shell Closed)  (IRQ:60h/62h?)  ;/
  3       Unused?
  4       Unused?  ;"Only used by Boot11" (uh, but bootrom tests only bit2)
  5-15    Unused?

10147010h - GPIO_DATA1_DATA_IN (R)
10147010h - GPIO_DATA1_DATA_OUT (W)
10147011h - GPIO_DATA1_DIRECTION (R/W)
10147012h - GPIO_DATA1_IRQ_EDGE (R/W)    ?
10147013h - GPIO_DATA1_IRQ_ENABLE (R/W)
  0       gpio:CDC Headphone (0=None, 1=Connected) (IRQ:64h) ;\GPIO services
  1       Unknown (0=?, 1=Normal)                  (IRQ:66h) ;/bitmask 18h
  2-7     Unused

10147014h - GPIO_DATA2_DATA_OUT (R/W)
  0       gpio:MCU, gpio:NWM: Wifi?     ;-GPIO services bitmask 20h
  1-15    Unused

10147020h - GPIO_DATA3_DATA_IN (R)
10147020h - GPIO_DATA3_DATA_OUT (W)
10147022h - GPIO_DATA3_DIRECTION (R/W)
10147024h - GPIO_DATA3_IRQ_EDGE (R/W)    ?
10147026h - GPIO_DATA3_IRQ_ENABLE (R/W)
  0       gpio:CDC, gpio:IR                         (IRQ:68h?) ;\
  1       gpio:IR             Boot11(uh, really?)   (IRQ:69h)  ;
  2       gpio:HID                                  (IRQ:6Ah?) ;
  3       gpio:HID, gpio:IR   used with ir:rst.     (IRQ:6Bh)  ; GPIO services
  4       gpio:IR send?  1=IR LED enable, 0=disable (IRQ:6Ch)  ; bitmask 3FFC0h
  5       gpio:IR receive?                          (IRQ:6Dh)  ;
  6       gpio:NFC                                  (IRQ:6Eh)  ;
  7       gpio:NFC                                  (IRQ:6Fh)  ;
  8       gpio:HID  HID-sysmodule, HID PAD state    (IRQ:70h?) ;
  9       gpio:MCU      (with interrupt 71h)        (IRQ:71h?) ;
  10      gpio:NFC                                  (IRQ:72h)  ;
  11      gpio:QTM   (Twlbg? and/or New3DS?)        (IRQ:73h??);/
  12-15   Unused (0)

10147028h - GPIO_DATA4_DATA_OUT_WIFI (R/W)
  0       gpio:MCU, gpio:NWM: Wifi Enable (1=On) ;-GPIO services bitmask 40000h
  1-15    Unused (0)

10147100h - Legacy RTC ?
Normally only 10147100h.bit15 is R/W, and the other bits/registers at 101471xxh
are all zero. But reportedly they can contain this...
  10147100h 2  RTC_CNT (?) ???
  10147110h 1  RTC_?       ???
  10147111h 1  RTC_?       ???
  10147120h 4  RTC_RAW     Byte-wise bit-swapped (bit7 is bit0, etc.) BCD RTC
                            (byte0 = seconds,
                             byte1 = minutes,
                             byte2 = hours,
                             byte3 = day(?))
  10147124h 4  RTC_?       RTC offset?
  10147130h 4  RTC_?       ???
  10147134h 4  RTC_?       ???
  10147140h 4  RTC_?       Some sort of byte-wise bit-swapped seconds counter
  10147150h 1  RTC_?       ???
  10147151h 1  RTC_?       ???
  10147160h 4  RTC_?       ???
  10147164h 4  RTC_?       ???
That is, apparently related to the "ARM7_RTC_xxx" registers at 100181xxh.
I haven't verifed the IRQ edge selection (but it's very most likely same as on DSi). Verified is switching the ports to output-direction with irq-enabled, and then toggling the data value - doing that (bit by bit) is triggering ARM11 interrupts. Except, the IRQ numbers with question marks didn't trigger (probably just because external hardware did hold the gpio pin at a fixed voltage).
Re: 3DS reverse engineering
by on (#241601)
nocash wrote:
I would have thought that WMI_SYNCHRONIZE would occur a bit later than WMI_READY_EVENT, but that might be timed a bit differently in NWM versus DSi Launcher (which doesn't use SYNCHRONIZE at all as it's only uploading the firmware). Anyways, the initialization should look as so: BMI commands, then a handful of "weird" handshakes (that are neither BMI nor WMI commands), and then the WMI stuff, with WMI_READY_EVENT and WMI_REGDOMAIN_EVENT, and then (I think thereafter?) WMI_BITRATE, WMI_FRAMERATES and WMI_SYNCHRONIZE etc.
Btw. There are also SDIO logs from DSi browser (in the "DSi Wifi rev-engineering" thread), maybe some of that data is helpful for 3DS, too. Ah, and the DSi wifi-firmware upload... that can be logged in no$gba when having SD/MMC(=and SDIO) logging enabled in the TTY Debug Message window.


I see where my confusion comes from now. It's not sending WMI_SYNCHRONIZE, it's sending that weird handshake after BMI_DONE.

I'm not sure where WMI_REGDOMAIN_EVENT comes into play. It receives my WMI_READY_EVENT, and WiFi init completes as per the open-source Atheros driver, but NWM hangs after that. What is supposed to be sending WMI_REGDOMAIN_EVENT? Is it another handshake command, or does it immediately follow WMI_READY_EVENT? I tried to send WMI_REGDOMAIN_EVENT 1 million cycles after WMI_READY_EVENT, but it didn't change anything.
Re: 3DS reverse engineering
by on (#241607)
Yes, that's the handshake, not WMI_SYNCHRONIZE. Oh, in current gbatek version... I still do have some outdated stuff where I was speculating that it might have been WMI_SYNCHRONIZE, I'll remove that sentence (maybe that was confusing you).

WMI_READY is sent after the last handshake message. And WMI_REG_DOMAIN is sent automatically a moment later. The timing should be more or less don't care, you could probably sent them immediately after each other (ie. ready in one 80h-byte mbox block, and domain appended in the next 80h-byte mbox block).

In no$gba, I am simply writing this bunch of crap to the mbox, that are the 6 handshake messages, and the 2 wmi messages, each one 80h bytes in size, and all sent at once at the begin of the handshake (and the DSi launcher seems to be happy with that, ie. it's reading the stuff after each handshake step, despite of everything being sent at once) (EDIT: not 100% sure if my code was really working like that, maybe I had somewhere inserted some extra trickery that prevents the launcher from seeing the newer mbox blocks too early):
Code:
  db 0,2,10h,0, 8,0,1,0, 0ah,0,8,6, 16h,0,2,6,      70h dup (0) ;-reply to cmd_1          ;?                ;?
  db 0,2,12h,0, 8,0,3,0, 0,1,0,1,   2,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_1      ;100h CONTROL_SVC ;control
  db 0,2,12h,0, 8,0,3,0, 1,1,0,2,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_1_1_5  ;101h DATA_BE_SVC ;best effort
  db 0,2,12h,0, 8,0,3,0, 2,1,0,3,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_2_1_5  ;102h DATA_BK_SVC ;background
  db 0,2,12h,0, 8,0,3,0, 3,1,0,4,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_3_1_5  ;103h DATA_VI_SVC ;video
  db 0,2,12h,0, 8,0,3,0, 4,1,0,5,   0,6,0,0,  2,6,  6eh dup (0) ;-reply to cmd_8_2_4_1_5  ;104h DATA_VO_SVC ;voice
  db 1,2,16h,0, 8,0,1,10h                                       ;\1st reply to cmd_2_4_3_1_5's irq  ;WMI_READY_EVENT
   @@mod_mac_address:                                           ;   ;00:23:xx:xx:xx:xx=MAC address
   db 0,23h,xxh,xxh, xxh,xxh,2,0                                ;
   @@mod_firmware_version:                                      ;
   db 7bh,0,0,21h, 2,6,  6ah dup (0)                            ;/  ;2100007Bh = firmware version (for AR6002 on DSi)
  db 1,2,0eh,0, 8,0,6,10h                                       ;\2nd reply to cmd_2_4_3_1_5's irq  ;WMI_REGDOMAIN_EVENT aka WMI_REG_DOMAIN_EVENT
   @@mod_reg_domain:                                            ;   ;80000188h = reg domain (188h=japan (and also same value used for europe))
   db 88h,1,0,80h                                               ;
  db 2,6, 6eh dup (0), 0dh,0,0,0                                ;/
That values are as logged from hardware (and include some garbage bytes at the end of some 1-2 blocks, that should be zerofilled instead of containing the garbage, eg. the 0dh at the end of the last message). However, most of it isn't garbage. The first 6 bytes in each block are the MBOX header, and the "2,6" is part of the MBOX Trailer (or what I've called Ack List in gbatek).

---

Last some days I've looked into the CDMA/XDMA controller specs. I have some rough idea how the DMA instructions are working...
The most simple case would using DMA_MOV to set up CCR and source/dest addresses, and the issue a series of DMA_LD / DMA_ST to load/store the data from source to dest. And slightly more complex code could use loops and syncing with data requests from peripherals.

What I haven't figured out are the "conditional" opcodes (those with the S or B suffix) that execute only if the "SINGLE" or "BURST" condition is true (and execute as NOP if it's false).
If the instruction does have a peripheral number specified (eg. "DMALDPS P2"), then it does supposedly get the condition from that peripheral.?
But "DMALDS" can be also conditional, but doesn't specify "P2" or the like. So where does the condition come from in that case? From the "memory addresss"? Or from the most recently used peripheral number?
And is that a thing at all on 3DS, or do all 3DS devices support only SINGLE or only BURST transfers anyways? Or even never use any conditional opcodes at all?

Btw. here's a summary of the DMA instructions
Code:
  00h                   DMAEND                  ;-done
  01h                   DMAKILL                 ;-
  04h                   DMALD                   ;\
  05h                   DMALDS                  ; load from SAR
  07h                   DMALDB                  ;/
  08h                   DMAST                   ;\
  09h                   DMASTS                  ; store to DAR
  0Bh                   DMASTB                  ;/
  0Ch                   DMASTZ                  ;-store zero to DAR
  12h                   DMARMB                  ;-read memory barrier
  13h                   DMAWMB                  ;-write memory barrier
  18h                   DMANOP                  ;-
  20h,len-1             DMALP lpc0,len          ;\loop start with loop counter
  22h,len-1             DMALP lpc1,len          ;/
  25h,periph*8          DMALDPS periph          ;\load peripheral
  27h,periph*8          DMALDPB periph          ;/
  29h,periph*8          DMASTPS periph          ;\store peripheral
  2Bh,periph*8          DMASTPB periph          ;/
  2Ch,rel_addr          DMALPEND                ;-loop end for DMALPFE
  30h,periph*8          DMAWFP periph,single    ;\
  31h,periph*8          DMAWFP periph,periph    ; wait for peripheral
  32h,periph*8          DMAWFP periph,burst     ;/
  34h,event*8           DMASEV event            ;-send event
  35h,periph*8          DMAFLUSHP periph        ;-
  36h,event*8+00h       DMAWFE event            ;\wait for event
  36h,event*8+02h       DMAWFE event,invalid    ;/(optional cache invalidate)
  38h,rel_addr          DMALPEND  lpc0          ;\
  39h,rel_addr          DMALPENDS lpc0          ; loop end for DMALP lpc0/1
  3Bh,rel_addr          DMALPENDB lpc0          ;
  3Ch,rel_addr          DMALPEND  lpc1          ;
  3Dh,rel_addr          DMALPENDS lpc1          ;
  3Fh,rel_addr          DMALPENDB lpc1          ;/
  54h,imm16             DMAADDH SAR,+imm16      ;\
  56h,imm16             DMAADDH DAR,+imm16      ; add halfword
  5Ch,imm16             DMAADDMH SAR,-imm16     ; (or negative halfword)
  5Eh,imm16             DMAADDNH DAR,-imm16     ;/
  A0h,channel,imm32     DMAGO channel,imm32     ;\jump/goto entrypoint
  A2h,channel,imm32     DMAGO channel,imm32,ns  ;/(ns=non-secure mode)
  BCh,00h,imm32         DMAMOV SAR,imm32        ;\
  BCh,01h,imm32         DMAMOV CCR,imm32        ; move to register
  BCh,02h,imm32         DMAMOV DAR,imm32        ;/
  imm8                  DCB imm8                ;\manually defined 'code'
  imm32                 DCD imm32               ;/
  -                     DMALPFE                 ;-set loop start (no opcode)
It looks relative easy to use. Even without a dedicated assembler, one could implement all instructions as macros, or simply enter them in data lines (best with using symbolic constants for the opcode names).
The slightly uncomfortable part is that one need to "patch" the code with the actual source/dest values in the DMA_MOV SAR/DAR instructions (and needing unaligned writes for that, although one could probably insert DMA_NOP's or even place DMA_LP loop start opcodes between the DMA_MOV SAR/DAR to have the imm32 values at well aligned addresses.
On the other hand, the method that Nintendo is using looks a bit overcomplicated (dynamically creating the whole code with STRB opcodes for emitting the DMA opcodes & parameters).

And, a summary of the DMA registers:
Code:
Corelink DMA Engines
XDMA cannot access the ARM9 bootrom at all.
  1000C000h  ARM9 XDMA Registers
  10200000h  ARM11 Old3DS CDMA Registers
  10206000h  ARM11 New3DS CDMA Registers

DMAC Control Registers
  000h       DSR           DMA Manager Status Register (R)
  004h       DPC           DMA Program Counter Register (R)
  008h-01Ch  -             Reserved
  020h       INTEN         Interrupt Enable Register (R/W)
  024h       INT_EVENT_RIS Event-Interrupt Raw Status Register (R)
  028h       INTMIS        Interrupt Status Register (R)
  02Ch       INTCLR        Interrupt Clear Register (W)
  030h       FSRD          Fault Status DMA Manager Register (R)
  034h       FSRC          Fault Status DMA Channel Register (R)
  038h       FTRD          Fault Type DMA Manager Register (R)
  03Ch       -             Reserved
  040h+n*4   FTRn          DMA channel n Fault type (R)
  060h-0FCh  -             Reserved
DMAC Channel Thread Status Registers
  100h+n*8   CSRn          DMA channel n Channel status (R)
  104h+n*8   CPCn          DMA channel n Channel PC (R)
  140h-3FCh  - - - - - Reserved
DMAC AXI Status and Loop Counter Registers
  400h+n*20h SARn          DMA channel n Source address (R)
  404h+n*20h DARn          DMA channel n Destination address (R)
  408h+n*20h CCRn          DMA channel n Channel control (R)
  40Ch+n*20h LC0_n         DMA channel n Loop counter 0 (R)
  410h+n*20h LC1_n         DMA channel n Loop counter 1 (R)
  414h+n*20h               Reserved
  418h+n*20h               Reserved
  41Ch+n*20h               Reserved
  500h-CFCh  -             Reserved
DMAC Debug Registers (debugging is meant to be synonym for "start execution")
  D00h       DBGSTATUS     Debug Status Register (R)
  D04h       DBGCMD        Debug Command Register (W) (start INST code)
  D08h       DBGINST0      Debug Instruction-0 Register (W) (code[2]+ch+thread)
  D0Ch       DBGINST1      Debug Instruction-1 Register (W) (byte[4])
  D10h-DFCh  -             Reserved
DMAC Configuration Registers
  E00h       CR0           Configuration Register 0 (R)
  E04h       CR1           Configuration Register 1 (R)
  E08h       CR2           Configuration Register 2 (R)
  E0Ch       CR3           Configuration Register 3 (R)
  E10h       CR4           Configuration Register 4 (R)
  E14h       CRD           DMA Configuration Register (R)
  E18h-E7Ch  -             Reserved
  E80h       WD            Watchdog Register (R/W) (rev1 only)
  E84h-FDCh  -             Reserved
Peripheral and component identification register summary
  FE0h-FECh  periph_id_n   Peripheral Identification Registers (R)
  FF0h-FFCh  pcell_id_n    Component Identification Registers 0-3 (R)
The baffling thing is that there seems to be no officially mentioned way to start transfers with those registers. Nintendo is doing that by writing a DMA_GO opcode to the "Debug Registers" (which does then jump/goto to the actual DMA code entrypoint)... and it looks as if that is actually the only working way to start transfers?

I am having problems to wrap my head around why they have called the registers "Debug Registers" instead of "Transfer Start Registers" or whatever. My best theory would be some translation error or misconception like this:
Bingo Blink, ARM developer wrote:
When I was in my early teens, I had started software by clicking on main.exe, but since I became a programmer, I got familar with typing debug main.exe at the command prompt, because that's how the devrs are doing it. I think debug means low level execution. The term is dating back to steam ships, like, when they were saying that a ship had debugged from the port. Or something like that.
What was weird is, when I designed the DMA controller for ARM, the senior devrs nodded it off, and congratulated me on even having implemented a debug feature - as if they had thought that people of my age could only start DMA transfers by mouse clicking instead of by debugging! Honestly, some of the seniors are a bit senile and out of touch with the low level things.
Hmmm, or, well, those "Debug Registers" could be probably used to implement single-step execution for debugging purposes. But that would be a rare corner case, not their normal use.

---

Well, anyways, reading the XDMA/CDMA config & id registers on 3DS... Two new findings are:
- ARM9 XDMA has four channels (not two).
- New3DS CDMA uses revision r1p1 (not r1p2) (though that should be "functionally same").
Oh, and that New3DS CDMA registers can be accessed only in New3DS mode (enabled with the same register that does also control the 3DS CPU clock and extra FCRAM). If enabled, the New3DS CDMA registers can be read (without causing data abort). And reading the Old3DS CDAM regs does still work, too. I don't know if there's further stuff needed to actually activate the New3DS CDMA registers (and to deactivate the Old3DS CDMA regs).

Some more details from those registers:
- XDMA: 4 channels, 8 peripherals, 12 events
- Old3DS CDMA: 8 channels, 18 peripherals, 16 events
- New3DS CDMA: 8 channels, 32 peripherals, 32 events
That doesn't neccessarily mean that all peripheral IDs are actually used in the 3DS. But for XDMA, it should be safe to say that it could only use id 0..7 (and leaves 8..31 unused).

Is there a way to poll all 32bit peripheral data request flags from some status register? That would be nice for testing if/which hardware is triggering them.
Only other way would be to program one channel to watch for one peripheral. The bad thing is that there are less channels than peripherals.

---

PS. With the wifi emulation. Are you just trying to get through the initialization, or are you planning to go farther, and support actual network/internet connections?
Emulating an access point is (hopefully) not too difficult. The more complicated part would be to connect the emulated access point to the real outside world. Stephen (from dswifi) mentioned...
Stephen Stair wrote:
there are some libraries that can do the hard work for you, if you get past the dislike of HLL code :) (e.g. winpcap)
To do it yourself basically means to build a NDIS lightweight filter driver and install it into the network stack, and communicate through that. Pretty complicated stuff.
If that driver thing would work... then everything else should work by itself (ie. the router handing out DHCP addresses, and taking core of routing packets to local network & internet).
I have zero experience with making windows drivers.
And, I had looked at some specs... it seems that there are a handful of different NDIS versions. I don't know if there is any backwards compatibility for old driver versions still working on newer OS versions. I am afraid that not, and that one would need to write a different driver for OS version (and add more drivers when new OS versions come out).
Re: 3DS reverse engineering
by on (#241613)
Handshake: Ah yes, I thought from reading GBAtek that it went straight to WMI after BMI_DONE. Well, adding REGDOMAIN like you said doesn't help matters either - it does receive and process the event, but it just hangs in the same place. Clearly there's something else I'm missing... eventually I will decompress the firmware being uploaded and see which type it is. If it's Type5 then I would not expect it to work using the current assumptions we have for DSi firmware.

CDMA/XDMA: I don't know what peripherals support single/burst. The only peripherals to use CDMA/XDMA so far in my emulator are the WiFi SDIO controller and the SHA FIFO, and both have used burst. It may be safe to assume that everything uses burst, but I cannot say for certain.

WiFi emulation: My intention is to only get past initialization. Like the DSi, the 3DS hangs if NWM cannot initialize, and I feel it is more prudent to get Home Menu working and booting applets/games instead of making WiFi fully work.
Re: 3DS reverse engineering
by on (#241635)
Yes, that wifi firmware init is a nasty obstacle to get things working. On DSi, it does show the launcher/bootmenu even if wifi init had failed... but it does somewhere memorize an error flag... and trying to start a title from the bootmenu won't work if that error flag is set.

Some ideas/checklist for wifi init...
- did you emulate the chip id and host interest stuff that happens along with the bmi commands?
- you do have the handshake emulated now? ARM11 should receive 6 messages, and reply with 6 messages
- after the handshake, mbox IRQs are needed instead of mere MBOX polling (that should arrive as IRQ number 41h on ARM11 side)
- wifiboot's "wifisdio.a22" source code should work as good flowchart that shows what happens when during init

NWM might do a few things differently than DSi launcher. If so, you might see that (if it's doing unexpected stuff). Or, less easy to spot, it might be more picky about verifying incoming values than my wifiboot code (which simply ignores the data in the incoming handshake messages, and (much earlier) doesn't check the SDIO func0 registers).

Did you try emulating wifiboot.firm instead of NWM? That's probably easier to get working, and easier to track down what goes wrong. And if wifiboot works, but NWM doesn't, then you do at least know that the problem is related to something that is not checked in wifiboot.
There isn't so much useful screen output in wifiboot during firmware upload (unless you enable the "verbose" mode in the source code). But it might just help to try to single-step through the "sdio_atheros_init" function.
Re: 3DS reverse engineering
by on (#241648)
speaking of 3DS/DSi shito

I'm stuck with something regarding booting cartridges in melonDSi, so, if anyone knows about that

basically, booting DS titles works fine, so does booting the installed DSiware titles (Flipnote, system settings, browser...)

but, booting any DSi-enabled game freezes before the game is booted

the DSi menu seems to do things with TWLCFG1.dat, like hashing its contents, but then, it gets stuck, and the freeze is likely related to it (it's in the same function that hashes TWLCFG1.dat)

so, wondering what I could be missing or what could be shitting itself there, if anybody happens to know. the DSi menu code is an absolute fucking mess of threads and events/objects and callbacks and shit, it's an absolute fucking ass-nightmare to debug.
Re: 3DS reverse engineering
by on (#241652)
It hangs where exactly? Inside of the SHA1 function, when doing what? And really inside of that function? I don't think that the SHA1 functions could hang at all, unless they were called with totally wrong parameters or wrong stack pointer.

As far as I understand the DSi Launcher can boot NDS cart and DSiware, but the very same DSi Launcher doesn't work for DSi carts? That might hint on a cartridge related problem. Does the ROM-image contain a complete dump, including the DSi areas? And the secure area is properly encrypted? Region would need to match, but if not, that would probably show an error message instead of hanging. Cartridge commands in DSi mode are using DSi blowfish key instead of the old NDS blowfish key. The cartridge Chip ID may be also important to indicate that it's a DSi cartridge (and to indicate how to load it, with what "sector size").
Re: 3DS reverse engineering
by on (#241655)
WiFi checklist:
- Some of it I've ignored, but I do handle at least the EEPROM and chip ID. NWM crashes after BMI if those aren't correct.
- Yes, the full handshake goes through.
- I do handle Mbox IRQs for the last step of the handshake, but on my version of NWM, this is also handled on IRQ 40h. NWM doesn't register an interrupt for 41h - not a bug in my emulator, the code only has an SVC for IRQ 40h.

wifiboot: I did try this, but it crashed both Luma3DS and boot9strap. I assume this is because of the lack of SHA hashes? I can edit my NAND dump to install wifiboot on FIRM0 later. It would be appreciated if wifiboot has those hashes in the future so that I can just boot it from my SD image :wink:

My main fear is that I will have already passed the "sdio_atheros_init" function in both wifiboot and NWM. At least NWM gets through the whole handshake without complaining.
Re: 3DS reverse engineering
by on (#241658)
Yes, using IRQ 40h for both SDIO controller and SDIO card should work, too. Using separate IRQs, 40h and 41h for that would make more sense, but the SDIO controller can also map both to IRQ 40h.

Are the SHA's missing in wifiboot, too? I thought they were only missing in the diag3ds file. Anyways, the RSA is missing in wifiboot (you can just replace that by the sighax signature). I didn't have that in there because it would depend on where you boot from.... I could insert the eMMC signature as default, as that is probably most commonly used.

If you got through the init then you are fine... or is it still crashing in the final steps, on WMI_READY_EVENT? What values are you sending in there exactly? The MAC address should match the I2C-EEPROM (and maybe also needs to match the SPI-FLASH). The firmware version should probably match up (with whatever you have uploaded). And, I don't know what is supposed to be in the last two halfwords.

And, yes, knowing which firmware type you have uploaded might also help. You could probably see the ASCII strings even without decompressing it. But seeing the firmware version number might require decompression (or a good guess on which bytes are what for). The 32bit firmware version number should be in literal pool (shortly after the ASCII strings).

---

I am looking through the MMU virtual memory TLB specs in "DDI0360F_arm11_mpcore_r2p0_trm". Some of it is new and confusing...
Attachment:
MagicMMU.gif
MagicMMU.gif [ 10.14 KiB | Viewed 3581 times ]
If that writing ever appears on the wall - then I can say that I have seen that magic number that everyone is talking about with my very own eyes.

What is a bit more confusing is that there are several different first-level tables: Backwards compatibility tables, and ARMv6 tables with/without sub pages. Most of that table entries have bit16 specified as SBZ. But looking at the bootrom code... the bootrom seems to be happily writing values with bit16=1 (eg. 10012h or 50416h in LSBs of the table entry). Am I missing something, or are there bugs in the bootrom, with bit16 set when it shouldn't be set?

The general idea (if I got it right) seems to be that the 4GB memory space is divided into 1Mbyte blocks, and those blocks are defined in the first-level table (4000h bytes in size, containing 1000h entries of 4byte each). And the 4byte entries point to separate second-level tables that contain the actual memory mapping for the separate 1Mbyte memory blocks. Or point to nowhere if a 1Mbyte block is unused.

Hmmm, but the bootrom seems to set one first-level table entry to 17E02412h... that doesn't look like a pointer to a second-level table... it looks more like a physical address?
I guess I'll need to read more about the meaning of LSBs of the table entries, maybe it'll make more sense then.
Re: 3DS reverse engineering
by on (#241674)
I figured out the problem with wifiboot. It was crashing because it assumes that CPSR is in system mode in the entry point, but Luma3DS loads all FIRM payloads in supervisor mode. This is a problem because the wifiboot function that initializes stack pointers for the different modes leaves CPSR in system mode, so when the function returns, it reads the last LR value from system mode (which is some boot ROM code). Other FIRMs inline their SP initialization in the startup code rather than making it a separate function, so this issue does not affect them. This might also affect loading under B9S but I haven't checked.

NWM: This is after WMI_READY_EVENT is processed, and the function that does process this event returns a success code. So maybe there's yet another event that it's expecting... the answers will/might be revealed after the firmware decompression.

MMU junk: each L1 entry can be 1 MB unmapped (always causes a fault when accessing), 1 MB section, 16 MB supersection, or L2 table pointer. L2 entries can be 4 KB unmapped, 4 KB small page, and 64 KB page. The MSBs of the entry, if they're not an L2 table pointer, are a physical address base. The 3DS always uses ARMv6 tables.

The MMU isn't needed to get past the boot ROMs or loading homebrew payloads. It's only needed by NATIVE_FIRM, TWL_FIRM, and AGB_FIRM when they set up their respective OSes.
Re: 3DS reverse engineering
by on (#241732)
I have decompressed the firmware that NWM uploads, and surprisingly, it appears to be Type1. It contains the string A_INIT() FAILED and is only about ~0x1A00 bytes when compressed. As expected, it is a newer firmware version than what you have: 0x230000EC. I will try to examine this firmware to see if there's anything special about my newer NWM.
Re: 3DS reverse engineering
by on (#241737)
PSI wrote:
I have decompressed the firmware that NWM uploads, and surprisingly, it appears to be Type1. It contains the string A_INIT() FAILED and is only about ~0x1A00 bytes when compressed. As expected, it is a newer firmware version than what you have: 0x230000EC. I will try to examine this firmware to see if there's anything special about my newer NWM.
I think, I have that file on my New3DS, too. At least, it's having the same 230000ECh version number in it. The exact compressed size is 1B1Bh bytes?

I haven't disassembled that version yet. But I could give it a try tomorrow, and perhaps share the disassemblies for the old and new version (then you have both in same disassembler syntax, making it easier to compare them, I'll have a look at it too, would be interesting to get an idea what they added or changed in newer versions).

Without proper headers in the NWM file, it's a bit difficult to find and extract the Type1 block and load it into no$gba disassembler - currently that works only if I tweak some stuff manually (would be easier if I would already have working 3DS emulation, then it would load automatically).
Re: 3DS reverse engineering
by on (#241738)
PSI wrote:
I figured out the problem with wifiboot. It was crashing because it assumes that CPSR is in system mode in the entry point, but Luma3DS loads all FIRM payloads in supervisor mode.
Good to know, thanks! I will fix that for better compatibility. Nethertheless, I am still strongly expecting that firm's are normally booted in system mode ; )
At least, that's how I am familar with it from booting NDS/DSi stuff, and I assume that 3DS works the same.

PSI wrote:
The MSBs of the entry, if they're not an L2 table pointer, are a physical address base. The 3DS always uses ARMv6 tables.
Ah, okay, thanks! I thought the sections/supersections were also pointing to L2 tables, instead of directly pointing to the memory block.

I've typed up the tables from the "DDI0360F_arm11_mpcore_r2p0_trm" datasheet to have them all in ASCII, that's making it easier to view & compare them as than scrolling through different pages of the pdf.

---

First of, the format of the 32bit entries in the Second-Level table...
Code:
Backwards-compatible Second-Level Page Table
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Address______________________|_?TEX?_|AP3|AP2|AP1|AP0|C_B|0_1| Large 4x16K
  |__Address______________________________|AP3|AP2|AP1|AP0|C_B|1_0| Small 4x1K
  |__Address______________________________|_SBZ_|_TEX_|AP_|C_B|1_1| Extended 4K

ARMv6 Second-Level Page Table (with n,S,A,X)
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Address______________________|X|_TEX_|n_S_A|_SBZ_|AP_|C_B|0_1| Large 64K
  |__Address______________________________|n_S_A|_TEX_|AP_|C_B|1_X| Small 4K
Okay, the new ARMv6 format has additional "n,S,A,X" attributes.
And the old format, I assume the Extended 4K pages are real 4K pages, and the Big 64K and Small 4K pages are internally split to 4x16K and 4x1K.
Hmmmm, that is strange. I first thought the Second-Level table would then contain four entries for each splitted page...
But that seems to be wrong, instead, there seems to be only one entry, but with four AP attributes in AP0/AP1/AP2/AP3 ?
Also confusing: The old format has a 4bit TEX value (that one marked "?TEX?") instead of the usual 3bit TEX values. That seems to be a bug in the documentation (bit2 and below are documented as "TEX[2...", but nothing in the whole doc mentions "TEX[3...").

---

And the 32bit entries in the First-Level table, that's going to be more confusing, with 3 different variants...
Code:
Backwards-compatible First-Level Page Table
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Second-Level-Table-Address_______________|P|Domain_|_SBZ_|0_1| Coarse
  |__Address______________|0|0|_SBZ_|_TEX_|AP_|P|Domain_|0_C_B|1_0| Section 1MB
  |__Address______|___SBZ___|1|_SBZ_|_TEX_|AP_|P|Ignored|0_C_B|1_0| Super 16MB
  |___________________________________________________________|1_1| Reserved

ARMv6 First-Level Page Table - with subpages enabled
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Second-Level-Table-Address_______________|P|Domain_|_SBZ_|0_1| Coarse
  |__Address______________|0|0|_SBZ_|_TEX_|AP_|P|Domain_|0_C_B|1_0| Section 1MB
  |__Address______|___SBZ___|1|_SBZ_|_TEX_|AP_|P|Ignored|0_C_B|1_0| Super 16MB
  |___________________________________________________________|1_1| Reserved

ARMv6 First-Level Page Table - with subpages disabled (with n,S,A,X)
   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
   1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0
  |__Ignored__________________________________________________|0_0| Fault
  |__Second-Level-Table-Address_______________|P|Domain_|_SBZ_|0_1| Coarse
  |__Address______________|0|0|n_S_A|_TEX_|AP_|P|Domain_|X_C_B|1_0| Section 1MB
  |__Address______|___SBZ___|1|_SBZ_|_TEX_|AP_|P|Ignored|X_C_B|1_0| Super 16MB
  |___________________________________________________________|1_1| Reserved
The first two seem to be actually identical. Almost looks as if they have them accidentally documented twice, once as "Backwards-compatible", and then again as "ARMv6 with subpages". Or is there a difference between them?
That "subpages" are apparently meant to be the 4K and 64K being split to 4x1K and 4x16K. And the new format without subpages does instead have the new "n,S,A,X" flags (as in the Second-Level entries).
Except, the Supersection has "SBZ" instead of "n,S,A", but, that doesn't make any sense. I guess that's another bug in the docs?
If the SBZ is bogus... that would also explain why the bootrom is setting bit16 in supersections.

---

And, two heartfelt complaints and cautions about the datasheet:
What they are calling "Coarse Table" is actually the "Second-Level Table".
What they are calling "Large Table" and "Small Table" is actually the final "Memory Block", (not an ominous "Third-Level Table")
That two things made it harder than neccessary to figure out what they were talking about.

---

Oh, and the difference between "Section" and "Supersection"...
The 16MB Supersection consists of 16 identical entries.
Which is basically same as 16 normal 1MB section entries with continously increasing addresses.
So there is no "real" difference (like saving memory by having bigger or smaller page tables).
As far as I understand, the only benefit is internal caching (ie. the hardware needs to cache only 1 of the 16 identical supersection entries, and it can assume that the other 15 entries are the same).

And the difference between 4K pages and 64K pages, that's the same, too, right?
Re: 3DS reverse engineering
by on (#241779)
wifiboot: It does seem nonsensical to change from system to supervisor mode. Nevertheless, that's how it is, and people expect FIRMs to work from all sources.

MMU: 4K pages and 64K pages aren't entirely identical. 4K has an XN bit, but 64K doesn't.

---

I've acquired the AR6014 ROM and have begun writing an Xtensa interpreter. My goal is to fully LLE WiFi initialization and replicate the results in HLE.

I was curious on how exceptions worked, as exception vectors are entirely implementation-defined. I have figured out their locations:

Code:
ROM_BASE = 0x8E0000
ROM_BASE+0x000: ResetVector
ROM_BASE+0x400: OverflowException4
ROM_BASE+0x440: UnderflowException4
ROM_BASE+0x480: OverflowException8
ROM_BASE+0x4C0: UnderflowException8
ROM_BASE+0x500: OverflowException12
ROM_BASE+0x540: UnderflowException12
ROM_BASE+0x640: ??? (break 0x10 + jmp infinite loop)
ROM_BASE+0x720: Either UserExceptionVector or KernelExceptionVector (reads from a function pointer table using EXCCAUSE as the index and jumps to it)
ROM_BASE+0x820: ??? (break 0x14 + jmp infinite loop)
ROM_BASE+0x920: InterruptVector[2] (uses EXCSAVE[2])
ROM_BASE+0xA20: InterruptVector[3] (uses EXCSAVE[3])
ROM_BASE+0xB20: ??? (single jmp infinite loop)


The Overflow/Underflow exceptions are related to out-of-bound accesses on the register window: they simply save and restore registers on the stack allocated by an ENTRY instruction, respectively.

User/KernelExceptionVector is a generic exception handler that many exceptions (indicated by EXCCAUSE) jump to, such as illegal instructions, syscalls, and regular interrupts. Which one that gets jumped to depends on the user mode, and apparently, only one of those vectors is defined. I would have to see what the user mode gets set to to see which vector is actually present at 0x720.

InterruptVector[2] and [3] are both "high-priority" interrupts. Even when lower-priority interrupts are disabled, a high-priority interrupt can still trigger an exception. Which interrupts are enabled is determined by INTLEVEL; if an interrupt's priority is higher than INTLEVEL, it can trigger an exception. Regular interrupts use the generic exception handler above.

I am not sure what the unknown exceptions are. 0x640 might be the "other" generic exception handler (or at least intended to be used for that purpose) but here it hangs the system. 0x820 might be DoubleExceptionVector, which is triggered when an exception occurs while another exception is being serviced. I have no idea what 0xB20 could be - perhaps another interrupt source, an NMI, or even something else entirely?

I also don't know which interrupts correspond to which vectors. So far I've seen that Mboxes and timers can cause interrupts, and there are probably other interrupt sources as well. Is any of that documented, or do we have to figure out which vectors they have the "fun" way?
Re: 3DS reverse engineering
by on (#241822)
Low-level emulation of the xtensa code sounds cool. I have never really considered that because of the trillions of I/O registers attached to it... but most of them are probably completely unused, or used only for calibrating analog stuff, or used only later on for actual transfers. So, emulating the init code might work, good luck with that!

The meaning of the EXCCAUSE values and/or of the ROM_BASE+xxxh vectors... I don't remember having seen them documented anywhere. They might be hiding in official atheros firmware source code. And there are some text strings in the rom, related to badvaddr, timer, and watchdog etc.

I have now disassembled three different Type1 firmware versions.
version=230000B3h, size=0FD3h
version=230000DCh, size=10F7h
version=230000ECh, size=1B1Bh
The first two have only minor differences. The third has more changes, AND it doesn't work when using it in wifiboot.

The minor differences are that 230000DCh and up seem to clear the key_cache registers, have some extra code in the mode_switch function, and install some new function at [[523C18h]+868h]. None of that is breaking functionality (they do both work when using them in wifiboot).

The 230000ECh version seems to have identical init code as 230000DCh, except that 230000ECh is installing more stuff at [[523C18h]+99Ch], [[523C18h]+850h], [[523C18h]+2D8h], [[523C18h]+31Ch], [[523C18h]+324h], [[523C18h]+234h], [[523C18h]+848h], [[523C18h]+884h].

One of them is changing the WMI_SET_APPIE command (now allowing 16bit ieLen values, but no longer supporting most of the frametype values) (don't know if that is a bug or a wanted feature, it's apparently breaking backwards compatibility, but the APPIE command is rarely used (if ever), so it shouldn't matter).

Another of the new functions is changing something related to sending probe responses (maybe that's just related to internally handling the new 16bit ieLen values for the APPIE thing).

I don't know what the other new functions are doing, and when they are called. Maybe one of them contains important changes applied before handshake - that would explain the problem in wifiboot...

When using 230000ECh in wifiboot, the BMI stuff passes okay, and the wifi unit should then send the first handshake message. But it doesn't do that : [
I can't figure out what is wrong there... maybe it's waiting for another value written to RAM, or to I/O registers before starting the handshake, or it's now using MBOX1 instead MBOX0, or whatever.
Did you notice anything unusual done by the NWM code on ARM side, something that doesn't match up with the ARM code in wifiboot?

PS. For the [[523C18h]+nnnh] vectors used in RAM firmware, those are identical to the [[523C14h]+nnnh] vectors used in ROM.
Ie. [523C18h] and [523C14h] contain the same value, both pointing to the same function table.
Re: 3DS reverse engineering
by on (#241846)
PSI wrote:
MMU: 4K pages and 64K pages aren't entirely identical. 4K has an XN bit, but 64K doesn't.

Yeah, looks like so... although I would said it's vice-versa.
No wait, they do both have XN and TEX bits, they are just moved to different bit numbers in 4K vs 64K.
Re: 3DS reverse engineering
by on (#241932)
I give up on the 230000ECh version, I can't figure out why it doesn't work in wifiboot. Just gazing at the disassembly doesn't help on solving the problem. Some other ideas would be patching 230000ECh to make it behave like 230000DCh (and see if any of the patches makes it work), or patch it to output status messages, or log the NWM SDIO traffic in emulator or hardware.
On the other hand one can simply use wifiboot with one of the older 230000xxh versions, so it doesn't really matter what is wrong with 230000ECh.
Re: 3DS reverse engineering
by on (#242090)
I've released a wifiboot update, more on that here: viewtopic.php?f=23&t=18065&start=60#p242088 I hope it's working better with existing 3DS bootloaders now. Reconnection on warmboot should be now also faster.

The diag3ds tool is also updated,
Attachment:
diag3ds.ZIP [70.41 KiB]
Downloaded 101 times
the RW test currently doesn't work well, but the Initial Values test does check some more memory mapped registers, and some non-memory mapped ones (like CPSR and P15 registers). It's possible that a handful of values are wrong or unstable and show errors when they shouldn't, but most should be correct. It's now also testing a few New3DS registers (which will probably trigger many errors on Old3DS). The source code with the register values lists is also inclulded, maybe that lists can be useful for emulators or bootloaders.
Re: 3DS reverse engineering
by on (#242183)
The New3DS has something called "MVD" (my current theory is that that stands for Movie Decoder or so).
The value 67312398h in register [10207000h] appears to be known as "HW_ID" for linux/android "VPU SERVICES".
Searching for that two strings gives this source code http://git.jp.linux-rockchip.org/cgit/r ... 0dc086a0d1 which in turn contains 6731h (the upper 16bit of the 67312398h value).
So I guess the "MVD" is identical to that Rockchip hardware (whatever that is). Could that be right? Or are there already other details or datasheets known for that hardware?
Re: 3DS reverse engineering
by on (#242349)
I am currently examining the GPU framebuffer setup registers. They consist of several 12bit H/V position settings for the usual things like sync/left/right border/display start/end, plus some control/status registers.

The difficult part is the interrupt feature, there are 7-8 interrupt modes. The default mode is simple: It does just trigger one IRQ per frame (at a selected horizontal location).
The other modes can trigger multiple IRQs per frame (somewhere within the IRQ start/end positions; if they are setup properly, or fail to work; if the IRQ position settings are wrong).
I haven't really figured out how to use those special IRQ modes, at best I get them to trigger some IRQs in a wanted range (and then followed by either no further IRQs at all, or endless IRQs in an unwanted/unstoppable range).

Official datasheet or other docs would be nice to have. Is there anything available?
The registers should look about as shown below - does that I/O map look familar to anybody?.
Caution: Horizontal and Vertical may be swapped in datasheets (because the 3DS screens are mounted rotated by 90).

Code:
  10400400h 100h Framebuffer Setup "PDC0" (top screen)
  10400500h 100h Framebuffer Setup "PDC1" (bottom screen)
  PDC = "PICA Display Control" or so?

  10400400h/10400500h - V-total-1                 ;1C2h       ;\
  10400404h/10400504h - V-lower-border-end        ;0D1h       ;
  10400408h/10400508h - V-irq?                    ;1C1h       ;
  1040040Ch/1040050Ch - V-upper-border-end        ;1C1h       ; V
  10400410h/10400510h - V-sync-start (?)          ;000h/0CDh  ;
  10400414h/10400514h - V-sync-end                ;0CFh       ;
  10400418h/10400518h - V-lower-border-start      ;0D1h       ;
  1040041Ch/1040051Ch - V-irq?                    ;1C1h       ;
  1040041Eh/1040051Eh - V-irq?                    ;1C5h       ;/
  10400420h/10400520h - V-prepadd?                ;000h       ;-V
  10400422h/10400522h - V-?                       ;001h       ;-V
  10400424h/10400524h - H-total-1                 ;19Dh       ;\
  10400428h/10400528h - H-left border end         ;002h/052h  ;
  1040042Ch/1040052Ch -    ?                      ;192h       ;
  10400430h/10400530h - H-right border end        ;192h       ; H
  10400434h/10400534h - H-SYNC start              ;192h/04Fh  ;
  10400438h/10400538h - H-SYNC end?               ;001h/050h  ;
  1040043Ch/1040053Ch - H-left border start       ;002h/052h  ;
  10400440h/10400540h - H-IRQ-1 end               ;192h       ;
  10400442h/10400542h - H-IRQ-2 start             ;193h       ;/
  10400444h/10400544h - V-irq??                   ;000h       ;-V?
  10400448h/10400548h - Screen Vsync/Hsync type?
  1040044Ch/1040054Ch - Screen Border color
  10400450h/10400550h - Vertical current position (R)
  10400454h/10400554h - Horizontal current position (R)
  10400458h/10400558h - Unused (0)
  1040045Ch/1040055Ch - V-display area size       ;0F0h       ;-V
  1040045Eh/1040055Eh - H-display (no effect)     ;190h/140h  ;-H
  10400460h/10400560h - V-lower-border-middle?    ;0D1h       ;\V
  10400462h/10400562h - V-upper-border-start      ;1C1h       ;/
  10400464h/10400564h - H-left border middle?     ;002h/052h  ;\H
  10400466h/10400566h - H-right border start      ;192h       ;/
  10400468h/10400568h - Framebuffer A first address (Left eye, or both eyes)
  1040046Ch/1040056Ch - Framebuffer A second address (Left eye, or both eyes)
  10400470h/10400570h - Framebuffer format
  10400474h/10400574h - Interrupt type
  10400478h/10400578h - Framebuffer select
  1040047Ch/1040057Ch - Readonly flags? maybe hblank/vblank/etc
  10400480h/10400580h - Color Lookup Table index (R/W)
  10400484h/10400584h - Color Lookup Table data (R/W)
  10400488h/10400588h - Unused (0)
  1040048Ch/1040058Ch - Unused (0)
  10400490h/10400590h - Framebuffer Horizontal Address Step
  10400494h/10400594h - Framebuffer B first address (Right eye, or unused)
  10400498h/10400598h - Framebuffer B second address (Right eye, or unused)
  1040049Ch/1040059Ch - V-IRQ?                    ;000h       ;-V?
  1040049Eh/1040059Eh - H-IRQ-1 start             ;192h       ;-H
  104004A0h/104005A0h - Unused (0's)
Re: 3DS reverse engineering
by on (#242390)
If you want to have a good laugh, here is my description of the eight interrupt modes. If that description makes perfect sense to you then you have a much better understanding of the hardware than myself.
Code:
10400474h/10400574h - Interrupt Type
  0      Display Enable (should be 1) (0=Off/screen fades out, 1=On/normal)
  1-7    Unused (0)
  8-10   Interrupt Mode (5=OncePerFrame, 7=None, 0..4,6=Special) (see below)
  7-11   Unused (0)
  16     Unknown...?    (0=???, 1=Normal)
  17-31  Unused (0)
The default is Interrupt Mode 5 (which acts as normal framerate interrupt). The
other modes are barely useful and kinda confusing (and seem to require manually
resurrecting IRQs in case of oneshot/multishot IRQs, or manually stopping IRQs
in case of unwanted endless repeating IRQs).

Interrupt Mode 0,1,2,3 in "oneshot" variant:
  - Works only when V settings are [10400504h]<=[1040059Ch]
  - If so, triggers once at V=[10400520h] and H=[1040059Eh]
  - Thereafter, no further IRQs occur (unless/until setting request.bit18)
Interrupt Mode 0,2 in "multishot" variant:
  - Works only when [1040051Ch]<[1040051Eh] and [1040059Eh]<[10400528h]
  - If so, triggers at V=[1040051Ch] and H=[1040059Eh]..[10400528h]
  - Thereafter, no further IRQs occur (unless/until setting request.bit18)
Interrupt Mode 1,3 in "multishot/other" variant:
  - Unknown, Mode 1 was also observed to have "multishot" (don't remember how)
  - (and Mode 3 might have something similar, too)
  - Mode 3 was also observed "oneshot" at V=[10400544h],and H=[10400528h]
  - And/or Mode 3 at [1040059Eh]+2(!) ;or H=[10400540h]?
Interrupt Mode 4 (endless with exclusion)
  - Same as Mode 6, but EXCLUDING triggering at H=[10400540h]..[10400542h]
Interrupt Mode 5 (framerate interrupt)
  - Triggers at V=[10400544h] and H=[10400540h] (usually H should be at Hblank)
Interrupt Mode 6 (endless)
  - Triggers at V=[1040051Ch], and H=[1040059Eh]..and up
  - IRQ's are endless repeated at all further H's (up to including next frame)
  - One way to prevent endless repeats is to set [1040051Ch]=1FFh (invalid)
  - Note: [1040051Ch] is latched somewhere (internally?)
  - (that latched value is NOT updated if [1040059Eh] is invalid)
Interrupt Mode 7 (interrupts disabled)
  - Doesn't trigger any IRQs.

For all IRQ H/V timings, mind that the display is drawn from left to right
(unlike normal top-to-bottom displays).
Note: Most of the V positions do actually trigger at V+1 (and perhaps similar
for H positions, though those are more difficult to measure).

But, one of the more recent findings might solve that mess: I was trying to set two registers to invalid values, [1040059Eh]=1FFh and [1040051Ch]=1FFh, hoping that that would stop endless repeating IRQs - and the results did depend on the write-order, ie. on which of the two registers was written first.
The new theory is that [1040059Eh] is the latch-point where changes to other registers are copied to internal registers. If that's right then IRQ modes may turn out to be much more straightforward (and all IRQs that had seemed to occur at [1040059Eh] were merely dirt effects caused by the latching).

PS. Are the Framerate and Dotclock already known for 3DS?
Asking especially because the upper screen can be used in horizontal hiresolution mode...
So I guess it must support double dotclock (or otherwise it would drop to half framerate).
Re: 3DS reverse engineering
by on (#242425)
Yes, [1040059Ch] and [1040059Eh] is the "H/V-latching-position" where most or all other registers are latched into internal registers. When setting that position to an invalid location (exceeding htotal/vtotal) then the latching will never occur - and then one can overwrite all other H/V registers (and border color, and maybe some others) by garbage values, and the screen will netherleless keep showing an intact picture (using the old latched settings).

Knowing that, I could make a bit more sense of the interrupt modes
Code:
  Interrupt Mode 0:
  - Triggers here or there depending on H/V settings
  Interrupt Mode 1:
  - Triggers at V=[10400544h], H=[10400540h]               ;irq point
  - Triggers at V=[10400504h], H=[10400528h]..[10400566h]  ;picture area
  Interrupt Mode 2:
  - Triggers here or there depending on H/V settings
  Interrupt Mode 3:
  - Triggers at V=[10400504h], H=[10400528h]..[10400566h]  ;picture area
  Interrupt Mode 4 (in selected H's)
  - Triggers at V=[1040051Ch], and H=[10400542h]..[10400540h]
  Interrupt Mode 5 (framerate interrupt, usually at H=Hblank)
  - Triggers at V=[10400544h] and H=[10400540h]
  Interrupt Mode 6 (once on every H)
  - Triggers at V=[1040051Ch], and H=any
  Interrupt Mode 7 (interrupts disabled)
  - Doesn't trigger any IRQs.
Mode 4,5,6,7 are now looking right (and do no longer require manual tweaking for stopping unwanted interrupts).
Mode 0,1,2,3 do require manually ack/request next IRQ via bit18 (or bit17) in [10400578h], of those four modes, mode 1 and 3 are looking more or less right. But I have given up on mode 0 and 2.
Mode 0-3 can have the weirdest (dirt) effects when setting "parameter A>=B in relation to C with D<E and flag X=0", making it difficult to guess what those modes were supposed to be used for.

The specs for GPU screen setup registers at 104004xxh/104005xxh are now looking okay & and I am confident that the 3ds specs in gbatek are looking better and better than some months ago; if anybody is interested: I could upload a gbatek update - or otherwise I'll keep working and upload it some months later after more findings.
Hmmmm, next it might make sense to look at the "LCD screen" registers at 10202xxxh as they are somewhat related to the above "GPU screen" registers... and maybe one of them does allow to configure the dotclock.
Re: 3DS reverse engineering
by on (#242428)
Btw. while looking at the 10202xxxh registers, the reminds me of the all-time biggest unknown 3ds thing. Most hardware components have a similar looking set of unknown registers which contain values 0C84h, 0840Ch, 480Ch, C048h on power-up, the four values are 8 bytes apart, and their R/W mask is CCCCh. What are those registers used for ???

Ie. these registers:
10102100h (20h bytes) Y2R
10110100h (20h bytes) LGYFB0
10111100h (20h bytes) LGYFB1
10202260h (20h bytes) LCD0
10202A60h (20h bytes) LCD1
10132100h (20h bytes) MVD
and maybe more

My first guess would be byte-order for RGBA values... but that would require only one 4-digit value, not four such values.
Re: 3DS reverse engineering
by on (#242437)
That LCD registers don't seem to be doing anything useful/interesting...

3DS Video LCD Registers
This seems to be an interface between GPU video output and actual LCD screens. The registers allow to control backlight brightness and to set a forced blank color. Some other registers seem to be also affect backlight brightness (or pixel brightness?); and maybe some do affect internal voltages or internal backlight PWM timings?

The bootrom error screen initializes only a few of these registers (and leaves the others at their power-up defaults). Many of the uninitialized registers seem to have no effect on the visible picture, even when setting/clearing all bits; some of them affect the brightness of the pixels or backlight (but only if CtrlFlags.bit0=1).

Code:
General LCD Control Registers
  Physical  Size R/W       Name
  10202000h 4    00070007h reportedly Parallax barrier enable (uh, in 2x3bit?)
  10202004h 4    FFFFFFFFh Whatever, should be 0A390A39h
  10202008h 4    (R)       Whatever, readonly (R) (bit0=top screen mode?)
  1020200Ch 4    00010001h Video Disable Bits (bit0/16=top/bottom disable?)
  10202010h 4    00001F0Fh Whatever, usually 00000900h
  10202014h 4    00000001h Video Enable Bit (bit0)
  10202018h 1E8h (0)       Unused (0) ?
  10202200h 600h ...       LCD Configuration for Top Screen (see below)
  10202800h 200h (0)       Unused (0) ?
  10202A00h 600h ...       LCD Configuration for Bottom Screen (see below)
  10203200h 40h  (0) ???   reportedly LCD related, in DSP area ??????

LCD Configuration for Top/Bottom Screen
  Top/Bottom Addr     Size R/W
  10202200h/10202A00h 4    00000301h CtrlFlags
  10202204h/10202A04h 4    01FFFFFFh Forced Blank Color
  10202208h/10202A08h 8    (0)       Unused (0) ?
  10202210h/10202A10h 4    000003FFh ? (default=0)    ;\
  10202214h/10202A14h 4    000003FFh ? (default=3FFh) ; darker when all zero
  10202218h/10202A18h 4    000003FFh ? (default=0)    ; (if CtrlFlags.bit0=1)
  1020221Ch/10202A1Ch 4    000003FFh ? (default=3FFh) ;/
  10202220h/10202A20h 4    000001FFh ? (default=100h) ;-
  10202224h/10202A24h 4    000000FFh ? (default=0)    ;\
  10202228h/10202A28h 4    000000FFh ? (default=0)    ;
  1020222Ch/10202A2Ch 4    000000FFh ? (default=0)    ;/
  10202230h/10202A30h 4    001F000Fh ? (default=4)    ;-
  10202234h/10202A34h 4    (0)       Unused (0) ?
  10202238h/10202A38h 4    000000FFh Last same entry in 10202400h (FFh=AllSame)
  1020223Ch/10202A3Ch 4    000000FFh ? (default=FFh)
  10202240h/10202A40h 4    000003FFh Backlight ;based on register 244h.low10bit
  10202244h/10202A44h 4    FFFFF3FFh Backlight?;LSBs: backlight? MSBs=flags?
  10202248h/10202A48h 8    (0)       Unused (0) ?
  10202250h/10202A50h 4    00FFFFFFh ? (default=0)    ;\brighter if 2nd=FFFFFFh
  10202254h/10202A54h 4    00FFFFFFh ? (default=0)    ;/(if CtrlFlags.bit0=1)
  10202258h/10202A58h 8    (0)       Unused (0) ?
  10202260h/10202A60h 4    0000CCCCh ? (default=0C84h);\
  10202264h/10202A64h 4    (0)       Unused (0) ?     ;
  10202268h/10202A68h 4    0000CCCCh ? (default=840Ch); the usual unknown stuff
  1020226Ch/10202A6Ch 4    (0)       Unused (0) ?     ; as everywhere else
  10202270h/10202A70h 4    0000CCCCh ? (default=48C0h); (eg. as in YuvToRgb)
  10202274h/10202A74h 4    (0)       Unused (0) ?     ;
  10202278h/10202A78h 4    0000CCCCh ? (default=C048h);
  1020227Ch/10202A7Ch 4    (0)       Unused (0) ?     ;/
  10202280h/10202A80h 24h  000000FFh ? (default=0)    ;-9 words (8th=brighter)
  102022A4h/10202AA4h 4Ch  (0)       Unused (0) ?
  102022F0h/10202AF0h 4    (-R-)     ? (R)            ;\initially 00h, but can
  102022F4h/10202AF4h 4    (-R-)     ? (R)            ; be FFh when screens
  102022F8h/10202AF8h 4    (-R-)     ? (R)            ;/are on?
  102022FCh/10202AFCh 4    (0)       Unused (0) ?
  10202300h/10202B00h 100h 00FFFFFFh New3DS only: LCD calibration array?
  10202400h/10202C00h 400h 000003FFh Backlight related array, used by bootrom
Re: 3DS reverse engineering
by on (#242450)
Two quick questions...

Floating point unit
The 3ds has floating point hardware, doesn't it? Is that accessed via coprocessor opcodes? What is the best document for the 3ds floating point hardware?
Oh, and slightly unrelated: nds/dsi did support integer sqrt/divide, but that feature seems to have been dropped in 3ds?

Operating system
I know that there are SVC (aka SWI) functions, but they seem to cover only stuff like thread creation. I assume that there are also OS functions for file IO and perhaps even GUI functions? I have spotted docs with command numbers or function numbers for OS functions... but how would one invoke such a function number?
A short description for getting started on using OS functions would be nice! Or some small binary and/or sample source code for something like file io.
Re: 3DS reverse engineering
by on (#242456)
nocash wrote:
Operating system
I know that there are SVC (aka SWI) functions, but they seem to cover only stuff like thread creation. I assume that there are also OS functions for file IO and perhaps even GUI functions? I have spotted docs with command numbers or function numbers for OS functions... but how would one invoke such a function number?
A short description for getting started on using OS functions would be nice! Or some small binary and/or sample source code for something like file io.

Disclaimer: I have never worked with the 3DS, but I do know how it works on the Switch, and the Switch kernel was based on the 3DS one, so they are pretty similar.

They are invoked by using the SendSyncRequest SVC (this is SVC number number 0x32 according to 3dbrew). First, you need to get the session handle for the service you want to communicate with. You can do that by calling the GetServiceHandle function on the Srv (Service Manager) service. This handle can be then used to send messages to the service by using SendSyncRequest. As the name implies, this is a synchronous request, so the calling thread will be put into wait state, and execution is resumed on that thread only when the response to your request is sent back.

Inter-process Communication (IPC) messages:

Communication with services is done with the use of messages. They store things like the command number of the function you want to call, the parameters passed to that function, and also other related information (such as possible buffers also passed to the function, handles etc). Similary, response messages are written at the same place (they overwrite the request message) and use a similar structure. This mechanism allows processes to communicate with each other on the 3DS OS.

The message that is sent to the service should be stored on the Thread Local Storage (TLS), a per-thread 0x200 bytes memory region reserved by the kernel on thread creation. The IPC message is always written at offset 0x80 within the TLS. At the server side, messages can be received by using the ReplyAndReceive SVC (this one is not normally accessible for applications, only the services should use it to reply IPC messages). ReplyAndReceive, as the name implies, is responsible for doing 2 things. First, it replies a request that was previously processed, and then it picks one incoming message on the queue for processing. If the queue is empty, then it simply waits for a message to arrive, during that time the thread will be in wait state.

The kernel is responsible for copying the request messages from the client to the server, and copying reply messages from the server to the client. They are both written at the same address (TLS + 0x80), and the reply message will simply overwrite the request message.

When SendSyncRequest returns, you're supposed to read the reply from the TLS. Normally, it will contain a result code, and depending on what you called, it may also contain more data after that. For some functions, you're also supposed to pass buffers (basically, just a address and size) on the request, where you pass large data to the function, or it can also be used by the service function to write large data that will be returned to you.

Simplified process:

To sum it up, the process is basically like this for invoking a service function:
- Call the ConnectToPort SVC, and pass on name "srv:" to get a handle for the SRV service. (You only need to do that once, you can then store the handle somewhere for later use).
- Call Srv GetServiceHandle function, using the above handle and SendSyncRequest, to get a session handle for the service you want to communicate with, writing the service name on the IPC message (that is the function parameter). The service names usually contains a `:` followed by a character that indicates privilege level. For example, `:u` stands for "user privilege". (You only need to do that once per-service).
- Call SendSyncRequest using the session handle returned from GetServiceHandle to call the desired function. The command number and parameters passed to the function should be written to the IPC message.
- After the above call returns, read the IPC message to get the response, including the result code and possibly other data depending on the function.

References:

The structure of the IPC messages is documented at:
https://www.3dbrew.org/wiki/IPC#Message_Structure
On that page, you can also find a brief explanation of sessions and ports (they are confusing, at least to me).

Documentation of the SVCs can be found at:
https://www.3dbrew.org/wiki/SVC#System_calls
The documentation is not complete however. And in a lot of cases, they are not clear about what the SVCs actually do.

Edit:

For file I/O, I believe you're looking for this service:
https://www.3dbrew.org/wiki/Filesystem_services
Re: 3DS reverse engineering
by on (#242471)
Many thanks! I had vaguely suspected that the OS services might accessed through SVC functions... but without your help I would have never guessed how that might work exactly.
Re: 3DS reverse engineering
by on (#242512)
I have found the floating point hardware. It is called VFPv2 (Vector Floating-point). The ARM DDI 0360F (ARM11 MPCore (r2p0) document contains a relative large amount of (mostly useless) information about it, and says to look at the Architecture Reference Manual for the actual floating point opcode specs; there are a lot of different reference manual versions, but I guess that they meant this version: ARM DDI 0100I ARM Architecture Reference Manual (for ARMv6 wirh VFPv2).

I've checked opcode "FMRX r0,FPSID" (aka EEF00A10h), and it does return value 410120b4h (as described in ARM DDI 0360F), that should confirm that the VFPv2 hardware does really exist on 3DS. And with FPSID.bit20=0 it is apparently what they are occasionally calling the "D variant" (with single AND double precision support).

The Fxxxx floating point opcodes are aliases for CP10/CP11 copressor numbers; CP10 used for single, and CP11 for double precision instructions. There seem to be about 100 different opcodes, but many of them are probably (hopefully) just slightly different variations of each other.
Re: 3DS reverse engineering
by on (#242531)
Now I have done the maths on the framerate timings (for bottom screen).
I might be wrong by factor 1000, but as far as I can tell it appears to be... 59.831Hz.

That's calculated from: The CP15 cycle counter increments by 11182h per frame (with cycle count units of 268.111856MHz/64).
And the display+blanking size is 19Eh*1C3h = 186714 dots per frame. So dotclock is 67.027964MHz/6 aka circa 11MHz.

The 19Eh*1C3h comes from the used hvtotal values 19Dh,1C2h (in port 104005xxh registers), which count from 0 to 19Dh and 0 to 1C2h.
Well, and that does look like a bug, if the hardware would count from 1 to 19Dh and 1 to 1C2h then it would give a more plausible framerate of 60.01Hz.
Or, as the hardware doesn't work like that, they might have wanted to use 19Dh-1,1C2h-1 as hvtotal values.
At least that's so for the bootrom error screen, I don't know if the firmware/games are using hvtotal settings closer to 60Hz, or maybe they intentionally didn't want to use exact 60Hz.

In lack of having a top screen, I didn't mind measuring its timings. My guess would be that it does always use doubled dotclock (=about 22MHz), and that the htotal value is internally doubled in lores mode, so lores 19Eh would have same timings as hires 33Ch.

EDIT: Just noticed that NDS is using 59.8261 Hz framerate... so the 59.831 Hz on 3DS looks intended and close to the NDS rate.
Re: 3DS reverse engineering
by on (#242620)
Time for identifying the peripherals. First of, here's the component list for New3DS XL/LL...
If I haven't missed some important sources... I think that this is the first-ever component list for any (New)3DS/2DS(XL) model.
Code:
New3DS LL Component List (aka japanese version of New3DS XL)
Mainboard (PCB "RED-CPU-01 SIDE B 11-1, [05: 14 071], RED-CPU-01 SIDE A")
 Chips on Side B (top side, access requires removing mainboard):
 Un  bga   CPU "1485 16, CPU LGR A, (C) 2014, Nintendo, JAPAN ARM"  ;\
 Un  bga   RAM "F JAPAN, 82MK9A9A, 7L FCRAM, 1429969, E1"           ;
 Un  6pin  MAX8570EUT+T for upper backlight "ABTJ"                  ; Side B
 Un  sqr   Wifi "ATHEROS, AR6014G-AL1C, NKY197.00B, 1422, TAIWAN"   ;
 Un  bga   eMMC "dotcode, SAMSUNG 410, KLM4G1YE0C-B301, CDA519GLN"  ;
 Un  8pin  Wifi-EEPROM I2C "408F, B347" (HN58X2408F; 1Kx8)          ;
 Un  bga   MCU "UC KTR, 423KM01, 'TK14"                             ;
 Un  bga   Powerman? "TexasInstr, 93045A4, 3CAK08W L, GI"           ;/
 Chips on Side A (bottom side, easily accessible):
 Un  16pin BQ24072 battery charger "CKP, TI 3A1, CBYS" (near ext.supply input)
 Un  6pin  power/charge? "9D" (or "06"?) (near ext.supply input)
 Un  6pin  power "635Q" (under powerman) (...maybe lower backlight?)
 Un  24pin IR?, near infra red receiver/transmitter "U8997, 3522"
 Un  16pin gyroscope? less-near infra red "IT3B,315BA1,LT425A" (like ITG-1010?)
 Un  32pin NFC Broadcom BCM20791 "20791UZ, KMLG 25, TD1430, 3976901W"
 Un  8pin  Wifi-FLASH SPI(?) "32B, 3XH, .01" (4Kx8) (near AIC)
 Un  bga   AIC "TexasInstr, AIC3010D, 3BC473W, GI" (mic/sound/touchscr)
 Un  16pin Accelerometer? near AIC and headphone "KXTKK, 40860, .3413" Kionix?
 Un  bga   TCA6416A IO Expander "PH416A, TI 46T" ;near top-screen connectors
 Other stuff:
 Xn  4pin "CA405" or so (near UC KTR, probably for RTC)
 Xn  4pin "40000, K42BY" (under atheros, probably for Wifi)
 Xn  4pin "13000, K413Y" (under cpu, probably whatever) (to near-field chip?)
 Xn  4pin "D164G" or so  (under cpu, probably whatever) (for CPU?)
 Ix  Infrared receiver/transmitter
 Pn  2pin External Power supply
 Pn  3pin External Headphone
 Pn  2pin Connector to antenna
 Pn ??pin Connector to Button board (many pins)
 Pn ??pin Connector to MicroSD slot (medium pins)
 Pn  4pin Connector to Front panel Reset button? and MIC
 Pn  4pin Connector to Front panel Home button? (4pins, only 2 wires attached)
 Pn  Connector to bottom-shell (left shoulder (8pin+shield?, only 4 wires used)
 Pn  Connector to bottom-shell (right shoulder (8pin+shld?, only 4 wires used)
 Pn  4pin Connector to NFC (rectangle under bottom screen) (only 2 wires used)
 Pn  4pin Connector to analog stick (above dpad)
 Pn  4pin Connector to bottom screen, touchscreen
 Pn  4pin Connector to bottom screen, backlight (4pin, only 2 wires used)
 Pn ??pin Connector to bottom screen, video (many pins)
 Pn ??pin Connector to top screen? ;\presumably video,backlight,cameras,sound
 Pn ??pin Connector to top screen? ; (many pins on each connector)
 Pn ??pin Connector to top screen? ;/
 Pn  1pin Goldplate as additonal connection to cartridge board GND
 Transistors/resistors/capacitors and the like
 Barcode/sticker "22946012 Q01011K N"
Battery:
 Name "Nintendo SPR-003, Rechargeable Battery, 3.7V 1750mAh 6.5Wh"
 Dotcode with text "MKH905D10"
 Back side "Li-ion 00, SPR-A-BPAA-C1"
Cartridge Slot board (PCB "(DC)17P-01, C-3, 1 '14 12")
 Pn  Cartridge Slot ("4081911")
 Pn  Connector to mainboard
 Pn  Connector to DPAD board (5pin)
 Pn  Goldplate as additonal connection to mainboard GND
DPAD board (PCB "F-KEY 01, R, ZD, HF, 4354.")
 Pn  Connector to cartridge slot board (5pin)
 Sw  Four switches (Up,Down,Left,Right)
Button board (PCB "F-7, PWB, /ABXY, /AU-C, /RED-01, CS, 01, 3814")
 Un  44pin ?? Chip "428A2, HF374, 7NU9"
 Pn  Connector to mainboard
 Pn  Connector to battery (3pin)
 Pn  Connector to rubber nibble (C-Stick) (4pin)
 Pn  Connector to shoulder (8pin)
 Sw  Six buttons (A,B,X,Y,Sel,Start)
 Sw  Front button (Power)
 Led Four Front LEDs (two single ones, and one LED-pair)
 Led Notification LED (small 4pin RGB LED? under shoulder-connector)
 ?   large 3pin thing "(M)UN"
 ?   tiny black BGA chip (about the size of an SMD capacitor) (4-8 pins?) (maybe magnet sensor?)
 Transistors/resistors and the like
 Barcode/sticker "30946012 Z0101E9 X"
Bottom Screen:
 Name "1912TSS140725, 21P4808L, B0014747QTFD" (4.18")
Top-screen unit
 black ribbon cable: to camera unit      ;outer/rear cable
 orange ribbon cable: to slider boards   ;middle cable
 orange ribbon cable: to lcd screen      ;inner/front cable
 red cable: to wifi antenna
 1x  LCD with Dotcode/sticker "LAM049M003A1, 0020S4911848"
 2x  2pin speaker's "G4830V23A" or "G4B30V23A" or so
 1x  2pin wifi-antenna (nameless pcb)
 1x  camera unit (with two pcbs, 3 cameras, and shielding, see below)
 2x  slider boards (see below)
Left slider/speaker board:
 1x  volume slider (9.8Kohm)
 1x  wires to left speaker
 1x  13pin connector to lcd screen (maybe parallax or whatever)
 1x  4pin connector to lcd screen (maybe backlight and/or whatever)
Right slider/speaker board:
 1x  3d slider (8.4Kohm)
 1x  wires to right speaker
Front facing camera board:
 two cameras, capacitors (C1..C12), FB1, FB2
Self facing camera board:
 one camera, capacitors (C1..C5), FB1, R1, Q1, D1 (ir-led?)
Case/bottom
 "(new), Nintendo, o3DS LL, (C)2014 Nintendo Made in China RED-001"
 "[MIC/KS], EC-14016, RED-RB-JPN-C0"
 "[R]007-AC0104, [T]D14-0144001, V(Ci Li-ion, (Nintendo)"
 Barcode/sticker "QJF10203741 6"

The one chip that I can't make sense of is the 44pin chip on the button board. The chip marking is "428A2, HF374, 7NU9" (whereas, "428A2" seems to be a datecode as it varies on other photos). The chip might be related to the new C-Stick (aka rubber nibble) and/or ZL/ZR buttons... but using a huge 44pin chip that purpose would be kinda overkill. Also, I don't know if older 3DS (without C-Stick) did have that 44pin chip, too?
Re: 3DS reverse engineering
by on (#242623)
Most of the peripherals are wired to the I2C busses, the I2C device list should looks somewhat like this:
Code:
I2C Devices
  id  bus:dev  service      Device description
  0   0:4Ah    "i2c::MCU"   BPTWL (aka MCU registers for DSi mode) ;\same as
  1   0:7Ah    "i2c::CAM"   Camera0? (same dev-addr as DSi cam0)   ; DSi
  2   0:78h    "i2c::CAM"   Camera1? (same dev-addr as DSi cam1)   ;/
  3   1:4Ah    "i2c::MCU"   MCU
  4   1:78h    "i2c::CAM"   ? maybe second external camera, for left or right?
  5   1:2Ch    "i2c::LCD"   ? maybe upper or lower screen?
  6   1:2Eh    "i2c::LCD"   ? maybe lower or upper screen?
  7   1:40h    "i2c::DEB"   Debug?
  8   1:44h    "i2c::DEB"   Debug?
  9   2:A6h/D6h"i2c::HID"   Debug?? addr changed from A6h to D6h in 8.0.0-18
  10  2:D0h    "i2c::HID"   Gyroscope (older version)  <-- read = FFh's ?
  11  2:D2h    "i2c::HID"   Gyroscope (newer version)  <-- EXISTS in New3DS
  12  2:A4h    "i2c::HID"   DebugPad
  13  2:9Ah    "i2c::IR"    IR  ;maybe IR transmitter/receiver? or IR camera??
  14  2:A0h    "i2c::EEP"   DebugEeprom?
  15  1:EEh    "i2c::NFC"   New3DS-only NFC (Near-field communication)
  16  0:40h    "i2c::QTM"   New3DS-only QTM (head tracking?) IO Expander!
  17  2:54h    "i2c::IR"    New3DS-only maybe C-stick and ZL/ZR.. 44pin chip??
  -   0:A0h    -            Reserved for Unknown DSi camera0 (Ext)
  -   0:E0h    -            Reserved for Unknown DSi camera1 (Self)
  -   0:40h    -            Reserved for Unknown Debug stuff or so? and QTM
  -   0:90h    -            Reserved for Unknown Debug stuff or so?

And a quick rundown on the 3DS controller inputs (and how to read them, as far as known):
Code:
  Buttons and DPAD: see port 10146000h/10146002h
  Circle Pad: Reportedly connected to Touchscreen/Sound controller?
  Power/Home buttons: see I2C MCU
  Wifi switch/slider/button: see I2C MCU (older 3DS only?)
  Volume/3D Sliders: see I2C MCU
  Accelerometer: see I2C MCU (also includes pedometer step counter)
  Gyroscope: see I2C Gyroscope
  Hinge/Shell: see GPIO
  New3DS: ZL/ZR and C-Stick: see I2C (instead of Old3DS's circle pad pro)
  DebugPad: See I2C (whatever that is)
  MIC, Cameras, IR, NFC, QTM, Charge, SD slot, ROM slot
  Old3DS: NFC reader/writer (external adaptor, instead of New3DS built-in)
  Old3DSonly?: Circle Pad Pro (second Circle Pad, +R/ZL/ZR buttons, on IR port)
  Invisible camera IR-LED (unknown how to control/test that)
  Head-tracking (unknown what that is, probably just normal camera input, maybe combined with IR-LED)
Re: 3DS reverse engineering
by on (#242636)
Questions on LCDs (and their I2C commands)
I would be glad on any info about the LCD screens, who made them, and how do their I2C controllers work? There are a bunch of characteristic details that might look familar to anyone ever having worked with similar screens...

The part numbers for New3DSXL screens are:
Code:
Bottom Screen: "1912TSS140725, 21P4808L, B0014747QTFD" (4.18")
Top-screen: "LAM049M003A1, 0020S4911848"
Part numbers for 3DS can be seen on photos (eg. on ifixit).

The bootrom's init sequence for the I2C registers:
Code:
  LCD[11h]=10h     ;whatever
  LCD[50h]=01h     ;whatever, this one done for TOP screen only
  LCD[60h]=00h     ;whatever
  LCD[01h]=10h/11h ;on/off (10h=display on, 11h=display black)


The read sequence for I2C registers is a bit uncommon. Normal I2C register reads would work as:
Code:
  I2cWriteCmd (Device, Index)
  I2cReadCmd  (Device, Data[Index])
However, the LCD chips do separate between "WriteIndex" and "ReadIndex". That is, one must write the "ReadIndex" to register 40h, and then read two bytes (the first does just contain the ReadIndex value and can be ignored, the second byte contains the desired data). As so:
Code:
  I2cWriteCmd (Device, 40h,       ReadIndex)
  I2cReadCmd  (Device, ReadIndex, Data[ReadIndex])
Reading seems to work for reading all registers at 00h..FFh. The bootrom is reading register 62h, which contains some init ready flag (01h=Ready).

Some webpage mentioned that Sharp and Hitachi had announced stereoscopic displays shortly before 3DS release, so maybe one of that companies did make the displays? The I2C chip inside of the display might be made by another company though, I don't know if Sharp/Hitachi are manufacturing their own chips or if they use third-party chips).

Oh, and the which-is-which question for the two I2C devices is now solved. Device 2Ch is upper screen, and 2Eh is lower screen (that is in 8bit notation). Datasheets do often insist on bit0 not being part of the device number, so in their language the 7bit device numbers in bit1-7 would be 16h and 17h instead of 2Ch and 2Eh. That device numbers might also help to identify the chips...?
Re: 3DS reverse engineering
by on (#242648)
Accelerometer
This is now more or less solved. The chip is said to be ST LIS331DLH, and software-wise, that seems to be correct. Ie. the register map looks as so:
Code:
LIS331DLH Accelerometer Register address map
  Name                     Type Addr  Default Comment Hex Binary
  Reserved (do not modify)   -  00-0E -         Reserved
  WHO_AM_I                   r  0F    00110010  Dummy register
  Reserved (do not modify)   -  10-1F -         Reserved
  CTRL_REG1                  rw 20    00000111
  CTRL_REG2                  rw 21    00000000
  CTRL_REG3                  rw 22    00000000
  CTRL_REG4                  rw 23    00000000
  CTRL_REG5                  rw 24    00000000
  HP_FILTER_RESET            r  25    -         Dummy register
  REFERENCE                  rw 26    00000000
  STATUS_REG                 r  27    00000000
  OUT_X_L                    r  28    output
  OUT_X_H                    r  29    output
  OUT_Y_L                    r  2A    output
  OUT_Y_H                    r  2B    output
  OUT_Z_L                    r  2C    output
  OUT_Z_H                    r  2D    output
  Reserved (do not modify)   -  2E-2F -         Reserved
  INT1_CFG                   rw 30    00000000
  INT1_SOURCE                r  31    00000000
  INT1_THS                   rw 32    00000000
  INT1_DURATION              rw 33    00000000
  INT2_CFG                   rw 34    00000000
  INT2_SOURCE                r  35    00000000
  INT2_THS                   rw 36    00000000
  INT2_DURATION              rw 37    00000000
  Reserved (do not modify)   -  38-3F -         Reserved
  Undocumented (zero)        -  40-7F
  As above with auto-increment  80-FF
And Hardware-wise...
On Old3DS it is marked ""2048, 33DH, X1MAQ", which is said to be ST LIS331DLH.
On New3DSXL it is marked "KXTKK, 40860, .3413", which might be a Kionix chip, resembling KXTIK, but with LIS331DLH-style register map & device address.

The chip is wired to the MCU, so it's I2C registers can be accessed only indirectly, through the MCU. The related MCU registers on 3dbrew are mostly left undocumented, or even mistaken as gyroscope registers ; )
The actual functions for MCU register 40h..4Fh are:
Code:
  40h          R/W  Accelerometer Mode (bit0,1) (enable/mode flags or so?)
  41h          R/W  Accelerometer I2C Index for manual read  (via MCU[44h])
  42h          R/W  Unused?
  43h          R/W  Accelerometer I2C Index for manual write (via MCU[44h])
  44h          R/W  Accelerometer I2C Dat from/to read/write (via MCU[41h/43h])
  45h,46h      R    Accelerometer Output X (lsb,msb)
  47h,48h      R    Accelerometer Output Y (lsb,msb)
  49h,4Ah      R    Accelerometer Output Z (lsb,msb)
  4Bh          R/W  Pedometer Step Count, bit0-7    ;\(for the current day)
  4Ch          R/W  Pedometer Step Count, bit8-15   ; (uh, how/which day?)
  4Dh          R/W  Pedometer Step Count, bit16-23  ;/
  4Eh          R/W  Pedometer Flags (Wr.bit0=ClearArray?, Rd.bit4=ArrayFull?)
  4Fh          R    Pedometer Array[6+N]   ;timestamp[6] and step.counts[2*A8h]
The Pedometer is some software feature in the MCU that converts the accelerometer data to step counters. Reading the Output X/Y/Z registers would be the normal way to get the accelerometer data (if enabled in the mode register). The manual read/write feature allows to view/modify I2C registers directly; for debugging/hacking purposes or so. The manual read/write seem to be done in a callback function (=not immediately after writing register 41h or 44h), and, before touching further accelerometer registers, one must wait until the callback has executed (which is indicated by MCU.interrupt.bit11).

Both Old3DS and New3DSXL have the chip on the mainboard, somewhere underneath of the bottom-screen. That (and the exact location) may be important when interpreting the accelerometer data (ie. the chip isn't parallel with the top-screen unless the case is fully unfolded).

With the pedometer feature... I guess that means that the accelerometer chip is always (or maybe optionally) battery-powered, even when the console is off?
Re: 3DS reverse engineering
by on (#242655)
Why does the accelerometer needs to be powered when power is off? The pedometer, for the purpose of Play Coins and the pre-installed statistic app "Omoide Kirokuchou", doesn't count steps when the 3DS is off. Only when it's on and in sleep mode by shutting the lid (or by using a small magnet around the A, B, X and Y buttons).
Re: 3DS reverse engineering
by on (#242657)
I just guessed so, because the chip is wired to MCU, and the MCU is itself battery powered (at least for the RTC and RAM sections), and it could have made sense to support the step counter even when powered off.
But supporting it in sleep mode only makes sense, too. I have just checked: In "off" state both supply pins of the accelerometer (pin1+14) are 0V. So yes, it isn't always on. Good to know, thanks for that detail!
Re: 3DS reverse engineering
by on (#242660)
Gyroscopes
This was a bit confusing because there are two different/incompatible gyroscope versions (with only one of them being known so far).

Old Gyroscope
The old gyroscope is described on ifixit/3dbrew. I2C Bus and Device number should be 2:D0h.
The part number is ITG-3270 (can be seen on the ifixit 3DS teardown photos; just clicking the photo links to a blurred image, but clicking on the magnification glass symbol links to hires; and there is also a text link next to the image, that does also link to hires, but in raw quality - without the colored rectangles).
For datasheets, the ITG-3200 datasheet is reportedly matching for the ITG-3270 chip. If that's true, then the register map would look as so:
Code:
  Hex Register Name Res R/W
  00h WHO_AM_I      (-) R/W Device ID (aka Who Am I) (should be 58h or 69h or so)
  15h SMPLRT_DIV    00h R/W Sample Rate Divider
  16h DLPF_FS       00h R/W DLPF, Full Scale
  17h INT_CFG       00h R/W Interrupt Configuration
  1Ah INT_STATUS    00h R   Interrupt Status
  1Bh TEMP_OUT_H    -   R   TEMP_OUT_H
  1Ch TEMP_OUT_L    -   R   TEMP_OUT_L
  1Dh GYRO_XOUT_H   -   R   GYRO_XOUT_H
  1Eh GYRO_XOUT_L   -   R   GYRO_XOUT_L
  1Fh GYRO_YOUT_H   -   R   GYRO_YOUT_H
  20h GYRO_YOUT_L   -   R   GYRO_YOUT_L
  21h GYRO_ZOUT_H   -   R   GYRO_ZOUT_H
  22h GYRO_ZOUT_L   -   R   GYRO_ZOUT_L
  3Eh PWR_MGM       00h R/W Power Management
  xxh-FFh Undocumented (unknown)


New Gyroscope
What I have found in the New3DSXL is completely different: The bus/device is 2:D2h (not 2:D0h), and the part number is "IT3B,315BA1,LT425A", and the TEMP/GYRO_OUT registers are somewhere at index 40h and up, and the WHO_AM_I register is at index 75h.
Searching for datasheets with WHO_AM_I and value 75h (or 117 decimal), there are quite a bunch...
Code:
     --> alike ICM-20608  ;16pin LGA 3xGyro+3xAccel
     --> alike ICM-20689  ;24pin QFN 3xGyro+3xAccel
     --> alike IAM-20680            ;3xGyro+3xAccel?
     --> alike ICM-20789            ;3xGyro+3xAccel?
     --> alike MPU-9250   ;24pin QFN 3xGyro+3xAccel+3xMagneto
     --> alike MPU-6000/6050    ;QFN 3xGyro+3xAccel+3xMagneto
     --> alike MPU-6555             ;3xGyro+3xAccel
     --> alike ICG-1020S  ;12pin LGA 2xGyro (only 2-axis)
     --> alike ITG-1010   ;16pin QFN 3xGyro <------ THIS looks alike New3DSXL
Most of that chips are also having a built-in accelerometer (which is a separate chip in 3DS's), so the ITG-1010 chip looks closest to the New3DSXL hardware. The register map for that chip would be:
Code:
  Hex Dec Register Name I/F  Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
  04h 04  XG_OFFS_TC_H R/W - - - - - - XG_OFFS_TC_H [9] XG_OFFS_TC_H [8]
  05h 05  XG_OFFS_TC_L R/W XG_OFFS_TC_L [7:0]
  07h 07  YG_OFFS_TC_H R/W - - - - - - YG_OFFS_TC_H [9] YG_OFFS_TC_H [8]
  08h 08  YG_OFFS_TC_L R/W YG_OFFS_TC_L [7:0]
  0Ah 10  ZG_OFFS_TC_H R/W - - - - - - ZG_OFFS_TC_H [9] ZG_OFFS_TC_H [8]
  0Bh 11  ZG_OFFS_TC_L R/W ZG_OFFS_TC_L [7:0]
  13h 19  XG_OFFS_USRH R/W X_OFFS_USR[15:8]
  14h 20  XG_OFFS_USRL R/W X_OFFS_USR[7:0]
  15h 21  YG_OFFS_USRH R/W Y_OFFS_USR[15:8]
  16h 22  YG_OFFS_USRL R/W Y_OFFS_USR[7:0]
  17h 23  ZG_OFFS_USRH R/W Z_OFFS_USR[15:8]
  18h 24  G_OFFS_USRL  R/W Z_OFFS_USR[7:0]
  19h 25  SMPLRT_DIV   R/W SMPLRT_DIV[7:0]
  1Ah 26  CONFIG       R/W - FIFO_MODE EXT_SYNC_SET[2:0] DLPF_CFG[2:0]
  1Bh 27  GYRO_CONFIG  R/W XG_ST YG_ST ZG_ST FS_SEL [1:0] - FCHOICE_B[1:0]
  23h 35  FIFO_EN      R/W TEMP_FIFO_EN XG_FIFO_EN YG_FIFO_EN ZG_FIFO_EN - - - -
  37h 55  INT_PIN_CFG  R/W INT_LEVEL INT_OPEN LATCH_INT_EN INT_RD_CLEAR FSYNC_INT_LEVEL FSYNC_INT_MODE_EN - -
  38h 56  INT_ENABLE   R/W - - - FIFO_OFLOW_EN FSYNC_INT_EN - - DATA_RDY_EN
  3Ah 58  INT_STATUS   R   - - - FIFO_OFLOW_INT FSYNC_INT - - DATA_RDY_INT
  41h 65  TEMP_OUT_H   R   TEMP_OUT[15:8]
  42h 66  TEMP_OUT_L   R   TEMP_OUT[7:0]
  43h 67  GYRO_XOUT_H  R   GYRO_XOUT[15:8]
  44h 68  GYRO_XOUT_L  R   GYRO_XOUT[7:0]
  45h 69  GYRO_YOUT_H  R   GYRO_YOUT[15:8]
  46h 70  GYRO_YOUT_L  R   GYRO_YOUT[7:0]
  47h 71  GYRO_ZOUT_H  R   GYRO_ZOUT[15:8]
  48h 72  GYRO_ZOUT_L  R   GYRO_ZOUT[7:0]
  6Ah 106 USER_CTRL    R/W - FIFO_EN - I2C_IF_DIS - FIFO_RESET - SIG_COND_RESET
  6Bh 107 PWR_MGMT_1   R/W DEVICE_RESET SLEEP - - TEMP_DIS CLKSEL[2:0]
  6Ch 108 PWR_MGMT_2   R/W - - - - STBY_XG STBY_YG STBY_ZG
  72h 114 FIFO_COUNTH  R/W - - - - - - FIFO_COUNT[9:8]
  73h 115 FIFO_COUNTL  R/W FIFO_COUNT[7:0]
  74h 116 FIFO_R_W     R/W FIFO_DATA[7:0]
  75h 117 WHO_AM_I     R   - WHO_AM_I[6:1] - (reads as 68h)
  80h-FFh Undocumented (in New3DSXL these are same as 00h-7Fh)
That looks more or less right, the outputs at 41h..48h seem to be okay, and the WHO_AM_I at 75h is okay, and 3Ah has the RDY bit set. Most others are zero, except 6Bh has bit0 set, uhm, and 00h..0Fh have non-zero values:
Code:
BD DB D1 29  9C 1D 20 67  F4 1A 8C 08  B1 71 00 00
That values are weird. The datasheet says that everything except WHO_AM_I is zero on reset - although, a few lines later, it is stating that the OFFS_TC values at 04h..0Bh are factory-programmed, so those can be non-zero, except that the High bytes at 04h,06h,08h,0Ah should be only 2bit wide, that doesn't match up with what I seeing.
For the first two bytes (BDh, DBh), I have found some old docs for clumsy RS232 gyroscopes that are stating "1 0xBD First header byte 2 0xDB Second header". Either that's just coincidence, or that two bytes are an undocumented relict from older gyro protocols.
Hmmm, and the part number, "IT3B,315BA1,LT425A" doesn't really sound like an abbreviation for ITG-1010, the IT3B might rather hint on something like the old ITG-3xxx part number. But those 4-letter chip codes are often meaningless, and, for now, ITG-1010 seems to be the best matching datasheet.
Re: 3DS reverse engineering
by on (#242663)
The GYRO X/Y/Z OUT values are signed offsets since last sample (or since last read). Ie. they are zero when the console isn't moving.
Or at least almost zero...

Even when firmly seated on a table, the LSBs are having some dirt, and only the MSBs are 00h.
That means the values are something like 00xxh+/-dirt (rather than 0000h+/-dirt, which would result in MSB=00h/FFh).

Are there calibration offsets in the 3DS filesystem files that could help to get rid of the 00xxh errors?
Otherwise software could try to auto-calibrate itself.
Or prompt users for manual calibration.
Or simply ignore values close to 0000h (but that might badly hurt resolution for slow movements).
Re: 3DS reverse engineering
by on (#242664)
nocash wrote:
The GYRO X/Y/Z OUT values are signed offsets since last sample (or since last read)
Digital gyroscopes give a direct measurement of the rotational velocity ω (often in radians/second, but I've seen others). If you have access to a physical phonograph turntable (or anything else with a predictable rotational velocity), you should be able to figure out the units you're getting.
Re: 3DS reverse engineering
by on (#242681)
Ah, I was thinking that the values were similar as for mouse reads (where you get a "distance" since last read). And I would have thought that gyroscopes are also measuring offsets to initial direction, or offset to most recent direction?
But, well, if it is a "rotation speed" value, then one would need to compute the angle since last read based on the time since last read:
Code:
  angle_offset = rotation_speed * time
On the other hand, if reading is done at a constant rate, then one could just declare it as:
Code:
  angle_offset = rotation_speed
and eventually multiply it by a general-purpose constant that contains the fixed time value, and any adjustments for number of fractional bits, and whatever conversions between rotations/radians/degrees.

Yeah, a turn table with 33rpm might help. Or just displaying an arrow or compass needle on the screen, and then tweaking the software to keep it always pointing in one direction. I am wondering how long it could maintain that direction?
For example, if it were told to point "north", and gets turned a bunch of times back and forth, and if there are conversion errors, rounding errors, and calibration errors... I guess that it would quickly forget where "north" was exacly. Or are those digital gyros more reliable than I think?

If it does also forget what is "horizontal" and what is "vertical", that might be even more confusing. And possibly difficult to recalibrate that on the fly... it might work only by guessing if the user is currently holding the console in horizontal orientation.

Getting back to how a mouse input is working: I am just wondering if gyro input could benefit from things like double-speed-threshold.
Re: 3DS reverse engineering
by on (#242682)
New3DS 16bit IO Expander (aka QTM)
I2C Bus/device 0:40h goes to a 16bit IO Expander (aka a 16bit gpio, aka TCA6416A chip). The I2C registers are:
Code:
16bit IO Expander I2C Registers (I2C Bus/Device: 0:40h)
  00h Input Port 0                    (R) (reset: var, reads as 05h on New3DS)
  01h Input Port 1                    (R) (reset: var, reads as 00h on New3DS)
  02h Output Port 0                   (R/W) (reset: FFh)
  03h Output Port 1                   (R/W) (reset: FFh)
  04h Polarity Inversion 0            (R/W) (reset: 00h=normal)
  05h Polarity Inversion 1            (R/W) (reset: 00h=normal)
  06h Configuration (aka Direction) 0 (R/W) (reset: FFh=input)
  07h Configuration (aka Direction) 1 (R/W) (reset: FFh=input)
  08h..FFh Reserved                   (-)   (FFh)
As for what the registers are used for. I could only do some far fetched guesses...
3dbrew says that the device is for QTM (that, I couldn't guess what QTM stands for).
There are some hints on QTM being related to head-tracking (whatever that is, and whatever it is good for).
The 16bit gpio itself is unlikely to be capable of head-tracking.
And I haven't spotted any other head-tracking-dedicated hardware in the component list.

So the guesses are:
Head-tracking is done by interpreting the camera input on the ARM processors, perhaps assisted by the camera's IR LED.
Head-tracking result might be passed to the parallax barrier of the stereoscopic screen, perhaps using the IO Expander chip.
Could that be right, or is it all nonsense from scratch up?

If anybody (with working top-screen) wants to verify the parallax theory:
One could output red/blue pixels for left/right eye, and then try to change the light direction using the IO expander bits.
Maybe best done with a high backlight setting, so that the screen would act as a two-color torch.
One of the IO Expander bits might also affect the IR LED, though that might be only visible when having a suitable IR receiver.

Oh, and one extra oddity: The IO Expander is wired to the I2C bus for DSi devices, and the DSi did assign the same device number to some sort of unused/debug hardware.
If any DSi titles are actually accessing that device, then all kinds or weird effects might happen in software or on hardware : )
Re: 3DS reverse engineering
by on (#242683)
nocash wrote:
just displaying an arrow or compass needle on the screen, and then tweaking the software to keep it always pointing in one direction. I am wondering how long it could maintain that direction?
For example, if it were told to point "north", and gets turned a bunch of times back and forth, and if there are conversion errors, rounding errors, and calibration errors... I guess that it would quickly forget where "north" was exactly.
The physics works out such that you can directly measure acceleration and rotation rate as an intrinsic property of a material. (Rotation rate can be measured by having two single-axis accelerometers at a fixed separation; the common mode tells you the bulk acceleration, the differential term along the axis of the separation tells you the centrifugal force and so tells you the rotational rate)

Quote:
Or are those digital gyros more reliable than I think?
A single integration (i.e. the summation you're implying) is reasonably accurate, but yes it will still drift with time. In contrast, the double integration needed to calculate position from acceleration is almost unusable given real-world measurement error.

Quote:
If it does also forget what is "horizontal" and what is "vertical", that might be even more confusing. And possibly difficult to recalibrate that on the fly... it might work only by guessing if the user is currently holding the console in horizontal orientation.
My understanding is that dead reckoning works reasonably well, but not by simply integrating the outputs but instead finding moments when the total acceleration is approximately equal to 9.8m/s² and hasn't changed significantly recently.
Re: 3DS reverse engineering
by on (#242694)
lidnariq wrote:
finding moments when the total acceleration is approximately equal to 9.8m/s² and hasn't changed significantly recently.

Oops, I was so focused on the gyroscope-direction that I forgot about the accelerometer, and that the accelerometer can measure gravity.
Re: 3DS reverse engineering
by on (#242761)
AIC chip (Touchscreen/Sound)
I am a bit stuck with the AIC chip. The overall chip is just a customized TSC2117 (similar to that used in DSi).
On 3DS, it does reportedly additionally include the Circle Pad analog inputs, is it already known how to read that inputs?
And how to activate the microphone input (probably simple, but I think it's still unknown how to do that, even on DSi)?

Touchscreen calibration on 3DS isn't clear to me.
For 3DS mode: Is there a calibration file?
For NDS/DSi mode: The calibration data for 256x192pix NDS screens is in Wifi-Flash, but how does that translate to the 320x240pix 3DS screens...?
Does the 3DS display NDS games in a small 256x192pix window? Or does it stretch them to 320x240pix size? Or does it allow either one optionally?

Some small findings...
The 3ds touchscreen registers seem to be compatible with DSi, although some registers seem to have different power-up values.
Registers TSC[3:2Ah..45h] should theoretically contain the current ADC values, but, on both DSi+3DS, they seem to be always-zero, so one could read the data only via the ringbuffer (unless there is some way to enable the always-zero registers?).
Register TSC[0:0Dh] seems to be completely unused in existing DSi code, however, it looks as if the undocumented TSC[0:0Eh] register is serving a similar function.
And I should really update gbatek with some flowcharts for touchscreen init & dsi-to-nds-mode-switch functions (and remove some very outdated stuff that was written before finding the TSC2117 datasheet).

PS. And of course everything about the Mini-DSP instruction set is unknown, I don't even know if the DSi/3DS hardware does really implement that feature; I don't think that any DSi software is using it.
Re: 3DS reverse engineering
by on (#242878)
nocash wrote:
Does the 3DS display NDS games in a small 256x192pix window? Or does it stretch them to 320x240pix size? Or does it allow either one optionally?

it allows both display modes, iirc you can get the native-size mode by pressing SELECT while booting a DS game, otherwise the default mode is fullscreen.


also, speaking of the touchscreen controller thing

that thing is way interesting. I wonder if there's a way to extract the microcontroller firmware or whatever?

I wondered about the miniDSP thing, but turns out the instruction set isn't public, and all TI provides is some lego-brick type building software for building audio processing flows, and it's not even a free download so if you're gonna ask for it you better be a serious company with actual plans to get a serious product into production so they will consider your "US Government Export Request" seriously.

couldn't find a download on another site either, all I can find is some dumb 'informer.com' scam site invading the search results by pretending to have every related file, but they ask you for an email address, only to send you an email telling you that 'muh we dont have the file'.

so, beh.
Re: 3DS reverse engineering
by on (#242905)
Arisotura wrote:
it allows both display modes, iirc you can get the native-size mode by pressing SELECT while booting a DS game, otherwise the default mode is fullscreen.
Good to know, reminds me of this wiki sentence "Like DS gamecards, holding down start+select while starting the dsmode dlplay client will disable stretching the screens." Until now I couldn't make much sense of it, because, in my experience, DS-carts don't stretch themselves... but now, I guess DS-carts-in-3DS-consoles might do so.
8bit carts on GBA did also allow stretching, including toggling that feature on/off during gameplay, but that's probably impossible with DS titles on 3DS because it would also require to toggle the touchscreen calibration points during gameplay (or unless the AIC chip could automatically scale the ADC values).

Arisotura wrote:
also, speaking of the touchscreen controller thing
that thing is way interesting. I wonder if there's a way to extract the microcontroller firmware or whatever?
Yes, seeing the touch/microphone hardware changing from "A/D converter" (DS) to "fully-fledged sound studio and built-in A/D converter" (DSi) was quite interesting, if not to say scary.
I don't know if there's a firmware in it, or if it's plain logic. The 4Mbit/s SPI write speed suggests that the data goes directly into hardware registers without software processing (or it's stored in a register array, and changes are later processed by software at slower speed). There are some "slow" events (like soft-reset completion for coefficient ram, and programmed-gain reached flags), maybe that parts are handled by software, or they might be done by dma-memfill and hardware counters.

Arisotura wrote:
I wondered about the miniDSP thing, but turns out the instruction set isn't public...
Yeah, getting specs or just a sample binary seems to be difficult. And, it isn't yet confirmed if the DSi/3DS is even having any DSP instruction RAM at all. As far as I remember reading that memory just returns zeroes. Though it might be actually zeroflled upon reset... I don't remember if I have ever tried to write to that memory.

Microphone (tested on DSi) (but 3DS should be very similar)
Rev-engineering that kind of hardware isn't so attractive, the incoming data is just random noise/sound, making it impossible to test if the data is correct. The things that can be tested are timings for Status Flags, IRQs, and DMA, which isn't so much fun to do, either. But I think I've now tested and solved almost all relevant stuff... and then... I can finally remove the chapter about the DSi's Unknown ARM7 Registers in gbatek : )

First of, the flowchart for (un-)muting the microphone (assuming that the Launcher had already initialized other TSC registers for things like PLL timings):
Code:
mic_enable:
 TSC[1:2Eh]=03h   ;MICBIAS=AVDD
 TSC[0:51h]=80h   ;ADC Digital Mic, on
 TSC[0:52h]=00h   ;ADC Digital Volume Control Fine Adjust, unmute
 TSC[1:2Fh]=37h   ;MIC PGA=27.5dB (eg. as used by SystemSettings/MicTest)

mic_disable:
 TSC[0:52h]=80h   ;ADC Digital Volume Control Fine Adjust, mute
 TSC[0:51h]=00h   ;ADC Digital Mic, off
 TSC[1:2Eh]=00h   ;MICBIAS=Off

And then, ARM registers are working as...
Code:
4004600h - DSi7 - MIC_CNT - Microphone Control (can be 0000E10Fh)
  0-1   Data Format    (0=TwiceSame, 1=SimilarAsNormal, 2=Normal, 3=None) (R/W)
  2-3   Sampling Rate  (0..3=F/1, F/2, F/3, F/4)                          (R/W)
  4-7   Unused (0)                                                          (-)
  8     FIFO Empty     (0=No, 1=Empty)           ;0 words                   (R)
  9     FIFO Half-Full (0=No, 1=Half-Full)       ;8 or more words           (R)
  10    FIFO Full      (0=No, 1=Full)            ;16 words                  (R)
  11    FIFO Overrun   (0=No, 1=Overrun/Stopped) ;more than 16 words        (R)
  12    Clear FIFO     (0=No change, 1=Clear)    ;works only if bit15 was 0 (W)
  13-14 IRQ Enable     (0=Off, 1=Same as 3, 2=When Full, 3=When Half-Full)(R/W)
  15    Enable         (0=Disable, 1=Enable)                              (R/W)
The Sampling Rate depends on the I2S frequency in SNDEXCNT.Bit13,
  I2S=32.73kHz --> F/1=32.73kHz, F/2=16.36kHz, F/3=10.91kHz, F/4=8.18kHz
  I2S=47.61kHz --> F/1=47.61kHz, F/2=23.81kHz, F/3=15.87kHz, F/4=11.90kHz
The Sampling Rate becomes zero (no data arriving) when SNDEXCNT.Bit15=0, or
when MIC_CNT.bit0-1=3, or when MIC_CNT.bit15=0, or when Overrun has occurred.
The Sample Data tends to be 0000h or FFFFh if the microphone related
TSC-registers aren't unmuted.

4004604h - DSi7 - MIC_DATA - Microphone Data (R)
  0-15  Signed 16bit Data     ;\16 words FIFO, aka 32 halfwords
  16-31 Signed 16bit Data     ;/
MIC_DATA can be read by software, or via NDMA (with startup mode 0Ch and
Blocksize 8 words).

The "TwiceSame" data format converts the incoming mono data to stereo (ie. data bit0-15 and bit16-31 will contain the same value; and, accordingly, the 16-word fifo will get full twice as fast).
The two other data formats are storing separate mono samples in bit0-15 and bit16-31. I don't know yet if the lower/upper halfword contains the first or second sample though, or maybe either one is supported... it could be tested when recording a sine- or sawtooth-wave.
So far, the data seems to be always signed 16bit. But the launcher does also contain some code for handling unsigned data, maybe there is a TSC register that can switch to unsigned mode (and, hmm, TSC[0:1Bh] seems to support non-16bit data, however that would end up on ARM side).

Overrun Caution: If data isn't read fast enough then the Overrun flag will get set, and FIFO updates will be stopped. At that point one can still read the remaining 16 words from the FIFO, but no further words will be added to the FIFO, until clearing the FIFO and Overrun flag via MIC_CNT.bit12 (which requires bit15=0 before setting bit12).

For SNDEXCNT, one new detail is that the Mute flag (whatever that is) it doesn't affect microphone. And, the I2S frequency can be changed only if SNDEXCNT.bit15 is (or was?) 0. The exact two frequencies are supposedly 33.513982MHz divided by either 400h, or 2C0h.
That SNDEXCNT stuff might be different on 3DS... I don't know know if the 3DS has an equivalent to SNDEXCNT at all... maybe one of the "CODEC" registers?

Oh, and, if I remember correctly... I think the microphone could be also routed to the Teaklite processor. That's probably still totally unknown how it works... unless wwylele has already figured out that part?
Re: 3DS reverse engineering
by on (#242920)
And the last three peripherals - those are unfortunately not so easy to figure out, even when having official datasheets...

NFC - Near-Field Communication (New3DS)
Bus/device 1:EEh. The chip used here is apparently a Broadcom BCM20791, there is a datasheet for it, but it's covering only electrical stuff, not the I2C bus protocol. That protocol appears to be a standarized thing called "NFC Controller Interface (NCI)" from the "NFC Forum", which is one those non-profit organizations not shy of charging $600 for a copy of the protocol specifications.
Homebrew specs, or any leaked details form the official specs might help... or, otherwise... there are several open-source implementations for BCM20791, and for NCI in general. But it would require some rev-engineering work to find the relevant source files, and to extract the actual protocol from the source code.

C-Stick and ZL/ZR-buttons (New3DS)
This is probably Bus/device 2:54h. And probably wired to the huge 44pin chip on the button-board. Trying to write index + read data from that device does return mostly FFh bytes, with some random bytes here and there (regardless of the written index byte), perhaps a few more random bytes when pressing the ZL/ZR-buttons (but I am not really sure on that).
If the chip is really just there for the stick+buttons then the protocol is probably very simple, but one would need to look at the official firmware driver's code to figure out how it works.
3dbrew is associating device 2:54h with some kind of IR:rst service, but I guess that's just a backwards-compatibility thing (the Old3DS did have a similar add-on (called Circle Pad Pro) attached to the IR port).

Infra-Red IrDA/SIR
Bus/device 2:9Ah, seems to use a SC16IS740/750/760 chip, containing UART and IrDA/SIR hardware. The datasheet does almost exclusively describe the UART part, and barely mentions IR at all. I guess the IR mode does basically redirect the UART RX/TX signals to the IR receiver/transmitter, presumably with "pulsed" signals instead of constant HIGH or LOW levels. In so far it would be simple to use (ecept, maybe needing additional error handling, and possibly needing software handshakes if RTC/CTS are left unimplemented in IR mode).
The more complicated part is that the official IrDA implemention does supposedly consist of a more complex protocol (reportedly available for $100 upwards, but, as for NFC, one can probably find open source code for free). I don't know if Nintendo had bothered to use the official IrDA protocol though, also possible that they have just used a custom protocol for their add-ons.
The overall purpose on Old3DS is using the IrDA hardware to access the external NFC reader and Circle Pad Pro add-ons. The New3DS does have that add-ons built-in, so the IrDA chip is becoming rather useless on New3DS... unless it's still used for other things?
IrDA as such appears to be limited to short-range transfers of 20cm - 100cm range, and to some sort of binary data... so it's probably not suitable for implementing things like classic TV remote controls.
Re: 3DS reverse engineering
by on (#242940)
NCI Technical Specification
Re: 3DS reverse engineering
by on (#242949)
Cool, that's interesting... hmmmm... but it doesn't really match-up with the few details that were thought to be known about the new3ds hardware...

On 3dbrew, the NFC is called "Device 15", https://www.3dbrew.org/wiki/I2C_Registers#Device_15 going by that, I2C command/responses should consist of a 4 byte header, followed by 0-255 byte data.
After power-up, I have noticed that the NFC chip sends six bytes on I2C bus: 10 60 00 02 00 01, then followed by endless FF-bytes. That's apparently some power-up/status message, with 4 byte header and 2 byte data.

In the pdf I couldn't spot anything mentioning those 4 byte headers. At best it seems to describe roughly similar 3 byte headers.
Looking at some source code, https://android.googlesource.com/kernel ... 079x-i2c.c it seems that there can be both 3 byte "HCI headers" and 4 byte "NCI headers" (whatever that is good for).

And, I guess there must be at least two protocols envolved, one for the I2C bus commands, and one for the actual wireless transmissons. So trying to use the specs for the wrong protocol might screw up everything. The pdf does mention I2C bus though, so it should theoretically cover the 4 byte headers that are used on new3ds I2C bus.

And, the chip manufacturer might have added yet another custom protocol (or at least few custom commands), eg. for the firmware update/patch feature.