OPL: kind of fix 4-op mode

This commit is contained in:
tildearrow 2022-03-14 02:30:25 -05:00
parent 32581bb228
commit 42df8255fc
2 changed files with 49 additions and 13 deletions

View file

@ -349,10 +349,21 @@ void DivPlatformOPL::tick() {
if (chan[i].keyOn || chan[i].keyOff) {
immWrite(chanMap[i]+ADDR_FREQH,0x00|(chan[i].freqH&31));
if (chan[i].state.ops==4 && i<6) {
immWrite(chanMap[i+1]+ADDR_FREQH,0x00|(chan[i].freqH&31));
}
chan[i].keyOff=false;
}
}
if (update4OpMask) {
update4OpMask=false;
if (oplType==3) {
unsigned char opMask=chan[0].fourOp|(chan[2].fourOp<<1)|(chan[4].fourOp<<2)|(chan[6].fourOp<<3)|(chan[8].fourOp<<4)|(chan[10].fourOp<<5);
rWrite(0x104,opMask);
}
}
for (int i=0; i<512; i++) {
if (pendingWrites[i]!=oldWrites[i]) {
immWrite(i,pendingWrites[i]&0xff);
@ -368,12 +379,21 @@ void DivPlatformOPL::tick() {
chan[i].freqH=freqt>>8;
chan[i].freqL=freqt&0xff;
immWrite(chanMap[i]+ADDR_FREQ,chan[i].freqL);
if (chan[i].state.ops==4 && i<6) {
immWrite(chanMap[i+1]+ADDR_FREQ,chan[i].freqL);
}
}
if (chan[i].keyOn) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH|(0x20));
if (chan[i].state.ops==4 && i<6) {
immWrite(chanMap[i+1]+ADDR_FREQH,chan[i].freqH|(0x20));
}
chan[i].keyOn=false;
} else if (chan[i].freqChanged) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH|(chan[i].active<<5));
if (chan[i].state.ops==4 && i<6) {
immWrite(chanMap[i+1]+ADDR_FREQH,chan[i].freqH|(chan[i].active<<5));
}
}
chan[i].freqChanged=false;
}
@ -457,6 +477,8 @@ int DivPlatformOPL::dispatch(DivCommand c) {
}
if (chan[c.chan].insChanged) {
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
chan[c.chan].fourOp=(ops==4);
update4OpMask=true;
for (int i=0; i<ops; i++) {
unsigned char slot=slots[i][c.chan];
if (slot==255) continue;
@ -554,16 +576,22 @@ int DivPlatformOPL::dispatch(DivCommand c) {
chan[c.chan].ins=c.value;
break;
case DIV_CMD_PANNING: {
switch (c.value) {
case 0x01:
chan[c.chan].pan=1;
break;
case 0x10:
chan[c.chan].pan=2;
break;
default:
if (c.value==0) {
chan[c.chan].pan=3;
break;
} else {
chan[c.chan].pan=(((c.value&15)>0)<<1)|((c.value>>4)>0);
}
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (isMuted[c.chan]) {
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1));
if (ops==4) {
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1));
}
} else {
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
if (ops==4) {
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
}
}
//rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
@ -687,6 +715,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
void DivPlatformOPL::forceIns() {
for (int i=0; i<18; i++) {
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
chan[i].fourOp=(ops==4);
for (int j=0; j<ops; j++) {
unsigned char slot=slots[j][i];
if (slot==255) continue;
@ -723,6 +752,7 @@ void DivPlatformOPL::forceIns() {
}
}
}
update4OpMask=true;
}
void DivPlatformOPL::toggleRegisterDump(bool enable) {
@ -768,10 +798,15 @@ void DivPlatformOPL::reset() {
lfoValue=8;
properDrums=properDrumsSys;
if (oplType==1) { // disable waveforms
immWrite(0x01,0x20);
}
if (oplType==3) { // enable OPL3 features
immWrite(0x105,1);
}
update4OpMask=true;
delay=0;
}

View file

@ -32,7 +32,7 @@ class DivPlatformOPL: public DivDispatch {
unsigned char freqH, freqL;
int freq, baseFreq, pitch, note;
unsigned char ins;
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta;
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp;
int vol, outVol;
unsigned char pan;
Channel():
@ -51,6 +51,7 @@ class DivPlatformOPL: public DivDispatch {
portaPause(false),
furnaceDac(false),
inPorta(false),
fourOp(false),
vol(0),
pan(3) {}
};
@ -78,7 +79,7 @@ class DivPlatformOPL: public DivDispatch {
unsigned char lfoValue;
bool useYMFM;
bool useYMFM, update4OpMask;
short oldWrites[512];
short pendingWrites[512];