| ||
| Views: 33,115,549 | Homepage | Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search | 09-05-26 11:02 AM |
| Guest: | ||
| 0 users reading DSP binary notes | 1 bot |
| Main - Development - DSP binary notes | Hide post layouts | New reply |
| Arisotura |
| ||
![]() Big fire melon magical melon girl Level: 65
Posts: 1011/1136 EXP: 2248398 Next: 87230 Since: 03-28-17 From: France Last post: 61 days ago Last view: 5 days ago |
so far, this is about what I observe with the Let's Golf DSP binary. the basic idea is to observe the comm protocol and figure out how it works, so we can HLE it.
basic idea is that most DSP titles have ucodes with pretty similar feature sets, and likely share a same base protocol. then there's shit like the AAC binary in the DSi sound app, that's something else... but we'll work on it, too. so. Let's Golf basic info commands are sent by using the CMD registers to signal a new command then writing parameters over the DSP pipe (a FIFO buffer in DSP memory). there are two separate channels for commands. CMD0 seems to be graphics stuff: * 0001 = scaling * 0002 = yuv2rgb CMD2 seems to be audio stuff: * 0002 = play sound? CMD2 serves to tell the other side that data was just written in a given pipe other binaries have more commands, but prolly the same base shit. init after loading the binary and starting the DSP, the ARM9 checks CMD0/1/2. when all 3 registers return 1, the DSP is ready. DSP sends a pointer to DSPiPipeMonitor over CMD2. address is 0x08D2 in Let's Golf. table contains 16 pipe entries, 5 words each: 00: base address of FIFO buffer (in DSP memory) 01: length of FIFO buffer in bytes 02: read pointer in bytes 03: write pointer in bytes 04: pipe index first FIFO buffer is at 0x0922. each buffer is 0x100 words long (ie 0x200 bytes). the pipes are as follows, according to Gericom's DSP code: 0: console, in 1: console, out 2: DMA, in 3: DMA, out 4: audio, in 5: audio, out 6: binary, in 7: binary, out 8: temp, in 9: temp, out 10-15: ??? 'in'/'out' seem to be from the viewpoint of the ARM9 (ie. 'out' = ARM9 sending data to DSP). 'console' would be a debug console? not sure if it's used in retail binaries. 'DMA' would be to arrange DMA transfers? not sure. 'audio' is for anything pertaining to audio playback. 'binary' seems to be for specific commands, ie. scaling/yuv2rgb for Let's Golf, AAC stuff for the DSi sound app, ... no idea what 'temp' is about. graphics commands * command ID is sent via CMD0 * command parameters are written into pipe 7 * pipe write pointer is updated * pipe index is sent via CMD2 * DSP responds by re-sending pipe index over CMD2 (to signal command/data reception?) * DSP sends 0001 over CMD1 (to signal it's ready?) command 0001: scaling parameters: 14 words 01/00: src ARM9 address 03/02: dst ARM9 address 04: filtering 05: src width 06: src height 07: width scale 08: height scale 09: rect X offset 0A: rect Y offset 0B: rect width 0C: rect height 0D: 'reserved' / garbage the provided dst width/height are expressed unscaled. for example: src=256x192, rect=256x192, scale=500/500 (ie half), will result in a 128x96 output size. the rect width/height affect how big the output bitmap is, but the scaling itself only uses the scale factors. basically, src width/height define the source bitmap, and rect X/Y/width/height define which section of it is taken - and scaled. the stride for the destination bitmap will be (rect width * X scale) / 1000. scale factors work as follows: (presumably) * dst width = (params[0B] * params[07]) / 1000 * dst height = (params[0C] * params[08]) / 1000 settings can add sub-offsets and shit, too... filtering modes: * 1: nearest neighbor * 2: bilinear * 3: bicubic * 10: 1/3 scaling * anything else: nearest neighbor mode 10 requires that the rect width/height be multiples of 3 (otherwise it just fails). in this mode, the X/Y scale values are ignored, and the bitmap is scaled down to 1/3 of the original size. rect X/Y still apply. https://en.wikipedia.org/wiki/Bicubic_interpolation bicubic scaling seems to use a = -1.0 in the convolution formula. 1/3 scaling works by reading a 3x3 block of source pixels and averaging the values of the 8 outer pixels. command 0002: yuv2rgb parameters: 6 words 01/00: length in bytes 03/02: src ARM9 address 05/04: dst ARM9 address algorith implemented is similar to this: https://github.com/Epicpkmn11/dsi-camera/blob/master/arm9/source/main.c#L11-L14 basically it's heavily based on bitshifts the equivalent multiplication-based formula is as follows * R = Y + ((V * 359 * 256) >> 16) * G = Y - ((((U * 352) + (V * 731)) * 256) >> 18) * B = Y + ((U * 1815 * 256) >> 18) ____________________ Kuribo64 |
| Arisotura |
| ||
![]() Big fire melon magical melon girl Level: 65
Posts: 1017/1136 EXP: 2248398 Next: 87230 Since: 03-28-17 From: France Last post: 61 days ago Last view: 5 days ago |
the AAC decoder ucode (DSi sound app)
(it also has the standard "play sound"/"sample mic" stuff, which seems common to all ucodes) commands and parameters are sent over CMD1. it doesn't use the pipe. first word is the command ID, but only command 1 is supported. ARM9 sends command 0 right before the first command 1. the ucode ignores it. command 1: decode AAC frame 00: command ID (0001) 01: input frame length 02: sampling frequency hi (bit16-31) 03: sampling frequency lo (bit0-15) 04: channel setup 05: input ARM9 address hi 06: input ARM9 address lo 07: left output ARM9 address hi 08: left output ARM9 address lo 09: right output ARM9 address hi 0A: right output ARM9 address lo the output buffers must be 0x800 bytes long. an AAC frame produces 1024 samples of output. error code 1 is returned if any of those conditions are met: * input frame length is 0 or greater than 1700 * frequency is 0 or greater than 48000 * channel setup is any value other than 1 or 2 * input frame address is 0 * left output address is 0 * channel setup is not 1 and right output address is 0 frequency must be one of those: 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000. if it's any other value, it will fail to initialize the decoder (but the return value from that is ignored, so it just uses whatever the previous state was?) response is sent over REPLY0: 0 = success 1 = incorrect parameters 2 = decoding failure it seems that the ucode can fail to decode data if frames are sent in too fast? - given a MP4 file (.m4a), the input data the ucode receives comes from the file's mdat chunk. the stsz chunk defines the size of each frame. the mp4a chunk contains info like the number of channels and sampling frequency. the same data is found in a .aac file, but the structure/metadata are different. ____________________ Kuribo64 |
| Arisotura |
| ||
![]() Big fire melon magical melon girl Level: 65
Posts: 1018/1136 EXP: 2248398 Next: 87230 Since: 03-28-17 From: France Last post: 61 days ago Last view: 5 days ago |
audio commands
command set seems common to all ucodes * command parameters are written into pipe 5 * pipe write pointer is updated * pipe index is sent via CMD2 * DSP responds by re-sending pipe index over CMD2 (to signal command/data reception?) * DSP sends 0004 over CMD2 (to signal new data in pipe 4) * ARM9 reads data in pipe 4 * pipe read pointer is updated * ARM9 sends pipe index over CMD2 (to signal that it has received the data?) command parameters: 8 words 00: command mask hi 01: command mask lo 02: ARM9 addr hi 03: ARM9 addr lo 04: length hi 05: length lo 06: reserved 07: reserved command must be 8 words - anything less is ignored example command: 0000 1102 0220 E10C 0000 1FDD 0000 0000 command mask bit1: volume (0=normal, 1=half) bit8-11: command bit12-15: command type (1=output, 2=input) command meaning varies depending on the command type for command type 1: must be 1. 1=play sound for command type 2: values 1 or 2 are possible. 1=start, 2=stop? data is PCM16. length is in samples. frequency is the same as the I2S output frequency. volume bit isn't supported by the DSi sound app ucode. all the more recent ucodes support it. response: 4 words (sent over pipe 4) response to "play sound" command: sent when sound is finished 00: 0000 01: 1200 02: ??? hi 03: ??? lo example response (to above command): 0000 1200 0000 0000 the first couple words might follow a format similar to the command mask above (ie. 1200 = output, stop). in practice, they are hardcoded. the last couple words seem to be some remaining length? they're always zero. maybe error cases produce different values? mic sampling is different: it doesn't use the addr/len params instead, it responds with the command word and an address in DSP memory address to the FIFO buffer for mic data. it doesn't DMA to ARM9 RAM. buffer is 0x1000 words long, plus 3 words of header: 00: pointer to buffer data 01: buffer length 02: write cursor within buffer typically, buffer is just after this DSP doesn't provide any "stop after X length" or alert mechanism for this, so one would have to set up a timer for this ____________________ Kuribo64 |
| Arisotura |
| ||
![]() Big fire melon magical melon girl Level: 65
Posts: 1020/1136 EXP: 2248398 Next: 87230 Since: 03-28-17 From: France Last post: 61 days ago Last view: 5 days ago |
G711
commands are sent over pipe 7 the command is 8 words 00: command hi 01: command lo 02: source addr hi 03: source addr lo 04: dest addr hi 05: dest addr lo 06: length hi 07: length lo length is in samples response is 2 words, sent over pipe 6 response seems to be the length that was processed command mask: bit0-7 = encoding (1=A-law, 2=ยต-law) bit8-11 = task (1=encode, other=decode) ____________________ Kuribo64 |
| Main - Development - DSP binary notes | Hide post layouts | New reply |
|
Page rendered in 0.108 seconds. (2048KB of memory used) MySQL - queries: 29, rows: 83/83, time: 0.050 seconds.
Acmlmboard 2.064 (2018-07-20)© 2005-2008 Acmlm, Xkeeper, blackhole89 et al. |