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;
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;
}

View File

@ -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]);
}