3DS reverse engineering

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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,
diag3ds.ZIP
(70.41 KiB) Downloaded 282 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.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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?
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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: Select all

  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)
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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: Select all

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).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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: Select all

  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.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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: Select all

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
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
gdkchan
Posts: 14
Joined: Tue Jun 21, 2016 2:43 pm

Re: 3DS reverse engineering

Post by gdkchan »

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
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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.
Last edited by nocash on Sat Oct 12, 2019 1:39 am, edited 1 time in total.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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: Select all

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?
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

Most of the peripherals are wired to the I2C busses, the I2C device list should looks somewhat like this:

Code: Select all

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: Select all

  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)
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1405
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: 3DS reverse engineering

Post by nocash »

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: Select all

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: Select all

  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: Select all

  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: Select all

  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...?
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
Post Reply