dev153 - fix SegaPCM slides

issue #1060
This commit is contained in:
tildearrow 2023-04-13 17:21:06 -05:00
parent ea172ea6ff
commit eaafc16eb3
5 changed files with 42 additions and 13 deletions

View file

@ -53,8 +53,8 @@
#define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock(); #define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock();
#define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false; #define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false;
#define DIV_VERSION "dev152" #define DIV_VERSION "dev153"
#define DIV_ENGINE_VERSION 152 #define DIV_ENGINE_VERSION 153
// for imports // for imports
#define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02 #define DIV_VERSION_FC 0xff02

View file

@ -2715,6 +2715,15 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} }
} }
// SrgaPCM slide compat
if (ds.version<153) {
for (int i=0; i<ds.systemLen; i++) {
if (ds.system[i]==DIV_SYSTEM_SEGAPCM || ds.system[i]==DIV_SYSTEM_SEGAPCM_COMPAT) {
ds.systemFlags[i].set("oldSlides",true);
}
}
}
if (active) quitDispatch(); if (active) quitDispatch();
BUSY_BEGIN_SOFT; BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();

View file

@ -72,7 +72,7 @@ void DivPlatformSegaPCM::tick(bool sysTick) {
chan[i].handleArp(); chan[i].handleArp();
} else if (chan[i].std.arp.had) { } else if (chan[i].std.arp.had) {
if (!chan[i].inPorta) { if (!chan[i].inPorta) {
chan[i].baseFreq=(parent->calcArp(chan[i].note,chan[i].std.arp.val)<<6); chan[i].baseFreq=(parent->calcArp(chan[i].note,chan[i].std.arp.val)<<7);
} }
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -106,21 +106,22 @@ void DivPlatformSegaPCM::tick(bool sysTick) {
} }
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64; chan[i].freq=chan[i].baseFreq+(chan[i].pitch)-128+(oldSlides?0:chan[i].pitch2);
if (!parent->song.oldArpStrategy) { if (!parent->song.oldArpStrategy) {
if (chan[i].fixedArp) { if (chan[i].fixedArp) {
chan[i].freq=(chan[i].baseNoteOverride<<6)+(chan[i].pitch>>1)-64+chan[i].pitch2; chan[i].freq=(chan[i].baseNoteOverride<<7)+chan[i].pitch-128+(chan[i].pitch2<<(oldSlides?1:0));
} else { } else {
chan[i].freq+=chan[i].arpOff<<6; chan[i].freq+=chan[i].arpOff<<7;
} }
} }
if (oldSlides) chan[i].freq&=~1;
if (chan[i].furnacePCM) { if (chan[i].furnacePCM) {
double off=1.0; double off=1.0;
if (chan[i].pcm.sample>=0 && chan[i].pcm.sample<parent->song.sampleLen) { if (chan[i].pcm.sample>=0 && chan[i].pcm.sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].pcm.sample); DivSample* s=parent->getSample(chan[i].pcm.sample);
off=(double)s->centerRate/8363.0; off=(double)s->centerRate/8363.0;
} }
chan[i].pcm.freq=MIN(255,(15625+(off*parent->song.tuning*pow(2.0,double(chan[i].freq+256)/(64.0*12.0)))*255)/31250)+chan[i].pitch2; chan[i].pcm.freq=MIN(255,(15625+(off*parent->song.tuning*pow(2.0,double(chan[i].freq+512)/(128.0*12.0)))*255)/31250)+(oldSlides?chan[i].pitch2:0);
rWrite(7+(i<<3),chan[i].pcm.freq); rWrite(7+(i<<3),chan[i].pcm.freq);
} }
chan[i].freqChanged=false; chan[i].freqChanged=false;
@ -201,7 +202,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
} }
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
chan[c.chan].baseFreq=(c.value<<6); chan[c.chan].baseFreq=(c.value<<7);
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
} }
chan[c.chan].furnacePCM=true; chan[c.chan].furnacePCM=true;
@ -289,17 +290,18 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
int destFreq=(c.value2<<6); int destFreq=(c.value2<<7);
int newFreq; int newFreq;
int mul=(oldSlides || parent->song.linearPitch!=2)?8:parent->song.pitchSlideSpeed;
bool return2=false; bool return2=false;
if (destFreq>chan[c.chan].baseFreq) { if (destFreq>chan[c.chan].baseFreq) {
newFreq=chan[c.chan].baseFreq+c.value*4; newFreq=chan[c.chan].baseFreq+c.value*mul;
if (newFreq>=destFreq) { if (newFreq>=destFreq) {
newFreq=destFreq; newFreq=destFreq;
return2=true; return2=true;
} }
} else { } else {
newFreq=chan[c.chan].baseFreq-c.value*4; newFreq=chan[c.chan].baseFreq-c.value*mul;
if (newFreq<=destFreq) { if (newFreq<=destFreq) {
newFreq=destFreq; newFreq=destFreq;
return2=true; return2=true;
@ -314,7 +316,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_LEGATO: { case DIV_CMD_LEGATO: {
chan[c.chan].baseFreq=(c.value<<6); chan[c.chan].baseFreq=(c.value<<7);
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
break; break;
} }
@ -337,7 +339,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
return 127; return 127;
break; break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=(chan[c.chan].note<<6); if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=(chan[c.chan].note<<7);
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;
case DIV_CMD_PRE_NOTE: case DIV_CMD_PRE_NOTE:
@ -504,6 +506,8 @@ void DivPlatformSegaPCM::setFlags(const DivConfig& flags) {
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
oscBuf[i]->rate=rate; oscBuf[i]->rate=rate;
} }
oldSlides=flags.getBool("oldSlides",false);
} }
int DivPlatformSegaPCM::getOutputCount() { int DivPlatformSegaPCM::getOutputCount() {

View file

@ -65,6 +65,7 @@ class DivPlatformSegaPCM: public DivDispatch {
segapcm_device pcm; segapcm_device pcm;
int delay; int delay;
int pcmL, pcmR, pcmCycles; int pcmL, pcmR, pcmCycles;
bool oldSlides;
unsigned char sampleBank; unsigned char sampleBank;
unsigned char lastBusy; unsigned char lastBusy;

View file

@ -1770,6 +1770,21 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
} }
break; break;
} }
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT: {
bool oldSlides=flags.getBool("oldSlides",false);
if (ImGui::Checkbox("Legacy slides and pitch (compatibility)",&oldSlides)) {
altered=true;
}
if (altered) {
e->lockSave([&]() {
flags.set("oldSlides",oldSlides);
});
}
break;
}
case DIV_SYSTEM_SM8521:/* { case DIV_SYSTEM_SM8521:/* {
bool noAntiClick=flags.getBool("noAntiClick",false); bool noAntiClick=flags.getBool("noAntiClick",false);