ANESE/roms/tests/apu/blargg_apu_2005.07.30
2017-12-19 16:14:50 -05:00
..
source misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
01.len_ctr.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
02.len_table.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
03.irq_flag.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
04.clock_jitter.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
05.len_timing_mode0.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
06.len_timing_mode1.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
07.irq_flag_timing.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
08.irq_timing.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
09.reset_timing.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
10.len_halt_timing.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
11.len_reload_timing.nes misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
readme.txt misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00
tests.txt misc cleanup + some apu tests 2017-12-19 16:14:50 -05:00

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