Fix BKCOL debug writes, more VSU edge cases

This commit is contained in:
Guy Perfect 2025-02-24 13:44:26 -06:00
parent c62dd833a3
commit 185362e6cd
2 changed files with 58 additions and 30 deletions

View File

@ -546,7 +546,7 @@ static void vipWriteIO(
break; break;
case 0x5F870>>1: /* BKCOL */ 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; break;
} }

View File

@ -50,7 +50,7 @@ static uint8_t vsuCheckFreqMod(VB *sim) {
return return
sim->vsu.freqmod.enb && sim->vsu.freqmod.enb &&
sim->vsu.freqmod.interval != 0 && ( sim->vsu.freqmod.interval != 0 && (
!sim->vsu.freqmod.modmask || ( sim->vsu.freqmod.modmask != 2 || (
sim->vsu.freqmod.func == 1 && sim->vsu.freqmod.func == 1 &&
sim->vsu.freqmod.rep sim->vsu.freqmod.rep
) )
@ -62,6 +62,12 @@ static uint8_t vsuCheckFreqMod(VB *sim) {
static void vsuNextFreqMod(VB *sim, Channel *chan) { static void vsuNextFreqMod(VB *sim, Channel *chan) {
int32_t next; 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 */ /* Sweep */
if (sim->vsu.freqmod.func == 0) { if (sim->vsu.freqmod.func == 0) {
next = chan->freq.current >> sim->vsu.freqmod.shift; next = chan->freq.current >> sim->vsu.freqmod.shift;
@ -76,35 +82,31 @@ static void vsuNextFreqMod(VB *sim, Channel *chan) {
/* Modulation */ /* Modulation */
else { else {
/* Compute the modulated value */
next = (int32_t) chan->freq.written + next = (int32_t) chan->freq.written +
sim->vsu.modulation[sim->vsu.freqmod.sample]; sim->vsu.modulation[sim->vsu.freqmod.sample];
if (next < 0) if (next < 0)
next = 0; next = 0;
if (next > 2047) if (next > 2047)
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 */ /* Configure state */
if (chan->freqmod)
sim->vsu.freqmod.next = next; 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 */ /* Process one channel */
static void vsuEmulateChannel(VB *sim, Channel *chan) { static void vsuEmulateChannel(VB *sim, Channel *chan) {
uint32_t bit; /* Pseudorandom bit */
/* Automatic shutoff */ /* Automatic shutoff */
if (chan->int_.auto_ && chan->int_.clocks == 0) { if (chan->int_.auto_ && chan->int_.clocks == 0) {
@ -124,12 +126,7 @@ static void vsuEmulateChannel(VB *sim, Channel *chan) {
/* Noise */ /* Noise */
else { else {
chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current); chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current);
bit = (( vsuNextNoise(sim);
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);
} }
} }
@ -147,15 +144,39 @@ static void vsuEmulateChannel(VB *sim, Channel *chan) {
} }
/* Frequency modification */ /* Frequency modification */
if (chan->freqmod && sim->vsu.freqmod.clocks == 0) { 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; chan->freq.current = sim->vsu.freqmod.next;
vsuNextFreqMod(sim, chan);
/* Channel itself is disabled */
if (!chan->int_.enb) if (!chan->int_.enb)
return; return;
/* 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.clocks = (uint32_t) sim->vsu.freqmod.interval *
(sim->vsu.freqmod.clk == 0 ? 19200 : 153600); (sim->vsu.freqmod.clk == 0 ? 19200 : 153600);
} }
/* Always process and validate next frequency value */
vsuNextFreqMod(sim, chan);
}
} }
/* Produce output for a channel */ /* Produce output for a channel */
@ -194,8 +215,10 @@ static void vsuWriteEV0(VB *sim, int index, uint8_t value) {
chan->env.interval = value & 7; chan->env.interval = value & 7;
chan->env.value = value >> 4 & 15; chan->env.value = value >> 4 & 15;
chan->env.reload = chan->env.value; chan->env.reload = chan->env.value;
if (index == 4) if (index == 4) {
chan->freqmod = vsuCheckFreqMod(sim);
vsuNextFreqMod(sim, chan); vsuNextFreqMod(sim, chan);
}
/* Configure state */ /* Configure state */
chan->env.clocks = 307220 * ((uint32_t) chan->env.interval + 1); 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 */ case 5: /* Channel 6 */
sim->vsu.noise.tap = value >> 4 & 7; sim->vsu.noise.tap = value >> 4 & 7;
sim->vsu.noise.register_ = 0x0000; 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); chan->clocks = 4 * (2048 - (uint32_t) chan->freq.current);
} else { } else {
sim->vsu.noise.register_ = 0x0000; sim->vsu.noise.register_ = 0x0000;
vsuNextNoise(sim);
chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current); chan->clocks = 40 * (2048 - (uint32_t) chan->freq.current);
} }
if (index == 4) { 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.clk == 0 ? 19200 : 153600);
sim->vsu.freqmod.modmask = 0; sim->vsu.freqmod.modmask = 0;
sim->vsu.freqmod.sample = 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) if (clocks < sim->vsu.freqmod.clocks)
sim->vsu.freqmod.clocks = clocks; sim->vsu.freqmod.clocks = clocks;
sim->vsu.channels[4].freqmod = vsuCheckFreqMod(sim); sim->vsu.channels[4].freqmod = vsuCheckFreqMod(sim);
vsuNextFreqMod(sim, &sim->vsu.channels[4]);
} }