dev176 - OPM/OPZ: fix pitch

This commit is contained in:
tildearrow 2023-09-12 01:12:59 -05:00
parent 8fe3811233
commit 658f69bc4e
6 changed files with 73 additions and 26 deletions

View file

@ -58,8 +58,8 @@ class DivWorkPool;
#define DIV_UNSTABLE #define DIV_UNSTABLE
#define DIV_VERSION "0.6pre14" #define DIV_VERSION "dev176"
#define DIV_ENGINE_VERSION 175 #define DIV_ENGINE_VERSION 176
// 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

@ -1058,6 +1058,11 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.systemFlags[0].set("keyPriority",false); ds.systemFlags[0].set("keyPriority",false);
} }
// OPM broken pitch
if (ds.system[0]==DIV_SYSTEM_YM2151) {
ds.systemFlags[0].set("brokenPitch",true);
}
ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0)); ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0));
if (active) quitDispatch(); if (active) quitDispatch();
@ -2976,6 +2981,16 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} }
} }
// OPM/OPZ slide compat
if (ds.version<176) {
for (int i=0; i<ds.systemLen; i++) {
if (ds.system[i]==DIV_SYSTEM_YM2151 ||
ds.system[i]==DIV_SYSTEM_OPZ) {
ds.systemFlags[i].set("brokenPitch",true);
}
}
}
if (active) quitDispatch(); if (active) quitDispatch();
BUSY_BEGIN_SOFT; BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();

View file

@ -197,10 +197,10 @@ void DivPlatformArcade::tick(bool sysTick) {
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) { if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val; chan[i].pitch2+=chan[i].std.pitch.val*(brokenPitch?2:1);
CLAMP_VAR(chan[i].pitch2,-32768,32767); CLAMP_VAR(chan[i].pitch2,-32768,32767);
} else { } else {
chan[i].pitch2=chan[i].std.pitch.val; chan[i].pitch2=chan[i].std.pitch.val*(brokenPitch?2:1);
} }
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -354,18 +354,18 @@ void DivPlatformArcade::tick(bool sysTick) {
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64+chan[i].pitch2; chan[i].freq=chan[i].baseFreq+chan[i].pitch-128+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;
} else { } else {
chan[i].freq+=chan[i].arpOff<<6; chan[i].freq+=chan[i].arpOff<<7;
} }
} }
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>=(95<<6)) chan[i].freq=(95<<6)-1; if (chan[i].freq>=(95<<7)) chan[i].freq=(95<<7)-1;
immWrite(i+0x28,hScale(chan[i].freq>>6)); immWrite(i+0x28,hScale(chan[i].freq>>7));
immWrite(i+0x30,chan[i].freq<<2); immWrite(i+0x30,((chan[i].freq<<1)&0xfc));
hardResetElapsed+=2; hardResetElapsed+=2;
chan[i].freqChanged=false; chan[i].freqChanged=false;
} }
@ -534,13 +534,13 @@ int DivPlatformArcade::dispatch(DivCommand c) {
int newFreq; int newFreq;
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; newFreq=chan[c.chan].baseFreq+c.value*(brokenPitch?2:1);
if (newFreq>=destFreq) { if (newFreq>=destFreq) {
newFreq=destFreq; newFreq=destFreq;
return2=true; return2=true;
} }
} else { } else {
newFreq=chan[c.chan].baseFreq-c.value; newFreq=chan[c.chan].baseFreq-c.value*(brokenPitch?2:1);
if (newFreq<=destFreq) { if (newFreq<=destFreq) {
newFreq=destFreq; newFreq=destFreq;
return2=true; return2=true;
@ -932,7 +932,9 @@ void DivPlatformArcade::setFlags(const DivConfig& flags) {
} }
CHECK_CUSTOM_CLOCK; CHECK_CUSTOM_CLOCK;
baseFreqOff=round(768.0*(log((COLOR_NTSC/(double)chipClock))/log(2.0))); baseFreqOff=round(1536.0*(log((COLOR_NTSC/(double)chipClock))/log(2.0)));
brokenPitch=flags.getBool("brokenPitch",false);
rate=chipClock/64; rate=chipClock/64;
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {

View file

@ -22,7 +22,7 @@
#include "fmsharedbase.h" #include "fmsharedbase.h"
#define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) #define NOTE_LINEAR(x) (((x)<<7)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*128.0)
class DivPlatformOPM: public DivPlatformFMBase { class DivPlatformOPM: public DivPlatformFMBase {
protected: protected:
@ -42,13 +42,15 @@ class DivPlatformOPM: public DivPlatformFMBase {
}; };
unsigned char lfoValue, lfoValue2, lfoShape, lfoShape2; unsigned char lfoValue, lfoValue2, lfoShape, lfoShape2;
bool brokenPitch;
DivPlatformOPM(): DivPlatformOPM():
DivPlatformFMBase(), DivPlatformFMBase(),
lfoValue(0), lfoValue(0),
lfoValue2(0), lfoValue2(0),
lfoShape(0), lfoShape(0),
lfoShape2(0) {} lfoShape2(0),
brokenPitch(false) {}
}; };
#endif #endif

View file

@ -147,10 +147,10 @@ void DivPlatformTX81Z::tick(bool sysTick) {
if (chan[i].std.pitch.had) { if (chan[i].std.pitch.had) {
if (chan[i].std.pitch.mode) { if (chan[i].std.pitch.mode) {
chan[i].pitch2+=chan[i].std.pitch.val; chan[i].pitch2+=chan[i].std.pitch.val*(brokenPitch?2:1);
CLAMP_VAR(chan[i].pitch2,-32768,32767); CLAMP_VAR(chan[i].pitch2,-32768,32767);
} else { } else {
chan[i].pitch2=chan[i].std.pitch.val; chan[i].pitch2=chan[i].std.pitch.val*(brokenPitch?2:1);
} }
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
@ -337,18 +337,18 @@ void DivPlatformTX81Z::tick(bool sysTick) {
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
if (chan[i].freqChanged) { if (chan[i].freqChanged) {
chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64+chan[i].pitch2; chan[i].freq=chan[i].baseFreq+chan[i].pitch-128+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;
} else { } else {
chan[i].freq+=chan[i].arpOff<<6; chan[i].freq+=chan[i].arpOff<<7;
} }
} }
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>=(95<<6)) chan[i].freq=(95<<6)-1; if (chan[i].freq>=(95<<7)) chan[i].freq=(95<<7)-1;
immWrite(i+0x28,hScale(chan[i].freq>>6)); immWrite(i+0x28,hScale(chan[i].freq>>7));
immWrite(i+0x30,(chan[i].freq<<2)|(chan[i].chVolL==chan[i].chVolR)); immWrite(i+0x30,((chan[i].freq<<1)&0xfc)|(chan[i].chVolL==chan[i].chVolR));
hardResetElapsed+=2; hardResetElapsed+=2;
chan[i].freqChanged=false; chan[i].freqChanged=false;
} }
@ -523,13 +523,13 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
int newFreq; int newFreq;
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; newFreq=chan[c.chan].baseFreq+c.value*(brokenPitch?2:1);
if (newFreq>=destFreq) { if (newFreq>=destFreq) {
newFreq=destFreq; newFreq=destFreq;
return2=true; return2=true;
} }
} else { } else {
newFreq=chan[c.chan].baseFreq-c.value; newFreq=chan[c.chan].baseFreq-c.value*(brokenPitch?2:1);
if (newFreq<=destFreq) { if (newFreq<=destFreq) {
newFreq=destFreq; newFreq=destFreq;
return2=true; return2=true;
@ -1043,7 +1043,9 @@ void DivPlatformTX81Z::setFlags(const DivConfig& flags) {
} }
CHECK_CUSTOM_CLOCK; CHECK_CUSTOM_CLOCK;
baseFreqOff=round(768.0*(log((COLOR_NTSC/(double)chipClock))/log(2.0))); baseFreqOff=round(1536.0*(log((COLOR_NTSC/(double)chipClock))/log(2.0)));
brokenPitch=flags.getBool("brokenPitch",false);
rate=chipClock/64; rate=chipClock/64;
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {

View file

@ -461,6 +461,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
} }
case DIV_SYSTEM_YM2151: { case DIV_SYSTEM_YM2151: {
int clockSel=flags.getInt("clockSel",0); int clockSel=flags.getInt("clockSel",0);
bool brokenPitch=flags.getBool("brokenPitch",false);
ImGui::Indent(); ImGui::Indent();
if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",clockSel==0)) { if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",clockSel==0)) {
@ -477,9 +478,34 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
} }
ImGui::Unindent(); ImGui::Unindent();
if (ImGui::Checkbox("Broken pitch macro/slides (compatibility)",&brokenPitch)) {
altered=true;
}
if (altered) { if (altered) {
e->lockSave([&]() { e->lockSave([&]() {
flags.set("clockSel",clockSel); flags.set("clockSel",clockSel);
flags.set("brokenPitch",brokenPitch);
});
}
break;
}
case DIV_SYSTEM_OPZ: {
bool clockSel=flags.getInt("clockSel",0);
bool brokenPitch=flags.getBool("brokenPitch",false);
if (ImGui::Checkbox("Pseudo-PAL",&clockSel)) {
altered=true;
}
if (ImGui::Checkbox("Broken pitch macro/slides (compatibility)",&brokenPitch)) {
altered=true;
}
if (altered) {
e->lockSave([&]() {
flags.set("clockSel",(int)clockSel);
flags.set("brokenPitch",brokenPitch);
}); });
} }
break; break;