fds_apu: correct modulator bias values at table indices 3 and 5

The FDS modulator unit's per-step bias table is documented on the
nesdev wiki and used in MDFN, NSFPlay, and negativeExponent's
fceumm_next as { 0, +1, +2, +4, RESET, -4, -2, -1 }.  The conditional
form in this file expanded to { 0, +1, +2, +3, RESET, -3, -2, -1 } -
producing the wrong magnitude at indices 3 and 5 where real hardware
takes a power-of-2 step.

Replace the conditional with a literal lookup table matching the
hardware.  Bit-identical for mod table values 0, 1, 2, 4, 6, 7; only
indices 3 and 5 change.

This is a step toward #560 (VS Excitebike FDS triangle pitch) but
unlikely to resolve it on its own.  The modulator's deeper bug is
that this file is missing the sweep_bias integrator entirely: real
hardware accumulates the bias steps over time and the resulting
running total scales the carrier frequency adjustment, whereas this
implementation applies each mod table entry's bias instantaneously to
the b8shiftreg88 sub-clock gating without accumulation.  Tracked
separately; the structural fix needs the modulator unit rebuilt
around an sweep_bias accumulator (or a wholesale backport of
_next's fds_apu rewrite).
This commit is contained in:
libretroadmin
2026-06-14 16:57:27 +00:00
committed by U-DESKTOP-SPFP6AQ\twistedtechre
parent 3f23e2b98f
commit 2a91d40f4d

View File

@@ -166,14 +166,21 @@ static INLINE void ClockRise(void) {
if (!(SPSG[0x7] & 0x80)) {
int t = fdso.mwave[(b17latch76 >> 13) & 0x1F] & 7;
int t2 = amplitude[1];
int adj = 0;
if ((t & 3)) {
if ((t & 4))
adj -= (t2 * ((4 - (t & 3))));
else
adj += (t2 * ((t & 3)));
}
int adj;
/* Per-step bias the modulator unit applies for each
* 3-bit mod table entry. Real hardware uses powers of
* 2 ({-4,-2,-1,0,+1,+2,+4} + RESET); the conditional
* form previously here computed { +/- (4 - (t & 3)) }
* for the negate cases and { +/- (t & 3) } for the
* positive cases, yielding ±3 instead of ±4 at table
* positions 3 and 5. Documented at nesdev wiki
* "FDS audio" / Modulator unit; same table is used in
* MDFN/NSFPlay and negativeExponent's fceumm_next. */
static const int8_t mod_bias_tab[8] = {
0, 1, 2, 4,
0, -4, -2, -1
};
adj = t2 * mod_bias_tab[t];
adj *= 2;
if (adj > 0x7F) adj = 0x7F;
if (adj < -0x80) adj = -0x80;