Skip to content

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

@bfirsh

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

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