4dsdev
Views: 1,383,816 Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search 03-28-24 03:45 PM
Guest:

0 users reading DSP reverse engineering | 1 bot

Main - Reverse-engineering - DSP reverse engineering Hide post layouts | New reply


StapleButter
Posted on 12-03-14 12:52 AM Link | #45
I wanted to start by the basics and determine how the DSP memory is mapped, and what is what on the DSP side.

DSP RAM goes from 1FF00000 to 1FF7FFFF. So far we have:

1FF00000 - 1FF3FFFF? -> program RAM (DSP exception vectors at 1FF00000+)
1FF40000 - 1FF5FFFF -> data RAM region 1 (1FF50000-1FF5FFFF exposed read-only to ARM11 userland)
1FF60000 - 1FF7FFFF -> data RAM region 2 (1FF70000-1FF7FFFF exposed read-only to ARM11 userland)

Does the program RAM end at 1FF3FFFF or 1FF1FFFF? (if then, what's in the leftover space?)

The DSP can only address 65536 words without switching banks or something in the like. That is, 128K. Assuming the two data RAM regions map to X-RAM and Y-RAM, and the program RAM goes from 1FF00000 to 1FF1FFFF, what would be in the leftover space? DSP-side I/O?

Well uh, clearly this DSP is able to address more than 128K of memory. There has to be a way to select which chunk of memory is being accessed, like on the SNES where they have DBR and PBR to specify which banks the CPU will access.


The docs mention movp and movd instructions, moving from/to data/program RAM. But nothing precises if the regular mov instructions access program RAM or data RAM.

____________________
blargSNES -- SNES emu for 3DS
More cool stuff

yuriks
Posted on 12-03-14 01:06 AM (rev. 2 of 12-03-14 01:08 AM) Link | #46
One thing I noticed while helping neobrain with FIRM REing is that the NATIVE_FIRM ARM11 initial processes are actually loaded into this 0x1FF00000-0x1FF7FFFF memory region. Do they later get relocated at some point in the boot process or is there some funny memory remapping going on?

StapleButter
Posted on 12-04-14 06:03 PM (rev. 5 of 12-04-14 06:27 PM) Link | #51
Dunno. I'm not really on that either.


Anyway, have more shiz.

Binary loading process

Binary is verified and segments are written to their appropriate locations in DSP RAM. As far as I can see, they're written directly, there is no fancy specific transfer mechanism involved. At this point it seems that the DSP isn't running.

Bits are set in some registers that control DSP RAM mapping (0x1EC40000, 0x1EC40008).

pdn:d command 0x100C0 sent 3 times:
1. params = 0, 1, 0
2. params = 1, 1, 0
3. params = 1, 1, 1

If bit 0 in 0x1ED03008 is zero, sets it to 1 and waits 0x60 cycles

Waits until bit 2 in 0x1ED0300C becomes zero

If bit 0 in 0x1ED03008 is nonzero: clear bits 9-11 in 0x1ED03008, set 0x1ED03010 to 0, set 0x1ED03018 to 0xFFFF, wait 0x60 cycles, issue reads from 0x1ED03024, 0x1ED0302C and 0x1ED03034 (read values ignored), wait 0x60 cycles

Set some bit (val unknown, maybe comes from DSP binary?) in 0x1ED03008, wait 0x60 cycles

Clear bit 0 in 0x1ED03008, wait 0x60 cycles

Set 0x1ED03014 (semaphore mask) based on that same unknown value, wait 0x60 cycles

If some bit is cleared: read DSP reply from command slot 0, wait 0x60 cycles; repeat until reply is 1
Repeat above for command slots 1 and 2

Write shit to 0x1ED03008 and 0x1ED03014, origins not quite known

Bit 11 in 0x1ED03008 is set to one then zero.
Simultaneously, bit 15 in 0x1ED03014 is set to zero then one.

*(vu16*)0x1ED03008 |= 0x0800;
*(vu16*)0x1ED03014 &= ~0x8000;
*(vu16*)0x1ED03008 &= ~0x0800;
*(vu16*)0x1ED03014 |= 0x8000;

Do those registers really match what is documented in NO$GBA's help text? The bits that are toggled here would be interrupt enable bits; makes little sense to toggle them if that's what they are. My guess is that they play a role in resetting the DSP?

This seems to also be done when unloading the DSP binary, so not quite sure.

Then there are two commands sent to cdc:DSP

cmdbuf[0] = 0x70040
(byte) cmdbuf[1] = 1

cmdbuf[0] = 0x80040
(byte) cmdbuf[1] = 1


Binary unloading (and turning the DSP off)

Same shit as above with 0x1ED03008 and 0x1ED03014.

Then it waits for bit 15 in 0x1ED0300C to become zero. Writes 0x8000 to 0x1ED03030 and does some wait loop (0x60 cycles).
-> sends command 0x8000 via command slot 2
then waits for bit 12 in 0x1ED0300C to become one. Reads reply from 0x1ED03034.

Reply is ignored.

Waits for bit 0 in 0x1ED03008 to become zero. Sets that bit to one, waits 0x60 cycles. Waits for bit 2 in 0x1ED0300C to become zero.

Sends pdn:d command 0x100C0.
cmdbuf[0] = 0x100C0
(byte) cmdbuf[1] = 1
(byte) cmdbuf[2] = 1
(byte) cmdbuf[3] = 0

Sends same command with params 0, 1, 0

Sends commands to cdc:DSP

cmdbuf[0] = 0x70040
(byte) cmdbuf[1] = 0

cmdbuf[0] = 0x80040
(byte) cmdbuf[1] = 1

____________________
blargSNES -- SNES emu for 3DS
More cool stuff

StapleButter
Posted on 12-04-14 08:42 PM Link | #52
Ugh. Apparently it doesn't like it if a usermode app tries to use pdn:d or cdc:DSP, even if they're in the exheader.

____________________
blargSNES -- SNES emu for 3DS
More cool stuff

ichfly
Posted on 01-11-15 05:27 PM Link | #77
booting dsp module

sending pdn:d command 0x000100C0 2 times but the handle for pdn is not set yet so 0 is used yet so nothing happens
1. params = 1, 1, 1
2. params = 0, 0, 0

svcBindInterrupt: numb:0x4a prio:4 ManualClear

check the bit(0) in 0x1ec40000 to 0x1ec40010 (access perm? (just a guess))

StapleButter
Posted on 01-11-15 11:41 PM Link | #78
What, it's trying to access the service without having loaded it prior? Hah.


smea's post about ninjhax inspired me, there might be a way to launch unsigned DSP binaries with something similar, but this is theory.

____________________
blargSNES -- SNES emu for 3DS
More cool stuff

ichfly
Posted on 01-20-15 09:41 PM Link | #81
the GetServiceSessionHandle happens after the calls

ADD: That reversing is from v2048 so I don't know if they fixed it now.

nocash
Posted on 10-12-15 07:18 PM Link | #499
Posted by StapleButter
I wanted to start by the basics and determine how the DSP memory is mapped, and what is what on the DSP side.

DSP RAM goes from 1FF00000 to 1FF7FFFF. So far we have:

1FF00000 - 1FF3FFFF? -> program RAM (DSP exception vectors at 1FF00000+)
1FF40000 - 1FF5FFFF -> data RAM region 1 (1FF50000-1FF5FFFF exposed read-only to ARM11 userland)
1FF60000 - 1FF7FFFF -> data RAM region 2 (1FF70000-1FF7FFFF exposed read-only to ARM11 userland)

Does the program RAM end at 1FF3FFFF or 1FF1FFFF? (if then, what's in the leftover space?)

The DSP can only address 65536 words without switching banks or something in the like. That is, 128K. Assuming the two data RAM regions map to X-RAM and Y-RAM, and the program RAM goes from 1FF00000 to 1FF1FFFF, what would be in the leftover space? DSP-side I/O?

Well uh, clearly this DSP is able to address more than 128K of memory. There has to be a way to select which chunk of memory is being accessed, like on the SNES where they have DBR and PBR to specify which banks the CPU will access.

The docs mention movp and movd instructions, moving from/to data/program RAM. But nothing precises if the regular mov instructions access program RAM or data RAM.


Don't know if that questions do still apply, but anyways:

The DSi uses "MBK" registers http://problemkaputt.de/gbatek.htm#dsinewsharedwramforarm7arm9dsp for mapping WRAM either to DSP or ARM memory at 3000000h-3FFFFFFh. I would assume that the 3DS has some similar "MBK" mapping mechanism (but mapping to 1FF00000h-1FF7FFFFh instead of 3000000h-3FFFFFFh).
Or is there no such mapping stuff on 3DS, and the ARM can access the memory even when the DSP is running?

Yes, Teaklite 1 did support on 16bit addresses. And the (undocumented) Teaklite 2 seems to have been expanded to at least 18bit addresses. The 16bit br/call/bkrep opcodes are using two formerly unused bits to gain 18bit range (except bkrep with imm8, which is still restricted to 16bit). Don't know if/how call+ret are managing 18bit return addresses though.
Mov opcodes must be in fact use some extra "bank" register. Maybe set via the new "load imm2,movpd" opcode, the "PD" might stand for "DataPage" or so. There are some new "movp" ocodes, allowing to use "(Ax)" (instead of 16bit "(Axl)") for program memory addressing, so there would be no "ProgramPage" required in that case.

Normal "mov" opcodes should be always accessing data ram (else executing the opcode fetch and data access in one clock cycle wouldn't work out). The movd/movp opcodes are:
movp = move FROM PROGRAM RAM (to data ram, or to register)
movd = move TO PROGRAM RAM (from data ram)
They could be used for manipulating program code (probably rarely done), or loading constants from program memory (might be done more often, but loading constants from data ram would be ways faster).

---

For the DSi, I have found some teak code in a file called "aac.a" (inside of the NITRO filesystem of the DSi Sound utility). It seems to using COFF format, containing binary and symbolic labels, which would very useful for debugging.
Are there any read-for-use utilities for extracting symbols from COFF files?

Dazzozo
Posted on 10-13-15 06:23 PM Link | #506
Posted by nocash
The DSi uses "MBK" registers http://problemkaputt.de/gbatek.htm#dsinewsharedwramforarm7arm9dsp for mapping WRAM either to DSP or ARM memory at 3000000h-3FFFFFFh. I would assume that the 3DS has some similar "MBK" mapping mechanism (but mapping to 1FF00000h-1FF7FFFFh instead of 3000000h-3FFFFFFh).


Yes, the same mechanism exists: http://3dbrew.org/wiki/PDN_Registers#PDN_SHAREDWRAM_32K_DATA


Main - Reverse-engineering - DSP reverse engineering Hide post layouts | New reply

Page rendered in 0.034 seconds. (2048KB of memory used)
MySQL - queries: 28, rows: 81/81, time: 0.008 seconds.
[powered by Acmlm] Acmlmboard 2.064 (2018-07-20)
© 2005-2008 Acmlm, Xkeeper, blackhole89 et al.