AY/8930: implement sample offset

This commit is contained in:
tildearrow 2024-04-23 18:49:28 -05:00
parent b8dd185463
commit a88b63cf31
4 changed files with 48 additions and 12 deletions

View file

@ -122,7 +122,7 @@ void DivPlatformAY8910::runDAC() {
int prevOut=chan[i].dac.out; int prevOut=chan[i].dac.out;
while (chan[i].dac.period>dacRate && !end) { while (chan[i].dac.period>dacRate && !end) {
DivSample* s=parent->getSample(chan[i].dac.sample); DivSample* s=parent->getSample(chan[i].dac.sample);
if (s->samples<=0) { if (s->samples<=0 || chan[i].dac.pos<0 || chan[i].dac.pos>=(int)s->samples) {
chan[i].dac.sample=-1; chan[i].dac.sample=-1;
immWrite(0x08+i,0); immWrite(0x08+i,0);
end=true; end=true;
@ -297,7 +297,11 @@ void DivPlatformAY8910::tick(bool sysTick) {
rWrite(0x08+i,0); rWrite(0x08+i,0);
addWrite(0xffff0000+(i<<8),chan[i].dac.sample); addWrite(0xffff0000+(i<<8),chan[i].dac.sample);
} }
if (chan[i].dac.setPos) {
chan[i].dac.setPos=false;
} else {
chan[i].dac.pos=0; chan[i].dac.pos=0;
}
chan[i].dac.period=0; chan[i].dac.period=0;
chan[i].keyOn=true; chan[i].keyOn=true;
} }
@ -422,7 +426,11 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample); addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
} }
} }
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0; chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0; chan[c.chan].dac.period=0;
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
@ -448,7 +456,11 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
} else { } else {
if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample); if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
} }
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0; chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0; chan[c.chan].dac.period=0;
chan[c.chan].dac.rate=parent->getSample(chan[c.chan].dac.sample)->rate*2048; chan[c.chan].dac.rate=parent->getSample(chan[c.chan].dac.sample)->rate*2048;
if (dumpWrites) { if (dumpWrites) {
@ -652,6 +664,11 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
sampleBank=parent->song.sample.size()/12; sampleBank=parent->song.sample.size()/12;
} }
break; break;
case DIV_CMD_SAMPLE_POS:
chan[c.chan].dac.pos=c.value;
chan[c.chan].dac.setPos=true;
if (dumpWrites) addWrite(0xffff0005,chan[c.chan].dac.pos);
break;
case DIV_CMD_MACRO_OFF: case DIV_CMD_MACRO_OFF:
chan[c.chan].std.mask(c.value,true); chan[c.chan].std.mask(c.value,true);
break; break;

View file

@ -57,7 +57,7 @@ class DivPlatformAY8910: public DivDispatch {
struct DAC { struct DAC {
int sample, rate, period, pos, out; int sample, rate, period, pos, out;
bool furnaceDAC; bool furnaceDAC, setPos;
DAC(): DAC():
sample(-1), sample(-1),
@ -65,7 +65,8 @@ class DivPlatformAY8910: public DivDispatch {
period(0), period(0),
pos(0), pos(0),
out(0), out(0),
furnaceDAC(false) {} furnaceDAC(false),
setPos(false) {}
} dac; } dac;
unsigned char autoEnvNum, autoEnvDen; unsigned char autoEnvNum, autoEnvDen;

View file

@ -118,7 +118,7 @@ void DivPlatformAY8930::runDAC() {
int prevOut=chan[i].dac.out; int prevOut=chan[i].dac.out;
while (chan[i].dac.period>rate && !end) { while (chan[i].dac.period>rate && !end) {
DivSample* s=parent->getSample(chan[i].dac.sample); DivSample* s=parent->getSample(chan[i].dac.sample);
if (s->samples<=0) { if (s->samples<=0 || chan[i].dac.pos<0 || chan[i].dac.pos>=(int)s->samples) {
chan[i].dac.sample=-1; chan[i].dac.sample=-1;
immWrite(0x08+i,0); immWrite(0x08+i,0);
end=true; end=true;
@ -285,7 +285,11 @@ void DivPlatformAY8930::tick(bool sysTick) {
rWrite(0x08+i,0); rWrite(0x08+i,0);
addWrite(0xffff0000+(i<<8),chan[i].dac.sample); addWrite(0xffff0000+(i<<8),chan[i].dac.sample);
} }
if (chan[i].dac.setPos) {
chan[i].dac.setPos=false;
} else {
chan[i].dac.pos=0; chan[i].dac.pos=0;
}
chan[i].dac.period=0; chan[i].dac.period=0;
chan[i].keyOn=true; chan[i].keyOn=true;
} }
@ -423,7 +427,11 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample); addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
} }
} }
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0; chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0; chan[c.chan].dac.period=0;
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
@ -449,7 +457,11 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
} else { } else {
if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample); if (dumpWrites) addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
} }
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0; chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0; chan[c.chan].dac.period=0;
chan[c.chan].dac.rate=parent->getSample(chan[c.chan].dac.sample)->rate*4096; chan[c.chan].dac.rate=parent->getSample(chan[c.chan].dac.sample)->rate*4096;
if (dumpWrites) { if (dumpWrites) {
@ -654,6 +666,11 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
sampleBank=parent->song.sample.size()/12; sampleBank=parent->song.sample.size()/12;
} }
break; break;
case DIV_CMD_SAMPLE_POS:
chan[c.chan].dac.pos=c.value;
chan[c.chan].dac.setPos=true;
if (dumpWrites) addWrite(0xffff0005,chan[c.chan].dac.pos);
break;
case DIV_CMD_MACRO_OFF: case DIV_CMD_MACRO_OFF:
chan[c.chan].std.mask(c.value,true); chan[c.chan].std.mask(c.value,true);
break; break;

View file

@ -65,7 +65,7 @@ class DivPlatformAY8930: public DivDispatch {
struct DAC { struct DAC {
int sample, rate, period, pos, out; int sample, rate, period, pos, out;
bool furnaceDAC; bool furnaceDAC, setPos;
DAC(): DAC():
sample(-1), sample(-1),
@ -73,7 +73,8 @@ class DivPlatformAY8930: public DivDispatch {
period(0), period(0),
pos(0), pos(0),
out(0), out(0),
furnaceDAC(false) {} furnaceDAC(false),
setPos(false) {}
} dac; } dac;
unsigned char autoEnvNum, autoEnvDen, duty; unsigned char autoEnvNum, autoEnvDen, duty;