mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-03 11:32:43 +01:00
Linted markdown
parent
98315f9a72
commit
6760f6d5de
@ -1,5 +1,4 @@
|
|||||||
## Introduction
|
## Introduction
|
||||||
---
|
|
||||||
|
|
||||||
- There are four known versions of this uCode: the accelerator version, the DMA version, the light version and the SMS version.
|
- There are four known versions of this uCode: the accelerator version, the DMA version, the light version and the SMS version.
|
||||||
- The accelerator version uses the DSP's accelerator to read sound data, whereas the DMA version reads sound data by DMA transfers.
|
- The accelerator version uses the DSP's accelerator to read sound data, whereas the DMA version reads sound data by DMA transfers.
|
||||||
@ -8,14 +7,11 @@
|
|||||||
- The SMS version uses a different communication protocol which requires three sync mails every frame instead of two every 16 PBs. Super Mario Sunshine uses the SMS version (hence its name).
|
- The SMS version uses a different communication protocol which requires three sync mails every frame instead of two every 16 PBs. Super Mario Sunshine uses the SMS version (hence its name).
|
||||||
|
|
||||||
## Details
|
## Details
|
||||||
---
|
|
||||||
|
|
||||||
### Initialization Mails
|
### Initialization Mails
|
||||||
---
|
|
||||||
|
|
||||||
These are all the mails that the game sends to the DSP upon initialization:
|
These are all the mails that the game sends to the DSP upon initialization:
|
||||||
|
|
||||||
|
|
||||||
#### Command 0xE (AKA DsetDMABaseAddr)
|
#### Command 0xE (AKA DsetDMABaseAddr)
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -39,7 +35,6 @@ Note that this command is available only in DMA version.
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Continuous Mails
|
### Continuous Mails
|
||||||
---
|
|
||||||
|
|
||||||
These are all the mails that the game continuously sends to the DSP.
|
These are all the mails that the game continuously sends to the DSP.
|
||||||
|
|
||||||
@ -59,7 +54,6 @@ The Legend of Zelda: Wind Waker keeps sending these forever, alternating between
|
|||||||
|
|
||||||
|
|
||||||
### Synchronization Mails
|
### Synchronization Mails
|
||||||
---
|
|
||||||
|
|
||||||
```
|
```
|
||||||
00000000
|
00000000
|
||||||
@ -76,19 +70,18 @@ The Legend of Zelda: Wind Waker keeps sending these forever, alternating between
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Ending Mails
|
### Ending Mails
|
||||||
---
|
|
||||||
|
|
||||||
`CDD10003`
|
`CDD10003`
|
||||||
Sent by the CPU after DsyncFrame command has completed (and sent 0xDCD10005 to the CPU).
|
Sent by the CPU after DsyncFrame command has completed (and sent 0xDCD10005 to the CPU).
|
||||||
|
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
---
|
|
||||||
|
|
||||||
The first command sent is 0xE. In the real Zelda ucode, this command is dummy. In the ucode used by SMG, it isn't the case.
|
The first command sent is 0xE. In the real Zelda ucode, this command is dummy. In the ucode used by SMG, it isn't the case.
|
||||||
Here is one of the differences between these two ucodes.
|
Here is one of the differences between these two ucodes.
|
||||||
|
|
||||||
For each command:
|
For each command:
|
||||||
|
|
||||||
- The CPU sends one mail whose high part is zero and whose low part represents the number of mails that will follow (non-light versions only).
|
- The CPU sends one mail whose high part is zero and whose low part represents the number of mails that will follow (non-light versions only).
|
||||||
- The CPU sends one mail whose bits 24 to 27 represent the command.
|
- The CPU sends one mail whose bits 24 to 27 represent the command.
|
||||||
- The CPU sends the remaining mails which are the parameters for the command
|
- The CPU sends the remaining mails which are the parameters for the command
|
||||||
@ -102,7 +95,6 @@ The purpose of that whole system is probably to keep mixing synchronous with the
|
|||||||
|
|
||||||
|
|
||||||
## How the Zelda ucode interprets mails
|
## How the Zelda ucode interprets mails
|
||||||
---
|
|
||||||
|
|
||||||
The mails are interpreted by the exception 7 handler.
|
The mails are interpreted by the exception 7 handler.
|
||||||
This means that exception 7 is probably triggered when a new mail was received (by DSP).
|
This means that exception 7 is probably triggered when a new mail was received (by DSP).
|
||||||
@ -112,37 +104,33 @@ The first mail received determines how the following ones will be interpreted:
|
|||||||
|
|
||||||
|
|
||||||
### If G is zero
|
### If G is zero
|
||||||
---
|
|
||||||
|
|
||||||
The whole mail is likely zero. The following mail will be formatted as follows:
|
The whole mail is likely zero. The following mail will be formatted as follows:
|
||||||
`0x000HIIII`
|
`0x000HIIII`
|
||||||
|
|
||||||
The following operation will then be executed:
|
The following operation will then be executed:
|
||||||
|
|
||||||
```
|
```
|
||||||
MEM[0x034E] = ((H+1) << 4);
|
MEM[0x034E] = ((H+1) << 4);
|
||||||
MEM[0x04FC+H] = I;
|
MEM[0x04FC+H] = I;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### If G is non-zero
|
### If G is non-zero
|
||||||
---
|
|
||||||
|
|
||||||
G determines how much mails will follow.
|
G determines how much mails will follow.
|
||||||
The first following mail defines the command number, the next ones define additional parameters depending on the command.
|
The first following mail defines the command number, the next ones define additional parameters depending on the command.
|
||||||
|
|
||||||
Then the mails are stored to memory and will be processed by the message loop.
|
Then the mails are stored to memory and will be processed by the message loop.
|
||||||
|
|
||||||
|
|
||||||
## How to play sound using the Zelda ucode (non-light versions)
|
## How to play sound using the Zelda ucode (non-light versions)
|
||||||
---
|
|
||||||
|
|
||||||
**First of all, keep in mind that the Zelda uCode is under Nintendo's copyright.**
|
**First of all, keep in mind that the Zelda uCode is under Nintendo's copyright.**
|
||||||
We don't recommend releasing apps that would use that uCode. However you're free to play around with it to see how powerful it is.
|
We don't recommend releasing apps that would use that uCode. However you're free to play around with it to see how powerful it is.
|
||||||
|
|
||||||
### Initializing the ucode
|
### Initializing the ucode
|
||||||
---
|
|
||||||
|
|
||||||
If you're using the DMA version, send a DsetDMABaseAddr command, by sending the following mails to the DSP:
|
If you're using the DMA version, send a DsetDMABaseAddr command, by sending the following mails to the DSP:
|
||||||
|
|
||||||
```
|
```
|
||||||
00000002
|
00000002
|
||||||
8E000000
|
8E000000
|
||||||
@ -156,6 +144,7 @@ When reading sound data from main memory, the base address G will be added to th
|
|||||||
For no fancy stuff, we'd recommend setting the DMA base address to the beginning of the ARAM.
|
For no fancy stuff, we'd recommend setting the DMA base address to the beginning of the ARAM.
|
||||||
|
|
||||||
Finally, you need to send a DsetupTable command:
|
Finally, you need to send a DsetupTable command:
|
||||||
|
|
||||||
```
|
```
|
||||||
00000005
|
00000005
|
||||||
8100GGGG
|
8100GGGG
|
||||||
@ -166,6 +155,7 @@ KKKKKKKK
|
|||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
- G is the number of voices
|
- G is the number of voices
|
||||||
- H is the address of the voice parameter blocks (PBs). See below for more info about them.
|
- H is the address of the voice parameter blocks (PBs). See below for more info about them.
|
||||||
- I is the address of a 1280-byte data table. Its purpose isn't known yet.
|
- I is the address of a 1280-byte data table. Its purpose isn't known yet.
|
||||||
@ -174,9 +164,9 @@ where:
|
|||||||
|
|
||||||
|
|
||||||
### Playing sound
|
### Playing sound
|
||||||
---
|
|
||||||
|
|
||||||
The DsyncFrame command is responsible for mixing, so if you want to hear any sound, you need to send DsyncFrame commands regularly:
|
The DsyncFrame command is responsible for mixing, so if you want to hear any sound, you need to send DsyncFrame commands regularly:
|
||||||
|
|
||||||
```
|
```
|
||||||
00000005
|
00000005
|
||||||
82GGHHHH
|
82GGHHHH
|
||||||
@ -187,6 +177,7 @@ JJJJJJJJ
|
|||||||
```
|
```
|
||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
- G is the number of frames
|
- G is the number of frames
|
||||||
- H is some unknown number
|
- H is some unknown number
|
||||||
- I is the address of right output buffers
|
- I is the address of right output buffers
|
||||||
@ -195,6 +186,7 @@ where:
|
|||||||
For each frame to render, there is a right buffer of 80 samples, and a left buffer of same capacity.
|
For each frame to render, there is a right buffer of 80 samples, and a left buffer of same capacity.
|
||||||
|
|
||||||
After you sent a DsyncFrame, you need, for each frame, to send sync mails:
|
After you sent a DsyncFrame, you need, for each frame, to send sync mails:
|
||||||
|
|
||||||
```
|
```
|
||||||
00000000
|
00000000
|
||||||
000GHHHH
|
000GHHHH
|
||||||
@ -209,11 +201,13 @@ Then it sends two mails: `0xDCD10004` and `0xF355FFXX`, to indicate the current
|
|||||||
Then it processes the next frame.
|
Then it processes the next frame.
|
||||||
|
|
||||||
When the uCode finished processing all the frames, it sends a `0xDCD10005` mail and triggers an interrupt. Then you must send a last mail:
|
When the uCode finished processing all the frames, it sends a `0xDCD10005` mail and triggers an interrupt. Then you must send a last mail:
|
||||||
|
|
||||||
```
|
```
|
||||||
CDD1000G
|
CDD1000G
|
||||||
```
|
```
|
||||||
|
|
||||||
where G is the task to execute, as follows:
|
where G is the task to execute, as follows:
|
||||||
|
|
||||||
- 0: Halt
|
- 0: Halt
|
||||||
- 1: Dump
|
- 1: Dump
|
||||||
- 2: Do something and halt
|
- 2: Do something and halt
|
||||||
@ -229,7 +223,6 @@ Phew. Now that your DsyncFrame successfully completed, you have to send another
|
|||||||
|
|
||||||
|
|
||||||
## The parameter blocks
|
## The parameter blocks
|
||||||
---
|
|
||||||
|
|
||||||
Like the well-known AX ucode, the Zelda ucode uses one parameter block (PB) per voice. (The number of voices is set by DsetupTable command).
|
Like the well-known AX ucode, the Zelda ucode uses one parameter block (PB) per voice. (The number of voices is set by DsetupTable command).
|
||||||
It also uses 4 much smaller PBs which seem to be used for something like reverb...
|
It also uses 4 much smaller PBs which seem to be used for something like reverb...
|
||||||
@ -290,12 +283,14 @@ Here is a table of what has been figured out inside these PBs (some parts of it
|
|||||||
| 0x90 | 48 | Padding |
|
| 0x90 | 48 | Padding |
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- The last 64 words (128 bytes) are read-only. The ucode reads them from memory but never writes them back.
|
- The last 64 words (128 bytes) are read-only. The ucode reads them from memory but never writes them back.
|
||||||
- The read offset and start offset are exprimed in bytes. They're offsets in ARAM, except in SMG ucode where they're offsets in main memory (minus DMA base set by command 0xE).
|
- The read offset and start offset are exprimed in bytes. They're offsets in ARAM, except in SMG ucode where they're offsets in main memory (minus DMA base set by command 0xE).
|
||||||
- The lengths and loop start positions are exprimed in samples.
|
- The lengths and loop start positions are exprimed in samples.
|
||||||
- When processing blank voices the ucode fills the temporary buffer with the value at offset 0x33 in PB.
|
- When processing blank voices the ucode fills the temporary buffer with the value at offset 0x33 in PB.
|
||||||
|
|
||||||
List of available sound formats:
|
List of available sound formats:
|
||||||
|
|
||||||
- 0x0000: Square wave
|
- 0x0000: Square wave
|
||||||
- 0x0001: Saw wave
|
- 0x0001: Saw wave
|
||||||
- 0x0002: Square+saw?
|
- 0x0002: Square+saw?
|
||||||
@ -315,7 +310,6 @@ List of available sound formats:
|
|||||||
|
|
||||||
|
|
||||||
## Unknown Registers?
|
## Unknown Registers?
|
||||||
---
|
|
||||||
|
|
||||||
The Zelda ucode accesses a memory region at 0xFF8X. At glance you may think it's accessing unknown DSP registers, but this is not the case.
|
The Zelda ucode accesses a memory region at 0xFF8X. At glance you may think it's accessing unknown DSP registers, but this is not the case.
|
||||||
This region is always accessed by lrs/srs opcodes, while CR is set to 0x0004.
|
This region is always accessed by lrs/srs opcodes, while CR is set to 0x0004.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user