3DS reverse engineering

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

Re: 3DS reverse engineering

Post by nocash » Wed Apr 08, 2020 1:21 am

I've checked the write-ability of the L2C Debug/Prefetch/Power control registers again, the ignored writes seen in my R/W tester were caused by the preceeding write to L2C_UNLOCK_WAY. If that unlocking stuff is busy then all writes to any L2C register seem to be ignored (eg. L2C_INT_MASK writes are ignored, too). Regardless of unlocking, writes to the L2C_ADDR_FILTERING_START/END registers are still ignored (ie. they are really not implemented).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Thu Apr 09, 2020 7:28 am

I've had a closer look at the unstable GBA ROM-image data. About 99% of memory reads are returning data from address+20h (within 800h-byte pages). And about 1% are randomly returning data from address+0. There must be some burst read or prefetch going on, and one does apparently need to disable that somehow in GBA mode.

The only known FCRAM related register seems to be Port 10141210h aka CFG11_GPU_FCRAM_CNT. I am not sure if it is actually GPU related, but it does have some effect on FCRAM. Setting the lower 2bit to anything other than 3 seems to hang the ARM11 when trying to read or write FCRAM. Bit2 is usually set, but in some cases it's cleared (that seems to depend on the old and newly written value in the lower 2bit).

Messing with that register doesn't have any positive (or negative) effect on GBA mode though. Or maybe it needs to be combined with another register (would be interesting to see a disassembly of the official code for using that register).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Sat Apr 11, 2020 2:03 pm

A bunch of small details...
CDMA 01h is NTRCARD on ARM11 side
Interrupt 44h is NTRCARD on ARM11 side
Interrupt 5Bh is HID PAD IRQ alike KEYCNT on GBA/NDS
CFG11_MPCORE_CNT.bit0 is memory enable for New3DS extra VRAM/QTM at 1F000000h (or whatever it is called).
CFG9_EXTMEMCNT9.bit0 is confirmed to be memory enable specifically for New3DS extra ARM9-RAM at 08100000h.
Port 1014010Ch can be called CFG11_CDMA_CNT (bit0/bit1 enable CDMA 00h/01h accordingly, bit4/bit5 are still unknown).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Sat Apr 11, 2020 2:23 pm

And, I have looked into starting the three other ARM11 CPU cores...

The bootrom overlay for changing the CPU2/3 entrypoints works as so:

Code: Select all

10140420h - New3DS - CFG11_BOOTROM_OVERLAY_CNT (R/W)
  0     ARM11 Bootrom Overlay Enable (0=Disable, 1=Enable)
  1-31  Unused (0)
When enabled, opcode/data reads from physical(?) address 00010000h-00010FFFh
and FFFF0000h-FFFF0FFFh will return following values:
  Opcode reads --> E59FF018h    (opcode LDR PC,[$+20h]
  Data reads   --> [10140424h]  (CFG11_BOOTROM_OVERLAY_VAL)
This is intended for redirecting the CPU2/3 reset vectors, however, it does
also affect all other exception vectors, including for CPU0/1 (so one should
usually disable IRQs while having the overlay enabled).
See CFG11_MPCORE_BOOTCNT_CPU2/3 for details on starting CPU2/3.

10140424h - New3DS - CFG11_BOOTROM_OVERLAY_VAL (R/W)
  0-31  ARM11 Bootrom Overlay Data (aka CPU2/3 entrypoint)
Note: For redirecting to different entrypoints for CPU2/3, one can use opcode
EE10nFB0h (mov Rn,p15,0,c0,c0,5) to obtain the current CPU number.
The "LDR PC,[$+20h]" effect can be seen when jumping to 10FE0h..10FFCh (with CP15 Control register bit13 changed to use the low vectors). The "LDR PC,[$+20h]" will then read garbage/opcodes from 11000h..1101Ch as jump target, and thus trigger a prefetch abort with the garbage/opcode value (+4) in LR register.

And the mechanisms for starting/stopping the CPU cores...

Code: Select all

10141310h - New3DS - CFG11_MPCORE_BOOTCNT_CPU0 (R)
10141311h - New3DS - CFG11_MPCORE_BOOTCNT_CPU1 (R)
  0-7   Fixed (always 30h, even when executing WFI opcode)                  (R)
These are readonly dummy registers, somewhat indicating that CPU0/1 do exist
and that they were already started (of which, CPU0 is actually running code,
and CPU1 is initially hanging in a bootrom waitloop; which waits for FIRM code
to send software interrupt 01h via Port 17E01F00h, and then jumps to
[1FFFFFDCh]).

10141312h - New3DS - CFG11_MPCORE_BOOTCNT_CPU2 (R/W)
10141313h - New3DS - CFG11_MPCORE_BOOTCNT_CPU3 (R/W)
  0     Start/Stop CPU core         (0=Stop upon WFI, 1=Start/Enable)     (R/W)
  1     Must be 1 when starting CPU (0=Hangs when setting bit0, 1=Works)  (R/W)
  2-3   Unused (0)
  4     CPU started                 (0=No, 1=Yes, bit0 is/was set)          (R)
  5     CPU not in WFI state        (0=Executes WFI opcode, 1=Normal)       (R)
  6-7   Unused (0)
Starting CPU2/3 must be done with CFG11_BOOTROM_OVERLAY_CNT/VAL (the default
reset vector in ARM11 bootrom doesn't support booting CPU2/3).
Bit0 enables CPU2/3 (and alongsides enables corresponding registers at
17E00900h/17E00A00h).
Bit1 must be set alongsides with bit0 (otherwise the CPU hangs somehow), once
when the CPU is started, toggling bit1 won't affect the CPU operation; clearing
bit1 is commonly done to notify CPU0 that the CPU has started.
Note: When starting/stopping CPU2/3, one should also notify the hardware about
the new state (via Port 17E00008h, SCU CPU Status Register).
I am not sure what bit1 is supposed to do (apart from needing to be set while setting bit0). Other than that, I hope that I got the descriptions right. Notably, none of the BOOTCNT bits seems to enable/disable the ROM overlays (which are solely controlled by the OVERLAY registers).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Sun Apr 12, 2020 11:17 am

Tracked down four more IRQs, they were already known to be Gamecard related, but it wasn't too clear how exactly (and that the two ARM9 IRQs appear to be identical to the two ARM11 IRQs).

Code: Select all

10000012h - CFG9_CARD_INSERT_DELAY (usually 1988h = 100ms) (R/W)
10000014h - CFG9_CARD_PWROFF_DELAY (usually 264Ch = 150ms) (R/W)
Same as 4004012h/4004014h on DSi, see DSi SCFG registers for details.
  0-15  Delay in 400h cycle units (at 67.027964MHz)  ;max FFFFh=ca. 1 second
There are related IRQs on ARM9 and ARM11 side (CGC aka Change Gamecard or so):
  ARM9 IF.bit25, and ARM11 Interrupt 74h   ;at begin of PWROFF delay
  ARM9 IF.bit26, and ARM11 Interrupt 75h   ;at end of INSERT delay
Apart from "inserting", insert does also trigger on power-up (if a card was inserted).
Apart from "manually powering off", power off does also trigger on eject (if the card was powered on).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Sun Apr 12, 2020 1:45 pm

And yet two more interupts...
Interrupt 4Fh is for Port 10207xxxh (aka MVD movie decoder, or whatever it is)
Interrupt 5Fh is for Port 10170xxxh (aka MP multiplayer, aka old NDS-Wifi registers)
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Sun Apr 19, 2020 4:59 am

My next long-term goal is trying to "draw a triangle" using the GPU. That doesn't look so easy, but I guess/hope that it could be solved in 1-2 weeks.
One obstacle are the various parameters for color buffer, frame buffer, view-port etc.
The other obstacle are the geometry shaders and vertex shaders.
My current understanding is that one must write vertices to the vertex shader (and use a vertex shader program for forwarding the vertices to the drawing engine).
And the geometry shader... my latest findings are that is completely unknown how to use that thing, but drawing works without using the geometry shader, so one could ignore that problem for now.

Anyways, before using the GPU, the first issue is Defining floating point numbers in source code. There is some sort of standard for 32bit, 64bit, and 80bit floating point numbers in 80x86 asm language, using normal data directives and a dot symbol to indicate floating point instead of integer format:

Code: Select all

  dd 1.0       ;32bit float1.8.23 (4byte aka doubleword)
  dq 1.0       ;64bit float1.11.52 (8byte aka quadword)
  dt 1.0       ;80bit float1.15.64 (10byte aka tenbyte)
But the GPU does need other sizes, with 16bit, 24bit, or (in few cases) really weird sizes of 20bit or 31bit:

Code: Select all

  float1.5.10  (16bit)
  float1.7.12  (20bit)
  float1.7.16  (24bit)
  float1.7.23  (31bit)
  float1.8.23  (32bit)
For the 20bit and 31bit formats, I would tend to say that they don't deserve to be supported by the assembler...

For 20bit, one could use 24bit, and then use the ARM cpu to right-shift the value to make it 20bit.
For 31bit, one could left-shift 24bit, or, if better precision is needed, use 32bit and modify the sign/exponent bits.

So, one would only need three native types, that could be defined as so:

Code: Select all

  dw   1.0     ;16bit float1.5.10 (2byte aka word)
  d??? 1.0     ;24bit float1.7.16 (3byte aka whatever???)
  dd   1.0     ;32bit float1.8.23 (4byte aka doubleword)
Are there any (semi-)standard directives for defining 24bit data values?
If not, I could brew up my own (non-)standard directive... in the no$sns snes assembler, I've used "df" for 24bit Far pointers. My current idea would be to re-use "df" for 24bit Float numbers... unless there are better suggestions for more-standard-like directives (but it should be compact, something like ".define_generic_data %value=1.0, %type=float, %unit=24bit" would be a bit long).

There are a few corner cases for GPU numbers:

24bit floats are often stored in 32bit numbers (with upper 8bit unused/zero). It would be nice to have a directive for that... but it's probably easier to define them as 24bit number, and then append a "db 00h" padding byte.

16bit floats are often merged with another 16bit float (or fixed point) number. To define that as 32bit number, one would need something like "dd (float16)*10000h+(float16)*1". But it's easier to use two "dw" lines.

Finally, there's at least one really weird case with a 16bit float value split into 8bit halves, with each 8bit half stored in a different register. That would require something like "(float16) AND 0FF00h". But it's easier to use a "dw" line to store the whole 16bit number, and then use ARM code to mess around with the 8bit halves.

Bottom line is that the assembler needs to support data directives for 16bit, 24bit, 32bit float numbers... and all other corner cases could be dealt with ARM code in software.
Or did forget some important must-have assembler features?
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Fri Apr 24, 2020 6:51 am

So here is one of the assholes with a few hints because i don't want to be an asshole-asshole:

GBA mode fully working:
https://github.com/profi200/open_agb_firm

GPU init needs this initialization cmd list to not hang at even drawing a simple triangle:
https://gist.github.com/profi200/9e1281 ... abb1680e41
The parser this output comes from: https://gist.github.com/Wolfvak/2f3e989 ... 17a8f77f0c

OpenGL-like userland lib for the GPU:
https://github.com/fincs/citro3d

Shader assembler:
https://github.com/fincs/picasso/

And a note:
I only post this because you can't realistically figure this out without help (emulators, reverse engineering) and i don't want anyone to be stuck when it has already been figured out.
I'm not doing reverse engineering for you anymore. If i do it then for documentations sake. Others pointed out to me, that you are maybe not aware you crossed a line but i want to make it clear that you did with the comment on page 15.

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

Re: 3DS reverse engineering

Post by nocash » Fri Apr 24, 2020 2:03 pm

This thread is about sharing new information about the 3ds hardware. The 3dbrew wiki is an important resource, and I am sure that the 3dbrew authors would agree on saying that most of their hardware specific documentation is still far from complete. I can hardly complain about that. One thing that I can complain about is that some pages are looking as if the authors might have known than what they have written, for example, simple details like saying "this is a mask bit" without telling if "1" means "on" or "off". It's possible that they just didn't knew, didn't have time to go more into detail, or just didn't mind telling. Either way, I am taking the freedom to say that such missing details can be frustating to me. I have managed to get contact details for a few of the wiki authors, and they are usually glad to help and to share additional info that is missing on the wiki pages.

Concerning your posts, I can't remember that you have ever posted any useful information without poisonous thorns and sidekicks, as if you can't share info withoiut telling people that they should have known that themselves, and without pointing out that there are much more clever people. I don't know if you were doing that intentionally, but I usually felt like being smeared with dirt, while at the same time feeling obliged to admit that some of your comments were helpful. I have mostly tried to ignore your negative energy, and to keep focusing on actual reverse engineering. The post where I was expressing frustations about abbreviations wasn't against you personally. But if it could keep you from posting unfriendly comments in this thread... that wouldn't be the worst thing to happen.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Fri Apr 24, 2020 3:55 pm

nocash wrote:
Fri Apr 24, 2020 2:03 pm
This thread is about sharing new information about the 3ds hardware. The 3dbrew wiki is an important resource, and I am sure that the 3dbrew authors would agree on saying that most of their hardware specific documentation is still far from complete. I can hardly complain about that. One thing that I can complain about is that some pages are looking as if the authors might have known than what they have written, for example, simple details like saying "this is a mask bit" without telling if "1" means "on" or "off". It's possible that they just didn't knew, didn't have time to go more into detail, or just didn't mind telling. Either way, I am taking the freedom to say that such missing details can be frustating to me. I have managed to get contact details for a few of the wiki authors, and they are usually glad to help and to share additional info that is missing on the wiki pages.

Concerning your posts, I can't remember that you have ever posted any useful information without poisonous thorns and sidekicks, as if you can't share info withoiut telling people that they should have known that themselves, and without pointing out that there are much more clever people. I don't know if you were doing that intentionally, but I usually felt like being smeared with dirt, while at the same time feeling obliged to admit that some of your comments were helpful. I have mostly tried to ignore your negative energy, and to keep focusing on actual reverse engineering. The post where I was expressing frustations about abbreviations wasn't against you personally. But if it could keep you from posting unfriendly comments in this thread... that wouldn't be the worst thing to happen.
And being frustrated gives you the right to call them assholes? It's documentation from hobbyists for hobbyists. There is no professional SDK with all the infos to copy (which is illegal because of NDA's by the way).
Maybe they don't know that you called them assholes behind their back because it's extremely rude to do that and then asking them for help directly. If someone did that to me he/she would get a middle finger and nothing else.
And besides that you are copying all this information to your site exclusively undermining the efforts to keep all documentation in one place. All the diffs and credits who found what and other infos also get lost in your copy. If you think something is missing then add/correct it. And not just in your version but the original aswell. Creating an account takes not even 5 minutes.

Because your posts very often read as if you did not read the docs or even tried to find the infos yourself. For example linked you multiple times the same GitHub repos where all the infos are in one place where you can run a search on. That is also frustrating. I admit i was a bit rude for example with your source code but you must understand, that basically everything besides your stuff assumes standard ARM ABI and being usable with standard toolchains. We can't even link against your code. It neither assembles with GAS nor is it ABI compatible in many cases. That raises the question if you are doing this for yourself only or the community.
If you think my work weighs less than my negativity that is fine. I'm not gonna serve it to you on a silver platter anymore.

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

Re: 3DS reverse engineering

Post by nocash » Fri Apr 24, 2020 5:47 pm

I've uploaded no$gba and gbatek version 3.01.

http://problemkaputt.de/gba.htm

25 Apr 2020 - version 3.01
- 3ds/help: added info on arm11/arm9 bootrom 3DS Exception Vectors
- 3ds/help: added info on bootrom key generator for AES key slots
- 3ds/help: added more notes/questions on still needed unknown gpu things
- 3ds/help: more gpu notes from 3dbrew (but isn't yet understood what they mean)
- 3ds/help: ntrcard on arm11 side: triggers cdma 01h, and interrupt 44h
- 3ds/help: clarified gamecard insert/pwroff irqs on arm9 and arm11 sides
- 3ds/help: info on starting/stopping arm11 cpu1 and cpu2/3 cores
- 3ds/help: details: pad irq 5Bh, memory enable for 08100000h and 1F000000h
- 3ds/help: added specs for Level 2 Cache (L2C) registers and cache irq 76h
- 3ds/help: added specs for AXI bus matrix registers (mostly readonly)
- 3ds/help: added specs ARM7 aka GBA config registers (and guess on gba footer)
- 3ds/help: added specs for LGYFB gba/nds framebuffer converters (thanks sono)
- 3ds/help: added specs for RGB-to-RGBA converter (L2B) (new3ds mvd related)
- 3ds/help: added specs for YUV-to-RGBA converter (Y2R) (camera related)
- 3ds/help: added many details for CTRCARD registers/seed/protocol
- dsi/help: added SCFG_CARD_xxx_DELAY specs, better cart power on/off sequences
- 3ds/help: added chapter with 3DS Console IDs and ID0/ID1 folder names
- 3ds/help: added mcu reflashing specs via uart cable on tool0 pin
- 3ds/help: renamed mcu looping-queue-stack-nonsense to battery-backed-ram
- 3ds/help: added details on mcu i2c-slave devices (fuel gauge and powerman/tsc)
- 3ds/help: rev-engineered RSA and SHA register details
- 3ds/help: fixed weird IPC_SYNC aka PXI_SYNC description
- 3ds/help: added specs for VFP vector-floating-point opcodes/registers
- 3ds/help: added tsc page 64h/65h/67h/FBh register info (thanks profi200)
- gba/bios: fixed multiboot-upload crash upon too many slaves or too much data
- dsi/debug: debugmsg window displays TSC page number alongsides with TSC index
- a22i/arm: bugfixed shortform for MOV Rd,shift (other than ALU Rd,Rx,shift)
- a22i/float: added data directives .float16/24/32/64/80
- a22i/dis: fixed corelink dma reladdr for loops (unsigned, target=$-offset)
- 3ds/disass: bugfixed RL78 short addr, and "[SFR+1]" for MSBs of SFRs
- 3ds/debug: added RL78 assembler for MCU code (and RL78 opcode list in help)
- 3ds/debug: added assembler/disassembler for VFP floating point opcodes
- 3ds/debug: added assembler/disassembler for CDMA/XDMA corelink dma opcodes
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

coto
Posts: 49
Joined: Wed Mar 06, 2019 6:00 pm
Location: Chile

Re: 3DS reverse engineering

Post by coto » Fri Apr 24, 2020 6:56 pm

I think profi200 is (and has been) a good resource and helpful guy over the years, at
least from what I have been reading about 3DS stuff. (even back in 2014/2015 when I was in IRC)
And I don't recall him being poisonous or the likes.

Also I think nocash may come off as an asshole sometimes, but I think that's because he
has mostly reverse engineered a ton of stuff by himself and very few dare to correct him
or whatever. LOL

Anyway move on guys don't fight... this is just for the sake of research and development.
You both do an excellent job at what you do.

Oh, also Yellows8 and derrek (and neimod maybe??), these are like the guys who started 3DS reverse engineering back then, and these
are VERY smart people, as well. So I think all their effort is worth and helped the 3DS homebrew to what it is today.

Thought it's worth saying that.

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

Re: 3DS reverse engineering

Post by nocash » Sat Apr 25, 2020 8:30 am

Here's my attempt on triangle drawing. I think it does cover all important steps, but doesn't work. There are probably some mistakes, or wrong assumptions on the register settings, or a few missing registers, or wrong formatting/byte-order for the float values, or whatever. Getting only one detail wrong means no triangle being displayed : /

What is working is filling the color buffer via GPU_MEMFILL, and later copying it to the LCD framebuffer via GPU_MEMCOPY. One slightly interesting finding was that those steps stopped when clearing some of the unknown bits in CFG11_GPU_CNT (bit1=0 disables MEMFILL, bit4=0 disables MEMCOPY).

For the triangle, my hopes were that drawing something near coordinate 0,0 would display something on one of the screen edges, or in the screen center. But that didn't work out, there's nothing displayed.

Code: Select all

;------------------
gpu_tests:
 push r0-r12,lr
 bl   cls

       ;bl try_set_unknown_registers
       ;bl try_clr_unknown_registers

 ldr r4,=REGBASE_3DS_GPU_INTERNAL
 ldr r5,=REGBASE_3DS_GPU  ;_EXTERNAL
 mov r0,01h        // str r0,[r4,GPUREG_START_DRAW_FUNC0]  ;0=draw, 1=config?

  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
;---fill...
 ldr r0,=(MEMORG_COLORBUF+0)/10h*2         // str r0,[r5,GPU_MEMFILL_START1]
 ldr r0,=(MEMORG_COLORBUF+400*240*4)/10h*2 // str r0,[r5,GPU_MEMFILL_END1]
 ldr r0,=11441100h                         // str r0,[r5,GPU_MEMFILL_DATA1]
 ldr r0,=00000201h                         // str r0,[r5,GPU_MEMFILL_CNT1]
@@fill_lop:
 ldr r0,[r5,GPU_MEMFILL_CNT1]
 tst r0,1
 bne @@fill_lop
  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
;---rasterizer...
 mov r0,0          // str r0,[r4,GPUREG_FACECULLING_CONFIG]  ;show front+back? (or hide front+back?)
  ;xxx VIEWPORT width/height, invw/invh, xy (currently uses hw-reset defaults; which are set to 320x240)
 mov r0,2          // str r0,[r4,GPUREG_SH_OUTMAP_TOTAL]   ;vertex+color
 ldr r0,=03020100h // str r0,[r4,GPUREG_SH_OUTMAP_O+0*4]   ;vertex.xyzw
 ldr r0,=0b0a0908h // str r0,[r4,GPUREG_SH_OUTMAP_O+1*4]   ;color.rgba
  ;xxx GPUREG_EARLYDEPTH_CLEAR ... does clear WHAT? memfill the depth buffer?
 ldr r0,=(1 shl 24)+((240-1)shl 12)+320 // str r0,[r4,GPUREG_RENDERBUF_DIM]
 mov r0,3                    // str r0,[r4,GPUREG_SH_OUTATTR_CLOCK]  ;needed? or internal state?
;---framebuffer
 ldr r0,=00e40100h // str r0,[r4,GPUREG_COLOR_OPERATION]  ;?
 ldr r0,=06020000h // str r0,[r4,GPUREG_BLEND_FUNC]       ;src+zero
;mov r0,00h        // str r0,[r4,GPUREG_LOGIC_OP]      ;0=clear
 ldr r0,=00001f00h // str r0,[r4,GPUREG_DEPTH_COLOR_MASK]
 mov r0,1          // str r0,[r4,GPUREG_FRAMEBUFFER_INVALIDATE]
 mov r0,1          // str r0,[r4,GPUREG_FRAMEBUFFER_FLUSH]
 mov r0,0fh        // str r0,[r4,GPUREG_COLORBUFFER_READ]
 mov r0,0fh        // str r0,[r4,GPUREG_COLORBUFFER_WRITE]
 mov r0,03h        // str r0,[r4,GPUREG_DEPTHBUFFER_READ]
 mov r0,03h        // str r0,[r4,GPUREG_DEPTHBUFFER_WRITE]
 mov r0,03h        // str r0,[r4,GPUREG_DEPTHBUFFER_FORMAT]
 mov r0,00000002h  // str r0,[r4,GPUREG_COLORBUFFER_FORMAT]
 mov r0,00h        // str r0,[r4,GPUREG_EARLYDEPTH_TEST1] ;try this, too?
 mov r0,00h        // str r0,[r4,GPUREG_EARLYDEPTH_TEST2]
 mov r0,00h        // str r0,[r4,GPUREG_FRAMEBUFFER_BLOCK32]
 ldr r0,=MEMORG_DEPTHBUF/8 // str r0,[r4,GPUREG_DEPTHBUFFER_LOC]
 ldr r0,=MEMORG_COLORBUF/8 // str r0,[r4,GPUREG_COLORBUFFER_LOC]
 ldr r0,=(1 shl 24)+((240-1) shl 12)+(320) // str r0,[r4,GPUREG_FRAMEBUFFER_DIM]
  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS

;---pipeline...
 mov r0,((1 shl 8)+00h)  *000 // str r0,[r4,GPUREG_GEOSTAGE_CONFIG]

 ldr r0,=((0/8) shl 1)  // str r0,[r4,GPUREG_ATTRIBBUFFERS_LOC]  ;base.addr
   ;xxx GPUREG_ATTRIBBUFFERS_FORMAT_LOW]      ;\
   ;xxx GPUREG_ATTRIBBUFFERS_FORMAT_HIGH]     ; for using attribute buffers
   ;xxx GPUREG_ATTRIBBUFFERi_OFFSET+0*0Ch]    ; in memory (instead of directly
   ;xxx GPUREG_ATTRIBBUFFERi_OFFSET+1*0Ch]    ; writing FIXEDATTRIB, which seems
   ;xxx GPUREG_ATTRIBBUFFERi_CONFIG1+0*0Ch]   ; to be easier for getting started)
   ;xxx GPUREG_ATTRIBBUFFERi_CONFIG2+0*0Ch]   ;
   ;xxx GPUREG_ATTRIBBUFFERi_CONFIG1+1*0Ch]   ;
   ;xxx GPUREG_ATTRIBBUFFERi_CONFIG2+1*0Ch]   ;/
   ;xxx GPUREG_INDEXBUFFER_CONFIG]            ;-unknown (default is 80000000h)
 mov r0,03h        // str r0,[r4,GPUREG_NUMVERTICES]
   ;xxx GPUREG_FIXEDATTRIB_INDEX]             ;\for constant attributes (ie.
   ;xxx GPUREG_FIXEDATTRIB_DATA0]             ; not useful for coordinates,
   ;xxx GPUREG_FIXEDATTRIB_DATA1]             ; which differ on each vertex)
   ;xxx GPUREG_FIXEDATTRIB_DATA2]             ;/
 mov r0,02h-1      // str r0,[r4,GPUREG_VSH_NUM_ATTR]
 mov r0,00h        // str r0,[r4,GPUREG_VSH_COM_MODE]  ;GSH/VSH?
 mov r0,02h-1      // str r0,[r4,GPUREG_VSH_OUTMAP_TOTAL1]   ;needed? or internal state?
 mov r0,02h-1      // str r0,[r4,GPUREG_VSH_OUTMAP_TOTAL2]   ;needed? or internal state?
 mov r0,(00h shl 8)+(02h-1)   // str r0,[r4,GPUREG_PRIMITIVE_CONFIG]  ;triangles
 mov r0,00000001h  // str r0,[r4,GPUREG_RESTART_PRIMITIVE] ;trigger restart
  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
;---shader...
 .if 01  ;try GSH too
   ldr r0,=(0a0h shl 24)+02h-1 // str r0,[r4,GPUREG_GSH_INPUTBUFFER_CONFIG]
   ldr r0,=076543210h // str r0,[r4,GPUREG_GSH_ATTRIBUTES_PERMUTATION_LOW]  ;\input
   ldr r0,=0fedcba98h // str r0,[r4,GPUREG_GSH_ATTRIBUTES_PERMUTATION_HIGH] ;/
   mov r0,03h         // str r0,[r4,GPUREG_GSH_OUTMAP_MASK]                 ;-output enable's
   mov r0,000h        // str r0,[r4,GPUREG_GSH_CODETRANSFER_INDEX]
   ldr r0,[@@code+0]  // str r0,[r4,GPUREG_GSH_CODETRANSFER_DATA+0]
   ldr r0,[@@code+4]  // str r0,[r4,GPUREG_GSH_CODETRANSFER_DATA+4]
   ldr r0,[@@code+8]  // str r0,[r4,GPUREG_GSH_CODETRANSFER_DATA+8]
   mov r0,000h        // str r0,[r4,GPUREG_GSH_OPDESCS_INDEX]     ;\
   ldr r0,[@@opdesc]  // str r0,[r4,GPUREG_GSH_OPDESCS_DATA+0]    ;/
   mov r0,00000001h   // str r0,[r4,GPUREG_GSH_CODETRANSFER_END]  ;trigger transfer end
   ldr r0,=7fff0000h+(000h/4) // str r0,[r4,GPUREG_GSH_ENTRYPOINT]   ;note: if MSBs=0000h --> hangs on 2nd write!
 .endif
 ldr r0,=(0a0h shl 24)+02h-1 // str r0,[r4,GPUREG_VSH_INPUTBUFFER_CONFIG]
 ldr r0,=076543210h // str r0,[r4,GPUREG_VSH_ATTRIBUTES_PERMUTATION_LOW]  ;\input
 ldr r0,=0fedcba98h // str r0,[r4,GPUREG_VSH_ATTRIBUTES_PERMUTATION_HIGH] ;/
 ldr r0,=03h        // str r0,[r4,GPUREG_VSH_OUTMAP_MASK]                 ;-output enable's
 mov r0,000h        // str r0,[r4,GPUREG_VSH_CODETRANSFER_INDEX]
 ldr r0,[@@code+0]  // str r0,[r4,GPUREG_VSH_CODETRANSFER_DATA+0]
 ldr r0,[@@code+4]  // str r0,[r4,GPUREG_VSH_CODETRANSFER_DATA+4]
 ldr r0,[@@code+8]  // str r0,[r4,GPUREG_VSH_CODETRANSFER_DATA+8]
 mov r0,000h        // str r0,[r4,GPUREG_VSH_OPDESCS_INDEX]     ;\
 ldr r0,[@@opdesc]  // str r0,[r4,GPUREG_VSH_OPDESCS_DATA+0]    ;/
 mov r0,00000001h   // str r0,[r4,GPUREG_VSH_CODETRANSFER_END]  ;trigger transfer end
 ldr r0,=7fff0000h+(000h/4) // str r0,[r4,GPUREG_VSH_ENTRYPOINT]   ;note: if MSBs=0000h --> hangs on 2nd write!
  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
;---draw...
 ldr r0,=(0 shl 8)+01h        // str r0,[r4,GPUREG_GEOSTAGE_CONFIG2]
 mov r0,00h         // str r0,[r4,GPUREG_START_DRAW_FUNC0]  ;0=draw, 1=config?
       ;mov r0,00000001h  // str r0,[r4,GPUREG_DRAWARRAYS]   ;trigger   ;XXX
       ;mov r0,00000001h  // str r0,[r4,GPUREG_DRAWELEMENTS] ;trigger   ;XXX
 mov r0,0fh         // str r0,[r4,GPUREG_FIXEDATTRIB_INDEX]
 ldr r1,=@@array
 mov r2,@@array_size_bytes
@@array_lop:
 .if 0;1   ;sane order...
   ldr r0,[r1,0]      // str r0,[r4,GPUREG_FIXEDATTRIB_DATA0]
   ldr r0,[r1,4]      // str r0,[r4,GPUREG_FIXEDATTRIB_DATA1]
   ldr r0,[r1,8]      // str r0,[r4,GPUREG_FIXEDATTRIB_DATA2]
 .else   ;insane order... (reportedly so)
   ldr r0,[r1,8]      // str r0,[r4,GPUREG_FIXEDATTRIB_DATA0]
   ldr r0,[r1,4]      // str r0,[r4,GPUREG_FIXEDATTRIB_DATA1]
   ldr r0,[r1,0]      // str r0,[r4,GPUREG_FIXEDATTRIB_DATA2]
 .endif
 mov r0,1000h // bl arm11_waitbyloop_step5
 add  r1,4+4+4
 subs r2,4+4+4
 bne  @@array_lop    ;hangs, AFTER MEMCOPY?!?!, when looping/sending all entries

  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
;---wait+flush
 bl  arm11_frame_delay
 mov r0,01h        // str r0,[r4,GPUREG_START_DRAW_FUNC0]  ;0=draw, 1=config?
 mov r0,1          // str r0,[r4,GPUREG_VTX_FUNC]  ;post-vertex cache flush?
 mov r0,1          // str r0,[r4,GPUREG_FRAMEBUFFER_FLUSH]
 mov r0,0000h      // str r0,[r4,GPUREG_GEOSTAGE_CONFIG2]
 bl  arm11_frame_delay
;---copy...
  ldr r1,=10141000h //  ldr r0,[r1] // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
 ldr r0,=MEMORG_COLORBUF/10h*2 // str r0,[r5,GPU_MEMCOPY_SRC_ADDR]
;ldr r0,=MEMORG_SCREEN0/10h*2  // str r0,[r5,GPU_MEMCOPY_DST_ADDR]
ldr  r0,=arm11_struct_screen1         ;\
ldr  r0,[r0,18h] ;dst (vram)          ;
mov  r0,r0,lsr (4-1)                  ;
str r0,[r5,GPU_MEMCOPY_DST_ADDR]      ;/
 ldr r0,=(320 shl 0)+(240 shl 16) // str r0,[r5,GPU_MEMCOPY_DISPLAY_DST_SIZ]
 ldr r0,=(320 shl 0)              // str r0,[r5,GPU_MEMCOPY_DISPLAY_SRC_SIZ]
 mov r0,0                         // str r0,[r5,GPU_MEMCOPY_FLAGS]
 mov r0,0                         // str r0,[r5,GPU_MEMCOPY_WRITE_NULL]
 mov r0,01h                       // str r0,[r5,GPU_MEMCOPY_KICK]
;- - -
  ldr r1,=10141000h //  ldr r0,[r1]    // bl wrhex32bit // bl wrcrlf ;CFG11_GPU_STATUS
  ldr r0,[r4,GPUREG_VSH_OUTMAP_TOTAL1] // bl wrhex32bit // bl wrcrlf
  ldr r0,[r4,GPUREG_VSH_ENTRYPOINT]    // bl wrhex32bit // bl wrcrlf
 bl    arm11_waitkey_with_keyrepeat
 pop  r0-r12,pc
;---
.pool
;---
@@code:
 dd (13h shl 26)+(00h shl 21)+(00h shl 12)   ;MOV o0,v0
 dd (13h shl 26)+(01h shl 21)+(01h shl 12)   ;MOV o1,v1
 dd (22h shl 26)                             ;END
;---
@@opdesc:
 dd (00h shl 0)+(1bh shl 5)+(1bh shl 14)+(1bh shl 23)
;---
.align 10h
@@array:
 .float24 -1.0    ;x?   ;\
 .float24 -1.0    ;y?   ; 1st coord
 .float24 -1.0    ;z?   ;
 .float24 -1.0          ;/
 .float24 1.0     ;r?   ;\
 .float24 0.5     ;g?   ; 1st color
 .float24 0.5     ;b?   ;
 .float24 0.5           ;/
 ;- - -
 .float24 50.0          ;\
 .float24 10.0          ; 2nd coord
 .float24 50.0          ;
 .float24 10.0          ;/
 .float24 0.5           ;\
 .float24 1.0           ; 2nd color
 .float24 0.5           ;
 .float24 0.5           ;/
 ;- - -
 .float24 20.0          ;\
 .float24 80.0          ; 3rd coord
 .float24 20.0          ;
 .float24 80.0          ;/
 .float24 0.5           ;\
 .float24 0.5           ; 3rd color
 .float24 1.0           ;
 .float24 0.5           ;/
@@array_size_bytes equ $-@@array
So, well, I am fucked up for now. My next ideas would be brute-forcing, sending random values to the GPU, hoping that it would displaying something (though I am afraid that it might rather lock up), or trying to extract the required low-level from citro3d.

3dbrew: I've tried to register a 3dbrew account several times a few years ago, and I've studied all the how-to-bypass-their-captcha guides on https://stackoverflow.com/questions/156 ... hash-linux and https://gbatemp.net/threads/why-is-the- ... ng.395800/ but somehow that didn't work out for me, and I've finally given up on getting an account. I could have probably solved the captcha with a newer PC, or newer browser, or with the DSi's sha1 function, or asked other people for help... but somehow my motivation didn't last long enough, and I've meanwhile reached near-zero motivation to post on 3dbrew myself. Anyways, I won't complain if someboy else wants to post my findings on 3dbrew.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Sat Apr 25, 2020 9:28 am

nocash wrote:
Sat Apr 25, 2020 8:30 am
3dbrew: I've tried to register a 3dbrew account several times a few years ago, and I've studied all the how-to-bypass-their-captcha guides on https://stackoverflow.com/questions/156 ... hash-linux and https://gbatemp.net/threads/why-is-the- ... ng.395800/ but somehow that didn't work out for me, and I've finally given up on getting an account. I could have probably solved the captcha with a newer PC, or newer browser, or with the DSi's sha1 function, or asked other people for help... but somehow my motivation didn't last long enough, and I've meanwhile reached near-zero motivation to post on 3dbrew myself. Anyways, I won't complain if someboy else wants to post my findings on 3dbrew.
Well, then i'm sorry for what i said about 3dbrew/contributing and take it back. But i don't think we can make this work. Even if someone creates an account for you that captcha stuff is on every edit page. It is annoying but it was needed to stop spam bots. The old captcha has been replaced some time ago and now it uses reCAPTCHA which will very likely not work on anything pre-Windows XP. But it requires no Linux tools anymore to solve. Just the mouse and a browser of course. It should work fine on Android Tablets.

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

Re: 3DS reverse engineering

Post by nocash » Sat Apr 25, 2020 5:02 pm

Sorry, too! Especially about the poisonous part! There've been only a few a cases where I've been worrying that the discussion was close to drifting to competition-mode or defense-mode. But looking back, most of the time it's been all fine, and I am glad about all the info that you have shared. And I didn't want to sound as if I would expect anybody to do all the work for me and my gbatek document, I had I thought (and still hope) that you have enjoyed the research, too, and that other people are also interested in your findings.

Well, and the post some week ago where I was saying that I am unsure if they are idiots... "or if I am an arrogant asshole & idiot myself". I would like to point out the latter part of that sentence. I am occasionally complaining about specifications that contain either too much, or too less detail, and I tried to say that I am aware that such frustated commens are rather making me sound like an asshole myself. Anyways, it's really stupid to say such things in public. I didn't want to attack anyone personally, and neither should I complain about unaware people behind their back. So, sorry about that, too.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

Post Reply