APU DMC: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
m (Parodius Da? more like Parodius DEL)
(→‎Likely internal implementation of the read: This bug is not present in PAL NESes)
Line 164: Line 164:
The 6502 cannot be pulled off of the bus normally. The 2A03 DMC gets around this by pulling RDY low internally. This causes the CPU to pause during the next read cycle, until RDY goes high again. The DMC unit holds RDY low for 4 cycles. The first three cycles it idles, as the CPU could have just started an interrupt cycle, and thus be writing for 3 consecutive cycles (and thus ignoring RDY). On the fourth cycle, the DMC unit drives the next sample address onto the address lines, and reads that byte from memory. It then drives RDY high again, and the CPU picks up where it left off.
The 6502 cannot be pulled off of the bus normally. The 2A03 DMC gets around this by pulling RDY low internally. This causes the CPU to pause during the next read cycle, until RDY goes high again. The DMC unit holds RDY low for 4 cycles. The first three cycles it idles, as the CPU could have just started an interrupt cycle, and thus be writing for 3 consecutive cycles (and thus ignoring RDY). On the fourth cycle, the DMC unit drives the next sample address onto the address lines, and reads that byte from memory. It then drives RDY high again, and the CPU picks up where it left off.


This matters, because it can interfere with the expected operation of any register where reads have a side effect: the controller registers ($4016 and $4017), reads of the PPU status register ($2002), and reads of VRAM/VROM data ($2007) if they happen to occur in the same cycle that the DMC unit pulls RDY low.
This matters, because on NTSC NES and Famicom, it can interfere with the expected operation of any register where reads have a side effect: the controller registers ($4016 and $4017), reads of the PPU status register ($2002), and reads of VRAM/VROM data ($2007) if they happen to occur in the same cycle that the DMC unit pulls RDY low.


For the controller registers, this can cause an extra rising clock edge to occur, and thus shift an extra bit out. For the others, the PPU will see multiple reads, which will cause extra increments of the address latches, or clear the vblank flag.
For the controller registers, this can cause an extra rising clock edge to occur, and thus shift an extra bit out. For the others, the PPU will see multiple reads, which will cause extra increments of the address latches, or clear the vblank flag.
This problem has been fixed on the 2A07 and PAL NES is exempt of this bug.


== Usage of DMC for syncing to video ==
== Usage of DMC for syncing to video ==

Revision as of 21:04, 19 September 2012

The NES APU's delta modulation channel (DMC) can output 1-bit delta-encoded samples or can have its 7-bit counter directly loaded, allowing flexible manual sample playback.

The DMC channel contains the following: memory reader, interrupt flag, sample buffer, timer, output unit, 7-bit counter.

                        Timer
                          |
                          v
Reader ---> Buffer ---> Output ---> Counter ---> (to the mixer)
$4010 IL--.FFFF Flags and frequency (write)
bit 7 I--- ---- IRQ enabled flag. If clear, the interrupt flag is cleared.
bit 6 -L-- ---- Loop flag
bits 3-0 ---- RRRR Rate index
Rate   $0   $1   $2   $3   $4   $5   $6   $7   $8   $9   $A   $B   $C   $D   $E   $F
      ------------------------------------------------------------------------------
NTSC  428, 380, 340, 320, 286, 254, 226, 214, 190, 160, 142, 128, 106,  84,  72,  54
PAL   398, 354, 316, 298, 276, 236, 210, 198, 176, 148, 132, 118,  98,  78,  66,  50
 
$4011 -DDD.DDDD Direct load (write)
bits 6-0 -DDD DDDD The counter is loaded with D. If a sample is currently playing, the counter is occasionally not changed properly.
 
$4012 AAAA.AAAA Sample address (write)
bits 7-0 AAAA AAAA Sample address = %11AAAAAA.AA000000
 
$4013 LLLL.LLLL Sample length (write)
bits 7-0 LLLL LLLL Sample length = %LLLL.LLLL0001

The counter's value is sent to the mixer. It is loaded with 0 on power-up.

Automatic 1-bit delta-encoded sample playback is carried out by a combination of three units. The memory reader fills the 8-bit sample buffer whenever it is emptied by the sample output unit. The status register is used to start and stop automatic sample playback.

The sample buffer either holds a single 8-bit sample byte or is empty. It is filled by the reader and can only be emptied by the output unit; once loaded with a sample byte it will be played back.

Pitch table

NTSC PAL
$4010 Period Frequency Note Period Frequency Note
$0 $1AC 4181.71 Hz C-8 -1.78c $18E 4177.40 Hz C-8 -3.56c
$1 $17C 4709.93 Hz D-8 +4.16c $162 4696.63 Hz D-8 -.739c
$2 $154 5264.04 Hz E-8 -3.29c $13C 5261.41 Hz E-8 -4.15c
$3 $140 5593.04 Hz F-8 +1.67c $12A 5579.22 Hz F-8 -2.61c
$4 $11E 6257.95 Hz G-8 -3.86c $114 6023.94 Hz F#8 +30.2c
$5 $0FE 7046.35 Hz A-8 +1.56c $0EC 7044.94 Hz A-8 +1.22c
$6 $0E2 7919.35 Hz B-8 +3.77c $0D2 7917.18 Hz B-8 +3.29c
$7 $0D6 8363.42 Hz C-9 -1.78c $0C6 8397.01 Hz C-9 +5.16c
$8 $0BE 9419.86 Hz D-9 +4.16c $0B0 9446.63 Hz D-9 +9.07c
$9 $0A0 11186.1 Hz F-9 +1.67c $094 11233.8 Hz F-9 +9.04c
$A $08E 12604.0 Hz G-9 +8.29c $084 12595.5 Hz G-9 +7.11c
$B $080 13982.6 Hz A-9 -12.0c $076 14089.9 Hz A-9 +1.22c
$C $06A 16884.6 Hz C-10 +14.5c $062 16965.4 Hz C-10 +22.7c
$D $054 21306.8 Hz E-10 +17.2c $04E 21315.5 Hz E-10 +17.9c
$E $048 24858.0 Hz G-10 -15.9c $042 25191.0 Hz G-10 +7.11c
$F $036 33143.9 Hz C-11 -17.9c $032 33252.1 Hz C-11 -12.2c

(Deviation from note is given in cents, which are defined as 1/100 of a semitone.)

Memory reader

When the sample buffer is emptied, the memory reader fills the sample buffer with the next byte from the currently playing sample. It has an address counter and a bytes remaining counter.

When a sample is (re)started, the current address is set to the sample address, and bytes remaining is set to the sample length.

Any time the sample buffer is in an empty state and bytes remaining is not zero, the following occur:

  • The CPU is stalled for up to 4 CPU cycles to allow the longest possible write (the return address and write after an IRQ) to finish. If OAM DMA is in progress, it is paused for two cycles.[1]
  • The sample buffer is filled with the next sample byte read from the current address, subject to whatever mapping hardware present.
  • The address is incremented; if it exceeds $FFFF, it is wrapped around to $8000.
  • The bytes remaining counter is decremented; if it becomes zero and the loop flag is set, the sample is restarted (see above); otherwise, if the bytes remaining counter becomes zero and the IRQ enabled flag is set, the interrupt flag is set.

At any time, if the interrupt flag is set, the CPU's IRQ line is continuously asserted until the interrupt flag is cleared. The processor will continue on from where it was stalled.

Output unit

The output unit continuously outputs a 7-bit value to the mixer. It contains an 8-bit right shift register, a bits-remaining counter, a 7-bit delta-counter, and a silence flag.

When an output cycle ends, a new cycle is started as follows:

  • The bits-remaining counter is loaded with 8.
  • If the sample buffer is empty, then the silence flag is set; otherwise, the silence flag is cleared and the sample buffer is emptied into the shift register.

When the timer outputs a clock, the following actions occur in order:

  1. If the silence flag is clear, bit 0 of the shift register is applied to the counter as follows: if bit 0 is clear and the delta-counter is greater than 1, the counter is decremented by 2; otherwise, if bit 0 is set and the delta-counter is less than 126, the counter is incremented by 2.
  2. The right shift register is clocked.
  3. The bits-remaining counter is decremented. If it becomes zero, a new cycle is started.

Nothing can interrupt a cycle; every cycle runs to completion before a new cycle is started.

Likely internal implementation of the read

The following is speculation, and thus not necessarily 100% accurate. It does accurately predict observed behavior.

The 6502 cannot be pulled off of the bus normally. The 2A03 DMC gets around this by pulling RDY low internally. This causes the CPU to pause during the next read cycle, until RDY goes high again. The DMC unit holds RDY low for 4 cycles. The first three cycles it idles, as the CPU could have just started an interrupt cycle, and thus be writing for 3 consecutive cycles (and thus ignoring RDY). On the fourth cycle, the DMC unit drives the next sample address onto the address lines, and reads that byte from memory. It then drives RDY high again, and the CPU picks up where it left off.

This matters, because on NTSC NES and Famicom, it can interfere with the expected operation of any register where reads have a side effect: the controller registers ($4016 and $4017), reads of the PPU status register ($2002), and reads of VRAM/VROM data ($2007) if they happen to occur in the same cycle that the DMC unit pulls RDY low.

For the controller registers, this can cause an extra rising clock edge to occur, and thus shift an extra bit out. For the others, the PPU will see multiple reads, which will cause extra increments of the address latches, or clear the vblank flag.

This problem has been fixed on the 2A07 and PAL NES is exempt of this bug.

Usage of DMC for syncing to video

The following method is discussed here

Concept

The NES hardware only has limited tools for syncing the code with video rendering. The VBlank NMI and sprite zero hit are the only two reasonably reliable flags that can be used, so only 2 synchronizations per frame are doable easily. In addition, only the VBlank NMI can trigger an interrupt, the sprite zero flag has to be polled, potentially wasting a lot of CPU cycles.

However, the DMC channel can hypothetically be used for syncing with video instead of using it for sound. Unfortunately it's a bit complicated, but used correctly, it can function as a crude scanline counter, eliminating the need for an advanced mapper.

The DMC's timing is completely separate from the video (obviously, it being an audio component). The DMC's timer is always running, and samples can only start every 8 clocks. However, because the DMC's timer isn't synchronized to the PPU in any way, these 8-clock boundaries occur on different scanlines each frame.

To achieve stable timing, this is what you do:

  • At a fixed time in rendering (we'll use the start of vblank as an example), start a dummy single-byte sample at rate $F. Due to a hardware quirk*, the sample needs to be started three times in a row like this:
 sei
 lda #$10 
 sta $4015 
 sta $4015 
 sta $4015 
 cli
  • Use any method to count how many cycles pass before the DMC IRQ happens (you can use an actual IRQ, or poll $4015).
    • At rate $F, there are 54 cpu cycles between clocks, so there are 432 cpu cycles ((432 * 3) / 341 = about 3.8 scanlines) between boundaries. Your measurement - 432 = the amount of time you need to wait after a DMC IRQ, in order to synchronize with vblank.
  • Start the actual sample that will be used for the timing.
  • When the IRQ happens, use your measurement from before to delay your program, and you'll synchronize the interrupt to vblank.

Note: The hardware quirk mentioned above deals with how DMC IRQs are generated. Basically, the IRQ is generated when the last byte of the sample is read, not when the last sample of the sample plays. The sample buffer sometimes has enough time to empty itself between your writes to $4015, meaning your next write to $4015 will trigger an immediate IRQ. Fortunately, writing to $4015 three times will avoid this issue.

Still using vblank as an example, the measurement you take will tell you how far into the 8-clock boundary vblank occured, and by delaying after a DMC IRQ, you can perform a raster effect at the same point within the 8-clock boundary, aligning it with vblank. If you perform this same method each frame, your raster effect will have a reasonably stable timing to it. As a bonus, since you're mostly using IRQs, the CPU is free to do something else, instead of waiting in a timed loop.

It's possible to use more than one IRQ per frame - but you need to do the measurement part at the same time within each frame, before you use any of the IRQs.

You can only have one split-point per IRQ, with the shortest IRQ being 3.8 scanlines. If you want them closer together, you must use timed code.

You should also make sure your samples are made up of all $00 bytes, and that you've written $00 to $4011 at some point. Otherwise, you might unintentionally create audio. This is a sound channel, after all.

Timing table

This table converts sample length in scanline length (all values are rounded to the higher integer).

NTSC               Rate 
Length              $0    $1   $2   $3   $4   $5   $6   $7   $8   $9   $a   $b   $c   $d   $e   $f 
---------------------------------------------------------------------------------------------------- 
1-byte (8 bits)     31    27   24   23   21   18   16   16   14   12   10   10   8    6    6    4 
17-byte (136 bits)  **    **   **   **   **   **   **   **   228  192  170  154  127  101  87   65 
33-byte (264 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   196  168  126 
49-byte (392 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   **   **   187 
PAL                Rate 
Length              $0    $1   $2   $3   $4   $5   $6   $7   $8   $9   $a   $b   $c   $d   $e   $f 
---------------------------------------------------------------------------------------------------- 
1-byte (8 bits)     30    27   24   23   21   18   16   15   14   12   10   9    8    6    5    4 
17-byte (136 bits)  **    **   **   **   **   **   **   **   225  189  169  151  126  100  85   64 
33-byte (264 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   194  164  124 
49-byte (392 bits)  **    **   **   **   **   **   **   **   **   **   **   **   **   **   **   184

Number of scanlines to wait table

This table gives the best sample length and frequency combinations for all possible scanlines interval to wait. They are best because they are where the CPU will have to kill the less time. However it's still possible to use options to wait for fewer lines and kill more time during the interrupt before the video effect.

Because a PAL interrupt will always happen about the same time or a bit sooner than a NTSC interrupt, the NTSC table will be used to set the "best" setting here :

Scanlines  Best opt. for IRQ 

1-3        Timed code 
4-5        Length $0, rate $f 
6-7        Length $0, rate $d 
8-9        Length $0, rate $c 
10-11      Length $0, rate $a 
12-13      Length $0, rate $9 
14-15      Length $0, rate $8 
16-17      Length $0, rate $6 
18-20      Length $0, rate $5 
21-22      Length $0, rate $4 
23         Length $0, rate $3 
24-26      Length $0, rate $2 
27-30      Length $0, rate $1 
31-64      Length $0, rate $0 
65-86      Length $1, rate $f 
87-100     Length $1, rate $e 
101-125    Length $1, rate $d 
126        Length $2, rate $f 
127-153    Length $1, rate $c 
154-167    Length $1, rate $b 
168-169    Length $2, rate $e 
170-186    Length $1, rate $a 
187-191    Length $3, rate $f 
192-195    Length $1, rate $9 
196-227    Length $2, rate $d 
228-239    Length $1, rate $8