3DS reverse engineering

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

Re: 3DS reverse engineering

Post by nocash » Sat Apr 17, 2021 2:34 pm

Just looking at the lcd.h file...

The three H,V,ERR irq flags sound good. If only one source is enabled then they do match up with the eight IRQ modes described in gbatek. And if more source are enabled.. that would pretty well explain some of the more confusing hardware behaviours).
The third irq source is called "ERR"? Not sure if that does mean error... maybe it's short for "Every Row Repeating" interrupt? That would match up with what I had observed (except, with the rotated display, it's actually Every Column Repeating, not Every Row Repeating).

"REG_LCD_UNK00C" is Clock Disable:

Code: Select all

1020200Ch - LCD_CLOCK_DIS - LCD Clock Disable (R/W)
  0      Top Screen Clock     (TP163/TP164) (0=Normal/On, 1=Screen fades out)
  1-15   Unused (0)
  16     Bottom Screen Clock  (TP189)       (0=Normal/On, 1=Screen fades out)
  17-31  Unused (0)
And, as your source code mentioned it... just checked, yes, the Clock Disable does also disable Vsync and Hsync signals (on bottom screen, the top screen's serial-bus has no such signals).

For this register...

Code: Select all

10202014h - LCD Enable Displays (R/W)
  0      Both Screens Display Enable (TP244) (0=Off/Black, 1=On/Picture)
  1-31   Unused (0)
Forces both screens to become black (although clock, data transfers, and
backlight are kept on). For whatever reason, the top screen isn't fully black:
the upper/lower/left/right screen borders are becoming dark gray... maybe
related to parallax being also disabled... somehow causing "leaking" light?
that's what you have called REG_LCD_RST... just checked... it does Reset the LCD I2C registers, so yes, it's Reset, not Display Enable.
Interestingly, my two consoles are all fine after resuming from reset (the picture does just reappear as before reset, without needing to re-initialize any I2C registers).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Sat Apr 17, 2021 5:54 pm

Solved one more testpoint: TP258 is Speaker/Audio Supply +3.5V. I've GNDed the "always high" pins, to see what happens, the console didn't catch fire, but one of the pins felt a bit sticky upon contact, like lots of amperes flowing... and the pin voltage looks same as speaker PWM... so I've tried the shortcut with sound playing, and the speakers did actually switch off immediately (the console kept running, and the speakers resumed working after some seconds).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Sun Apr 18, 2021 9:15 am

nocash wrote:
Sat Apr 17, 2021 9:42 am
I haven't encountered that famous lost sync problem yet, maybe it will show up when re-installing the bottom screen in the old3ds.

Is there anything known about how many different LCD screens exist, with chip IDs or part numbers, and maybe some notes about which screens can lose sync?
It's almost always IPS panels that act picky about the way they get initialized but it happened before with regular panels. My N3DS XL does have a top IPS panel. You can easily tell because they have very wide viewing angles with barely any color distortion. I don't think there is a complete list of panels yet but this has the most common IDs:
https://github.com/joel16/3DSident/blob ... tem.c#L147
nocash wrote:
Sat Apr 17, 2021 2:34 pm
The three H,V,ERR irq flags sound good. If only one source is enabled then they do match up with the eight IRQ modes described in gbatek. And if more source are enabled.. that would pretty well explain some of the more confusing hardware behaviours).
The third irq source is called "ERR"? Not sure if that does mean error... maybe it's short for "Every Row Repeating" interrupt? That would match up with what I had observed (except, with the rotated display, it's actually Every Column Repeating, not Every Row Repeating).
Not exactly sure about what kind of error this is myself. Maybe DMA/FIFO errors. The reg where you specify the frame buffer pixel format has a kind of DMA interval in the topmost bits. Setting this very high slows down frame buffer scanning significantly. Maybe this triggers errors. There are also burst length bits.

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

Re: 3DS reverse engineering

Post by nocash » Mon Apr 19, 2021 4:04 pm

profi200 wrote:
Sun Apr 18, 2021 9:15 am
I don't think there is a complete list of panels yet but this has the most common IDs:
https://github.com/joel16/3DSident/blob ... tem.c#L147
Yeah, like that, but seems to be an OS function with 4bit return value. It doesn't seem to be directly related to the 8bit I2C registers.
profi200 wrote:
Sun Apr 18, 2021 9:15 am
Not exactly sure about what kind of error this is myself. Maybe DMA/FIFO errors. The reg where you specify the frame buffer pixel format has a kind of DMA interval in the topmost bits. Setting this very high slows down frame buffer scanning significantly. Maybe this triggers errors. There are also burst length bits.
Good to know! The ERR IRQs seem to occur at the begin of each picture column, maybe that happens only if there wasn't enough data prefetched, and maybe some of the "middle border position" registers are related prefetch timings. Might be worth testing if the ERR IRQs are generated even when using known good settings for all other register.

At the moment I am struggling again with testing initial register values and read/write-ability of all registers (and trying to mask out "random" bits to get meaningful results, that's not easy).
Anyways, I've found a handful of registers that were known-to-exist on New3DS - but not-known-to-not-exist on Old3DS.

And, alongsides I've stumbled over what seems to be some overlooked IRQ sources. IRQ 20h-23h and 3Ch-3Fh were thought to be unused, but some of them have nonzero IRQ line states...

Code: Select all

  20h     -           Unused?                                     ;\
  21h     -           Unused? But [17E01D00h].bit33 is set        ; maybe related to
  22h     -           Unused?                                     ; first two CPU cores?
  23h     -           Unused? But [17E01D00h].bit35 is set        ;/
  3Ch     -           Unused?                                     ;\
  3Dh     -           Unused? But New3DS [17E01D00h].bit61 is set ; maybe alike IRQ 20h-23h
  3Eh     -           Unused?                                     ; for extra CPU cores?
  3Fh     -           Unused? But New3DS [17E01D00h].bit63 is set ;/
Any ideas what they are good for?
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Wed Apr 21, 2021 4:27 pm

Just going through some config register changes on 3dbrew...
http://www.3dbrew.org/wiki/CONFIG11_Registers
http://www.3dbrew.org/wiki/PDN_Registers
Looks as if TuxSH has made quite some new findings.

Port 10140100h (CFG11_NULLPAGE_CNT) bit0 enables trapping data aborts on access to first 4Kbyte of ARM11 bootrom at 0..0FFFh (but doesn't trap mirrors at 10000h or FFFF0000h)... and the unknown bit in bit16 is simply the corresponding flag (set on access to that memory area, and cleared when writing 0 to bit16).

Port 1014110Ch (CFG11_WIFIUNK) "bit4 set to 1 very early in NWM-module" is gone because that register doesn't exist for real... except, it does exist, but seems tohave been a typo meant to be 1014010Ch (CFG11_CDMA_CNT) which does actually have bit4 set to 1 by NWM code, whereas bit4 does supposedly enable CDMA peripheral 04h.

Although, 3dbrew claims that CFG11_CDMA_CNT bit5 would be "WiFi. Enabled during kernel init since 11.4", but I guess bit5 is something else, maybe for debug sdio?

Port 10140108h is also gone on 3dbrew... but that register does exist for real, bit0 appears to be very much read/write-able to me.

And then there are new newly discovered LGY_CARDDETECTEMU and LGY_GPIOEMU registers... the GPIOEMU ones do still leave a lot of open questions though, about which 3DS GPIO bit corresponds to which DSi GPIO bit.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Thu Apr 22, 2021 10:15 am

Some final measurements before reassembling the console...

The polarity of the H/V-Sync signals can be inverted (that was half expected):

Code: Select all

10400448h/10400548h - Screen Sync Polarity (R/W)
  0      V-Sync Polarity (0=Active Low, 1=Active High)  ;Bottom Screen TP190
  1-7    Unused (0)
  8      H-Sync Polarity (0=Active Low, 1=Active High)  ;Bottom Screen TP191
  9-31   Unused (0)
Must be 00h for top screen, and 11h for bottom screen.
And, less expected, the 16MHz clock on TP152 can be changed to 8MHz, or switched off:

Code: Select all

10141220h - CFG11_SPEAKER_CNT
  0     Unknown (R/W)
  1     Speaker 8MHz/16MHz Clock (TP152)  (0=Off/Muted Sound, 1=On)
  2-31  Unused (0)
Should be set to 02h. The Speaker Clock seems to drive speaker PWM (sound gets
muted when bit1=0, although audio I2S clock/data are kept running).
EDIT: Above does only enable/disable the clock, the 8MHz/16MHz frequency is selected here:

Code: Select all

10145000h - CODEC_SNDEXCNT (R/W)
  0-5   DSP sound volume (00h..3Fh)
  6-11  GBA sound volume (00h..3Fh)
  12    Enable Microphone timing
  13    Sound/Microphone I2S Clock Frequency (0=32.73 kHz, 1=47.61 kHz)
  14    Unknown...? (maybe Mute, alike DSi's SNDEXCNT)
  15    Enable Microphone and Teak BTDMP timing and GBA sound
  16-28 Unused (0)
  29    Unknown...? (R/W)
  30    Speaker (PWM?) Clock TP152 (0=Normal 8MHz, 1=Dissonant 16MHz)
  31    Sound/Microphone I2S Clock Enable (TP149/TP150)
Bit12-14 and bit28-30 are write-able only if bit31 was zero before the write.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Sat May 08, 2021 7:13 am

I'm in the process of rewriting the drivers for the Toshiba SD(IO) controller and SD/(e)MMC and thought i should post this little detail that seems to be missing on gbatek. The unknown lowermost bits int REG_SD_OPTION are a card detection timer. It's the time between inserted status and the "SIGSTATE" status getting set. Not sure how useful it is though because that bit doesn't trigger an IRQ. Might as well sleep X ms after getting the inserted IRQ (voltage ramp up time ect.). I think i roughtly figured out how it's calculated since the calculated and measured time seem to be extremely close. I have noted this down for 3DS:

"Card detect: 0x400<<9 / 67027964 = 0.007821929 sec."

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

Re: 3DS reverse engineering

Post by nocash » Sat May 08, 2021 1:32 pm

Very good to know! Even if it's just useful for knowing how to avoid too long delays, or for knowing whether or not needing additional software delays after SIGSTATE changes.
And it does shed some light on what http://www.3dbrew.org/wiki/EMMC_Registers might have referred to when saying that "Assertion happens around 250 ms after SD card insertion and/or enabling the EMMC hardware (delay could possibly be due to an SD bus timeout?)."

The formula looks good, 0x400 and 67MHz are constants, and "9" is the setting from lower 4bit of what I had called SD_CARD_OPTION? If it works similar than the other timeout in that register, then value "15" might be a special case with shorter delay.
And, the the other timeout uses the SDCLK instead of fixed clock source like 67MHz... but I guess SIGSTATE should work even when SDCLK is stopped, so the fixed 67MHz clock makes more sense here.

Other minor finding about ROM cartridges: I've cracked open a 3DS cartridge with the long unknown manufacturer ID=45h. The known NDS/3DS cart maker IDs were C2h=Macronix, AEh=Noname, ECh=Samsung, 80h=SanDisk, and... rather unexpectedly... 45h is also SanDisk.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Sat May 08, 2021 2:12 pm

nocash wrote:
Sat May 08, 2021 1:32 pm
Very good to know! Even if it's just useful for knowing how to avoid too long delays, or for knowing whether or not needing additional software delays after SIGSTATE changes.
And it does shed some light on what http://www.3dbrew.org/wiki/EMMC_Registers might have referred to when saying that "Assertion happens around 250 ms after SD card insertion and/or enabling the EMMC hardware (delay could possibly be due to an SD bus timeout?)."

The formula looks good, 0x400 and 67MHz are constants, and "9" is the setting from lower 4bit of what I had called SD_CARD_OPTION? If it works similar than the other timeout in that register, then value "15" might be a special case with shorter delay.
And, the the other timeout uses the SDCLK instead of fixed clock source like 67MHz... but I guess SIGSTATE should work even when SDCLK is stopped, so the fixed 67MHz clock makes more sense here.

Other minor finding about ROM cartridges: I've cracked open a 3DS cartridge with the long unknown manufacturer ID=45h. The known NDS/3DS cart maker IDs were C2h=Macronix, AEh=Noname, ECh=Samsung, 80h=SanDisk, and... rather unexpectedly... 45h is also SanDisk.
9 is the value i use and it's the lowest that still works and is within SD/MMC spec. Voltage ramp up time is well within spec in my measurements. And the required 74 clock pulses can easily be done with a cycle accurate loop or timer (the later wastes less energy).

It's the setting from bits 0-3 of REG_SD_OPTION. And yeah, 15 is some kind of test mode or something for both bits 0-3 and 4-7.

Regarding 3DS gamecards: In case you didn't notice yet the entire encryption scheme has been broken: https://www.3dbrew.org/w/index.php?titl ... ldid=21411

They used some obscure and not so well known algorithms for this. Not a bad idea until someone figures it out...

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

Re: 3DS reverse engineering

Post by nocash » Sun May 09, 2021 11:36 pm

Interesting, RC4 is the standard WEP encryption, but I've never heard of SNOW 2.0 before, and it seems to be barely documented. I've found only this two webpages:
https://link.springer.com/content/pdf/1 ... 92-7_5.pdf - describes SNOW 2.0, but isn't shy of using obscure maths symbols
https://github.com/floodyberry/supercop ... snow-2.0/e - optimized source code for SNOW 2.0, but the optimization makes it difficult to know how it works (like what was multiplied by what to generate the tables)
The README file on the source code page claims to include a "reference implementation of SNOW 2.0" but that isn't actually released, or maybe one needs to buy an ISO/IEC document to obtain that reference thing.

Well, and to actually implement it, one would need to know the two blurred out 16-byte keys, cardrc4keyhalf and cardsnowiv on the https://i.imgur.com/1tYQgdK.png page (and probably a few more similar constants for the different CTRCARD_SECCNT modes). The RC4 key could be probably broken by anybody how knows how to extract enough test cases from the cartridge or console (and knowns more about crypto attacks than me), but I have no idea how difficult it would be to find the SNOW iv value.

The other thing that I've never figured out is how to calculate the CRC32 values. Going by 3dbrew, it sounds as if it's calculated on the decrypted data, not affected by the command or status/ready bytes. And going by the snow .png file it looks as if the CRC32 bytes are also transferred in encrypted form. And going by my own tests, the CRC32 checks seem to work only for command BFh and 82h.
But I have never managed to read an intact standard CRC32 value from the cartridge, so maybe there's more to it... nonstandard polynomial or nonstandard initial value or whatever.

EDIT: Two more RC4 problems, I couldn't say what the png's "reduce lambda x y tolist" means (unless it just says that tbe cmd is RC4 encrypted), and, unlike WEP, the firat 256 bytes of the RC4 output are skipped (alike as in WPA EAPOL messages), that might make it a lot more difficult to find the orginal key.
EDIT2: Breaking WEP/RC4 does probably rely on dumping several packets with a constant key and several different known public IV values, but in this case the RC4 "IV's" are unknown random numbers coming from the SNOW hardware.
Last edited by nocash on Mon May 10, 2021 11:38 pm, edited 1 time in total.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

windwakr2
Posts: 5
Joined: Sun Mar 29, 2020 4:28 pm

Re: 3DS reverse engineering

Post by windwakr2 » Mon May 10, 2021 9:48 am

nocash wrote:
Sun May 09, 2021 11:36 pm
https://github.com/floodyberry/supercop ... snow-2.0/e - optimized source code for SNOW 2.0, but the optimization makes it difficult to know how it works (like what was multiplied by what to generate the tables)
The README file on the source code page claims to include a "reference implementation of SNOW 2.0" but that isn't actually released, or maybe one needs to buy an ISO/IEC document to obtain that reference thing.
One of the code files there mentions a url that's dead, but available on archive.org
https://web.archive.org/web/20060202010 ... logy/snow/
It looks like it has a reference implementation for download.

nocash wrote:
Sun May 09, 2021 11:36 pm
I couldn't say what the png's "reduce lambda x y tolist" means (unless it just says that tbe cmd is RC4 encrypted)
Looks like it's just decrypting the bytes of the command. Must be done this way because of how the encrypted data is being stored(as one large number).

Reduce will take the first two values in the second parameter and pass them to the function in the first parameter. Then pass the output of that along with the third value from the second parameter into it, and so on. For example

Code: Select all

reduce(lambda x, y: x<<8 | y, [0x11, 0x22, 0x33, 0x44, 0x55])
will produce the output 0x1122334455.

The part in the square brackets on the right in that image is breaking the command down into individual bytes and XOR'ing them with RC4 output.

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

Re: 3DS reverse engineering

Post by nocash » Mon May 10, 2021 11:40 pm

Thanks for clarifying the reduce lambda part, and good to have the original snow source code!
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by nocash » Thu May 13, 2021 5:36 am

I am bit ashamed of myself for wasting time on converting a high resolution truecolor image into uncompressed and necrophile ascii text, but I seem to have typed up the .png, so here it is:

Code: Select all

##################################.py

from snow20 import SNOW20
from rc4 import RC4

cardrc4keyhalf = 0x4##############################7
cardsnowiv = 0xD##############################4
#cardrc4keyhalf = 0x3##############################9
#cardsnowiv = 0xD##############################4
#cardrc4keyhalf = 0x7##############################C
#cardsnowiv = 0x0##############################A

def tolist(val, nbytes):
    return [val >> i & 0xff for i in reversed(range(0, nbytes*8, 8))]

def initsnowstream(snowkey):
    snow20stream = SNOW20(snowkey, cardsnowiv)
    for _ in xrange(32): #discard 1024 bits of output, each output is 32 bits
        snow20stream.next()
    return snow20stream

def initrc4stream(snowstream):
    tmp = snowstream.next() << 96 | snowstream.next() << 64 | \
          snowstream.next() << 32 | snowstream.next()
    key = cardrc4keyhalf << 128 | tmp
    rc4stream = RC4(tolist(key, 32))
    for _ in xrange(256): #discard the first 256 bytes of output
        rc4stream.next()
    return rc4stream

#sample data from 3dbrew   ;http://www.3dbrew.org/wiki/Gamecards
titlekey1 = 0x################ #decrypted from header at bottom of gamecard page
titlekey2 = 0x################
enccmds = [[0xF32C92D85C9D44DED3E0E41DBE7C90D9, 0x00],
           [0x696B9D8582FB55D31B68CAFE70C74A95, 0x04],
           [0xBAA4812CA0AC9C5D19399530E3ACCCAB, 0x04],
           [0x178E427C22D87ADB86387249A97D321A, 0x00],
           [0xE06019B1BD5C9130ED6A4D9F4A9E7193, 0x04],
           [0x4E0D224862523BBFE2E6255F80E15F37, 0x04],
           [0x4CDF93D319FB62D0DB632A45E3E8D84C, 0x04],
           [0x9AA5D80551002F955546D296A57F0FEF, 0x04],
           [0xC12BA81AEF30DDDBD93FAD5D544C6334, 0x04],
           [0x62EC5FB7F420AE1DC6253AE18AFA5BB3, 0x200+4], #+crc
           [0xE3FA23AA016BE0C93430D1F42FF41324, 0x200+4]] #+crc

 snow20stream = initsnowstream(titlekey1 << 64 | titlekey2)
 rc4stream = initrc4stream(snow20stream)

 for cmd, datalen in enccmds:
     print 'encrypted command: %032X' % (cmd)
     dec = reduce(lambda x, y: x<<8 | y, [rc4stream.next() ^ x for x in tolist(cmd, 16)])
     print 'decrypted command: %032X' % (dec)

     if dec >> (15*8) == 0x83: #"set seed" command, replaces titlekey2 and reinitializes the snow cipher
         randseed = dec & 0xFFFFFFFFFFFFFFFF
         print 'changing "seed" to %016X' % (randseed)
         snow20stream = initsnowstream(titlekey1 << 64 | randseed)

     rc4stream = initrc4stream(snow20stream) #after every(?) encrypted command, the rc4 cipher is reinitialized with the next 128 bits of snow output

     print 'skipping %d bytes' % (datalen)
     for _ in xrange(datalen):
         rc4stream.next() #we don't have the returned data in this sample data, so just throw out bytes from the cipher stream
profi200 wrote:
Sat May 08, 2021 7:13 am
The unknown lowermost bits int REG_SD_OPTION are a card detection timer. It's the time between inserted status and the "SIGSTATE" status getting set. Not sure how useful it is though because that bit doesn't trigger an IRQ.
I am just trying to test that and measure the timing on DSi, but it doesn't work as expected.
As far as I understood, I set the delay in lower 4bit of SD_CARD_OPTION (Port 4004828h), then acknowledge all IRQs in SD_IRQ_STAT (Port 4004810h), insert the SD card, and wait until IRQ_STAT bit4 gets set (cart newly inserted), and then there is a variable delay until IRQ_STAT bit5 (SIGSTATE) gets set? But, over here, bit4 and bit5 seem to get set exactly at the same time. How did you measure that delay?

It looks as if both bit4 and bit5 might be both affected by the delay, but it's hard to tell since the max delay setting is less than one second (and I couldn't exactly say when the insert switch gets closed during insertion). My only idea would be rewiring the insert switch signal, so that it could be toggled by software. But you didn't really do that, or did you?
EDIT: Also tried on 3DS, that does also set bit4 and bit5 simultaneously.

Apropos, do you know if the delay occurs only on card insert, or also on power up, or also upon somehow resetting the card controller?
profi200 wrote:
Sat May 08, 2021 2:12 pm
9 is the value i use and it's the lowest that still works and is within SD/MMC spec. Voltage ramp up time is well within spec in my measurements.
Yeah, that timings are relevant on power up (when the card is already inserted). When actually newly inserting the card, I think the delay is more about eliminating switch bounce (on the insert switch signal), and ensuring that data/clk/cmd pins have properly settled (eg. depending on how quickly and smoothly the user is pushing the card in). I guess card insert would typically need delays much longer than 7.8ms (or you could start to try to access the card instantly, but be prepared to retry for several 100ms in case of errors).

Btw. the 3DS seems to have a separate power supply for the SD card slot (TP13), instead of using the "main" 3.3V supply (TP3). I don't know if or how that supply can be switched on/off by software though.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

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

Re: 3DS reverse engineering

Post by profi200 » Sat May 15, 2021 5:55 am

nocash wrote:
Thu May 13, 2021 5:36 am
profi200 wrote:
Sat May 08, 2021 7:13 am
The unknown lowermost bits int REG_SD_OPTION are a card detection timer. It's the time between inserted status and the "SIGSTATE" status getting set. Not sure how useful it is though because that bit doesn't trigger an IRQ.
I am just trying to test that and measure the timing on DSi, but it doesn't work as expected.
As far as I understood, I set the delay in lower 4bit of SD_CARD_OPTION (Port 4004828h), then acknowledge all IRQs in SD_IRQ_STAT (Port 4004810h), insert the SD card, and wait until IRQ_STAT bit4 gets set (cart newly inserted), and then there is a variable delay until IRQ_STAT bit5 (SIGSTATE) gets set? But, over here, bit4 and bit5 seem to get set exactly at the same time. How did you measure that delay?
Hmm, could be they are set at the same time. I assumed insert/remove is pretty much instant. I measured time on a logic capture i made a long while ago but i could not figure out exactly where the timer starts so i assumed it starts about when all the lines go high. The timing was about 6.07 ms.
Bildschirmfoto_2021-05-15_14-41-48.png
nocash wrote:
Thu May 13, 2021 5:36 am
It looks as if both bit4 and bit5 might be both affected by the delay, but it's hard to tell since the max delay setting is less than one second (and I couldn't exactly say when the insert switch gets closed during insertion). My only idea would be rewiring the insert switch signal, so that it could be toggled by software. But you didn't really do that, or did you?
EDIT: Also tried on 3DS, that does also set bit4 and bit5 simultaneously.

Apropos, do you know if the delay occurs only on card insert, or also on power up, or also upon somehow resetting the card controller?
profi200 wrote:
Sat May 08, 2021 2:12 pm
9 is the value i use and it's the lowest that still works and is within SD/MMC spec. Voltage ramp up time is well within spec in my measurements.
Yeah, that timings are relevant on power up (when the card is already inserted). When actually newly inserting the card, I think the delay is more about eliminating switch bounce (on the insert switch signal), and ensuring that data/clk/cmd pins have properly settled (eg. depending on how quickly and smoothly the user is pushing the card in). I guess card insert would typically need delays much longer than 7.8ms (or you could start to try to access the card instantly, but be prepared to retry for several 100ms in case of errors).

Btw. the 3DS seems to have a separate power supply for the SD card slot (TP13), instead of using the "main" 3.3V supply (TP3). I don't know if or how that supply can be switched on/off by software though.
The detection timer kicks in in these scenarios (tested): Card physically inserted or card port moved to the controller via REG_SDMMCCTL (3DS).

Even if the power supply is already up i think the card still needs about 1 ms before you can start applying the 74 clock pulses.
From the SD simplified spec 8.00 section "6.4.1.1 Power Up Time of Card":
"A device shall be ready to accept the first command within 1ms from detecting VDD min. Device may use up to 74 clocks for preparation before receiving the first command."

In practice i can say this is needed. There are many SD cards out there which will not work correctly if you dont follow the rules.


edit:
I tested this and indeed insert and the detect ("SIGSTATE") bit get set at the same time so it's good to know the card detection timer is not useless having an IRQ.
If i didn't mention this yet on 3DS a value of 8 for the timer is already too fast and some SD cards will not init properly.

And i observed weird behavior with the way write data transfers work. When i return from the send command function early letting the controller send the last block in background and another write cmd is getting sent, waiting for CMD busy seems to not work sometimes. Only if i wait for both CMD busy being 0 and bit 29 being set the controller/code does not hang. Bit 29 is documented nowhere though and not even Nintendo's driver uses this bit.

Btw this driver is very close. Even closer than TMIO maybe. Only difference is this controller is connected externally via PCIe:
https://github.com/torvalds/linux/blob/ ... t/toshsd.c (header file in the same dir)

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

Re: 3DS reverse engineering

Post by nocash » Mon May 17, 2021 7:28 am

Okay, now I got the delay reproduced using SDMMCCTL on 3DS. I don't know if there's a similar way to trigger the delay by software on DSi.
I got the same timings on 3DS, "400h SHL (0..14) HCLKs" for value 0..14. And "100h HCLKs" for value 15.
Status bit4 and bit5 get set after that delay.

Alongsides, I've noticed that Status bit9 and bit10 are also getting set about 2D000h..36000h HCLKs (=circa 3ms) after activating SDMMCCTL. That happens even without cart inserted, it's not useful, but it's interesting: Apparently, at that time, the data line pull-up resistors are receiving enough volts to be treated as "high", though the supply is probably still less than 3.3V at that point. So I've scope-checked the SD Slot 3.3V power pin on DSi and Old3DS...

On the DSi, it does increase almost linearily from 0V to 3V within 3ms, and then suddenly jumps from 3V to 3.3V. That's happening on power-up, before booting from SD/MMC, so software won't have to care about that.
On the 3DS, it does increase somewhat sine-like from 0V to 3.3V within 4.2ms (once when activating it via SDMMCCTL bit0=0?). Together with the 1ms card boot up time, the delay should be at least 5.2ms. So, yes, setting 9 (almost 8ms) sounds right, and 8 (almost 4ms) would be too short.

I didn't knew the toshsd.* source code. Yup it looks closer (or more complete, the other chips should have the Error bits, too, but the tmio source code didn't mind to define that bits).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty

Post Reply