Skip to content

APU: various channel bugs (sequencer reset, length counter gating, timer stepping, noise LFSR) #609

Description

@bfirsh

Summary

Several APU channel bugs:

1. Square sequencer not reset on $4003/$4007 write

Per nesdev APU Pulse, writing the 4th register ($4003 or $4007) resets the duty cycle sequencer to step 0. The code (channel-square.js:158-168) only sets envReset = true but never resets squareCounter. This affects note attack timing.

2. Triangle/Noise length counters loaded when channel disabled

channel-triangle.js:72 and channel-noise.js:85 load the length counter without checking isEnabled. Per the wiki, the length counter should only be loaded when the channel's enable flag ($4015) is set.

3. Square timer uses if instead of while (papu/index.js:256, 266)

The triangle channel correctly uses while for its timer, but the square channels use if. At high frequencies with long CPU instructions, multiple sequencer steps can be missed within a single timer period.

4. Noise LFSR shifts left instead of right (papu/index.js:286)

Real hardware shifts the 15-bit LFSR right with feedback from bit 0. The code shifts left and tests bit 15. While both produce pseudo-random sequences, the exact output differs.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    accuracyHardware accuracy improvementbugcomponent: apuAPU / audio (papu/)difficulty: mediumModerate change requiring understanding of one subsystempriority: mediumIncorrect behavior for specific games or edge cases

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions