From 185362e6cd1c0f668a186adde2522da2f0d45307 Mon Sep 17 00:00:00 2001 From: Guy Perfect Date: Mon, 24 Feb 2025 13:44:26 -0600 Subject: [PATCH] Fix BKCOL debug writes, more VSU edge cases --- core/vip.c | 2 +- core/vsu.c | 86 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/core/vip.c b/core/vip.c index c898ed5..3cef9e9 100644 --- a/core/vip.c +++ b/core/vip.c @@ -546,7 +546,7 @@ static void vipWriteIO( break; case 0x5F870>>1: /* BKCOL */ - sim->vip.bkcol = (sim->vip.bkcol & mask) | (value & 3 * ~mask); + sim->vip.bkcol = (sim->vip.bkcol & mask) | (value & 3 & ~mask); break; } diff --git a/core/vsu.c b/core/vsu.c index 8ed69e7..971e507 100644 --- a/core/vsu.c +++ b/core/vsu.c @@ -50,7 +50,7 @@ static uint8_t vsuCheckFreqMod(VB *sim) { return sim->vsu.freqmod.enb && sim->vsu.freqmod.interval != 0 && ( - !sim->vsu.freqmod.modmask || ( + sim->vsu.freqmod.modmask != 2 || ( sim->vsu.freqmod.func == 1 && sim->vsu.freqmod.rep ) @@ -62,6 +62,12 @@ static uint8_t vsuCheckFreqMod(VB *sim) { static void vsuNextFreqMod(VB *sim, Channel *chan) { int32_t next; + /* Modulation mask control */ + if (sim->vsu.freqmod.modmask == 1 && sim->vsu.freqmod.func == 1) { + sim->vsu.freqmod.modmask = 2; + chan->freqmod = vsuCheckFreqMod(sim); + } + /* Sweep */ if (sim->vsu.freqmod.func == 0) { next = chan->freq.current >> sim->vsu.freqmod.shift; @@ -76,35 +82,31 @@ static void vsuNextFreqMod(VB *sim, Channel *chan) { /* Modulation */ else { - - /* Compute the modulated value */ next = (int32_t) chan->freq.written + sim->vsu.modulation[sim->vsu.freqmod.sample]; if (next < 0) next = 0; if (next > 2047) next = 2047; - - /* Not the final modulation sample */ - if (sim->vsu.freqmod.sample != 31) - sim->vsu.freqmod.sample++; - - /* Last modulation sample processed */ - else { - sim->vsu.freqmod.modmask = 1; - if (sim->vsu.freqmod.rep) - sim->vsu.freqmod.sample = 0; - } - } /* Configure state */ - sim->vsu.freqmod.next = next; + if (chan->freqmod) + sim->vsu.freqmod.next = next; +} + +/* Advance the noise channel's shift register */ +static void vsuNextNoise(VB *sim) { + uint32_t bit = (( + sim->vsu.noise.register_ >> NOISE_TAPS[sim->vsu.noise.tap] ^ + sim->vsu.noise.register_ >> 7 + ) & 1) ^ 1; + sim->vsu.noise.register_ = bit | + (sim->vsu.noise.register_ << 1 & 0x7FFE); } /* Process one channel */ static void vsuEmulateChannel(VB *sim, Channel *chan) { - uint32_t bit; /* Pseudorandom bit */ /* Automatic shutoff */ if (chan->int_.auto_ && chan->int_.clocks == 0) { @@ -124,12 +126,7 @@ static void vsuEmulateChannel(VB *sim, Channel *chan) { /* Noise */ else { chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current); - bit = (( - sim->vsu.noise.register_ >> NOISE_TAPS[sim->vsu.noise.tap]^ - sim->vsu.noise.register_ >> 7 - ) & 1) ^ 1; - sim->vsu.noise.register_ = bit | - (sim->vsu.noise.register_ << 1 & 0x7FFE); + vsuNextNoise(sim); } } @@ -147,13 +144,37 @@ static void vsuEmulateChannel(VB *sim, Channel *chan) { } /* Frequency modification */ - if (chan->freqmod && sim->vsu.freqmod.clocks == 0) { - chan->freq.current = sim->vsu.freqmod.next; - vsuNextFreqMod(sim, chan); + if (chan == &sim->vsu.channels[4] && sim->vsu.freqmod.clocks == 0) { + + /* Apply previously computed frequency modification */ + if (chan->freqmod) + chan->freq.current = sim->vsu.freqmod.next; + + /* Channel itself is disabled */ if (!chan->int_.enb) return; - sim->vsu.freqmod.clocks = (uint32_t) sim->vsu.freqmod.interval * - (sim->vsu.freqmod.clk == 0 ? 19200 : 153600); + + /* Frequency modifications are enabled */ + if (chan->freqmod) { + + /* Not the final modulation sample */ + if (sim->vsu.freqmod.sample != 31) + sim->vsu.freqmod.sample++; + + /* Last modulation sample processed */ + else { + sim->vsu.freqmod.modmask = 1; + if (sim->vsu.freqmod.rep) + sim->vsu.freqmod.sample = 0; + } + + /* Schedule next modification */ + sim->vsu.freqmod.clocks = (uint32_t) sim->vsu.freqmod.interval * + (sim->vsu.freqmod.clk == 0 ? 19200 : 153600); + } + + /* Always process and validate next frequency value */ + vsuNextFreqMod(sim, chan); } } @@ -194,8 +215,10 @@ static void vsuWriteEV0(VB *sim, int index, uint8_t value) { chan->env.interval = value & 7; chan->env.value = value >> 4 & 15; chan->env.reload = chan->env.value; - if (index == 4) + if (index == 4) { + chan->freqmod = vsuCheckFreqMod(sim); vsuNextFreqMod(sim, chan); + } /* Configure state */ chan->env.clocks = 307220 * ((uint32_t) chan->env.interval + 1); @@ -223,6 +246,7 @@ static void vsuWriteEV1(VB *sim, int index, uint8_t value) { case 5: /* Channel 6 */ sim->vsu.noise.tap = value >> 4 & 7; sim->vsu.noise.register_ = 0x0000; + vsuNextNoise(sim); } } @@ -265,6 +289,7 @@ static void vsuWriteINT(VB *sim, int index, uint8_t value) { chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current); } else { sim->vsu.noise.register_ = 0x0000; + vsuNextNoise(sim); chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current); } if (index == 4) { @@ -272,6 +297,8 @@ static void vsuWriteINT(VB *sim, int index, uint8_t value) { (sim->vsu.freqmod.clk == 0 ? 19200 : 153600); sim->vsu.freqmod.modmask = 0; sim->vsu.freqmod.sample = 0; + chan->freqmod = vsuCheckFreqMod(sim); + vsuNextFreqMod(sim, chan); } } @@ -304,6 +331,7 @@ static void vsuWriteSWP(VB *sim, uint8_t value) { if (clocks < sim->vsu.freqmod.clocks) sim->vsu.freqmod.clocks = clocks; sim->vsu.channels[4].freqmod = vsuCheckFreqMod(sim); + vsuNextFreqMod(sim, &sim->vsu.channels[4]); }