ANESE/roms/tests/apu/blargg_apu_2005.07.30/readme.txt
2017-12-19 16:14:50 -05:00

187 lines
4.7 KiB
Text
Executable file
Vendored

NES APU Frame Counter Update
----------------------------
I have run more tests on the NES APU and come up with new information
about the exact timing of the frame counter and length counter, and some
subtle behavior. The information here either extends or contradicts what
is stated in the NES APU reference and on the nesdev wiki.
Not documented here is a delay when changing modes by writing to $4017.
This is quite complex and I haven't fully worked out its exact
operation. Once determined, documented, and tested, the information here
should still be valid. This delay when changing modes involves the
current mode running a few clocks before switching to the new mode, so
it only affects the rare case where $4017 is written within a few clocks
of a frame counter step. This delay does not cause the steps to occur
any later than shown below; it only causes the first few clocks of the
new mode to be transparent, allowing the previous mode to "show
through".
Also not documented is the exact operation of the envelope, sweep, and
triangle's linear counter when register writes occur close to clocking.
Refer to tests.txt for a description of the test ROMs included.
I have not yet fully updated my APU emulator and tested it with this
information, so report any problems you have with implementation.
Shay <hotpop.com@blargg> (swap to e-mail)
Clock Jitter
------------
Changes to the mode by writing to $4017 only occur on *even* internal
APU clocks; if written on an odd clock, the first step of the mode is
delayed by one clock. At power-up and reset, the APU is randomly in an
odd or even cycle with respect to the first clock of the first
instruction executed by the CPU.
; assume even APU and CPU clocks occur together
lda #$00
sta $4017 ; mode begins in one clock
sta <0 ; delay 3 clocks
sta $4017 ; mode begins immediately
Mode 0 Timing
-------------
-5 lda #$00
-3 sta $4017
0 (write occurs here)
1
2
3
...
Step 1
7459 Clock linear
...
Step 2
14915 Clock linear & length
...
Step 3
22373 Clock linear
...
Step 4
29830 Set frame irq
29831 Clock linear & length and set frame irq
29832 Set frame irq
...
Step 1
37289 Clock linear
...
etc.
Mode 1 Timing
-------------
-5 lda #$80
-3 sta $4017
0 (write occurs here)
Step 0
1 Clock linear & length
2
...
Step 1
7459 Clock linear
...
Step 2
14915 Clock linear & length
...
Step 3
22373 Clock linear
...
Step 4
29829 (do nothing)
...
Step 0
37283 Clock linear & length
...
etc.
Length Halt
-----------
Write to halt flag is delayed by one clock:
$10->$4000 clear halt flag
0 $00->$4017 begin mode 0
14914 $30->$4000 set halt flag
14915 Length not clocked
$10->$4000 clear halt flag
0 $00->$4017 begin mode 0
14915 $30->$4000 set halt flag
Length clocked
$30->$4000 set halt flag
0 $00->$4017 begin mode 0
14914 $10->$4000 clear halt flag
14915 Length clocked
$30->$4000 set halt flag
0 $00->$4017 begin mode 0
14915 $10->$4000 clear halt flag
Length not clocked
Length Reload
-------------
Length reload is completely ignored if written during length clocking
and length counter is non-zero before clocking:
$38->$4003 make length non-zero
0 $00->$4017
14914 Write to $4003
Length reloaded
14915 Length clocked
$38->$4003 make length non-zero
0 $00->$4017
14915 Write to $4003
Length not reloaded
Length clocked
$00->$4015 clear length counter
$01->$4015
0 $00->$4017
14915 Write to $4003
Length reloaded
Length not clocked
Misc
----
- The frame IRQ flag is cleared only when $4015 is read or $4017 is
written with bit 6 set ($40 or $c0).
- The IRQ handler is invoked at minimum 29833 clocks after writing $00
to $4017 (assuming the frame IRQ flag isn't already set, and nothing
else generates an IRQ during that time).
- After reset or power-up, APU acts as if $4017 were written with $00
from 9 to 12 clocks before first instruction begins. It is as if this
occurs (this generates a 10 clock delay):
lda #$00
sta $4017 ; 1
lda <0 ; 9 delay
nop
nop
nop
reset:
...
- As shown, the frame irq flag is set three times in a row. Thus when
polling it, always read $4015 an extra time after the flag is found to
be set, to be sure it's clear afterwards,
wait: bit $4015 ; V flag reflects frame IRQ flag
bvc wait
bit $4015 ; be sure irq flag is clear
or better yet, clear it before polling it:
bit $4015 ; clear flag first
wait: bit $4015 ; V flag reflects frame IRQ flag
bvc wait