Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
* 'master' of https://github.com/tildearrow/furnace: (77 commits) GUI: use pattern font for input latch GUI: partially implement note input latch UI GUI: transpose value does not transpose effect ID GUI: prepare for note input latch UI GUI: min ins selector width fix GUI: separate operation masks GUI: add missing FDS preset GUI: prepare for separate operation mask GUI: "none" instrument should not remove inscolumn GUI: fix ins 0 being inserted on blank song GUI: add a "none" option to instrument list update to-do list GUI: add "absorb" instrument input mode use good default instrument when adding ins better default instrument for OPL/OPLL GUI: fix selection being visible in dummy row area Further fix looped sample preview GUI: fix about screen in power saving mode VRC6: saw volume 63 GUI: add an effect list window ... # Conflicts: # src/engine/platform/amiga.cpp # src/engine/vgmOps.cpp # src/gui/dataList.cpp # src/gui/guiConst.cpp # src/gui/insEdit.cpp # src/gui/sampleEdit.cpp
This commit is contained in:
commit
49a41ff862
116 changed files with 2535 additions and 993 deletions
|
|
@ -22,7 +22,7 @@
|
|||
void DivDispatch::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
}
|
||||
|
||||
void DivDispatch::tick() {
|
||||
void DivDispatch::tick(bool sysTick) {
|
||||
}
|
||||
|
||||
void* DivDispatch::getChanState(int chan) {
|
||||
|
|
|
|||
|
|
@ -108,7 +108,9 @@ void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t le
|
|||
} else {
|
||||
DivSample* s=parent->getSample(chan[i].sample);
|
||||
if (s->samples>0) {
|
||||
writeAudDat(s->data8[chan[i].audPos++]);
|
||||
if (chan[i].audPos<s->samples) {
|
||||
writeAudDat(s->data8[chan[i].audPos++]);
|
||||
}
|
||||
if (((s->loopMode!=DIV_SAMPLE_LOOPMODE_ONESHOT) && chan[i].audPos>=s->loopEnd) || (chan[i].audPos>=s->samples) || (chan[i].audPos>=131071)) {
|
||||
if (s->isLoopable()) {
|
||||
chan[i].audPos=s->loopStart;
|
||||
|
|
@ -155,7 +157,7 @@ void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t le
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformAmiga::tick() {
|
||||
void DivPlatformAmiga::tick(bool sysTick) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -204,7 +206,7 @@ void DivPlatformAmiga::tick() {
|
|||
}
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
|
|
@ -222,7 +224,7 @@ void DivPlatformAmiga::tick() {
|
|||
int DivPlatformAmiga::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||
double off=1.0;
|
||||
if (ins->amiga.useWave) {
|
||||
chan[c.chan].useWave=true;
|
||||
|
|
@ -312,7 +314,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
|||
chan[c.chan].ws.changeWave1(chan[c.chan].wave);
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||
chan[c.chan].sample=ins->amiga.initSample;
|
||||
double off=1.0;
|
||||
if (!chan[c.chan].useWave && chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
|
|
@ -362,7 +364,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class DivPlatformAmiga: public DivDispatch {
|
|||
void* getChanState(int chan);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ inline int hScale(int note) {
|
|||
return ((note/12)<<4)+(noteMap[note%12]);
|
||||
}
|
||||
|
||||
void DivPlatformArcade::tick() {
|
||||
void DivPlatformArcade::tick(bool sysTick) {
|
||||
for (int i=0; i<8; i++) {
|
||||
chan[i].std.next();
|
||||
|
||||
|
|
@ -264,6 +264,20 @@ void DivPlatformArcade::tick() {
|
|||
rWrite(0x1b,chan[i].std.wave.val&3);
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].chVolL=(chan[i].std.panL.val&2)>>1;
|
||||
chan[i].chVolR=chan[i].std.panL.val&1;
|
||||
if (isMuted[i]) {
|
||||
rWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||
} else {
|
||||
rWrite(chanOffs[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3)|((chan[i].chVolL&1)<<6)|((chan[i].chVolR&1)<<7));
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -432,7 +446,7 @@ void DivPlatformArcade::muteChannel(int ch, bool mute) {
|
|||
int DivPlatformArcade::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].state=ins->fm;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class DivPlatformArcade: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void notifyInsChange(int ins);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ void DivPlatformAY8910::updateOutSel(bool immediate) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::tick() {
|
||||
void DivPlatformAY8910::tick(bool sysTick) {
|
||||
// PSG
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i].std.next();
|
||||
|
|
@ -215,6 +215,9 @@ void DivPlatformAY8910::tick() {
|
|||
rWrite(0x08+i,(chan[i].outVol&15)|((chan[i].psgMode&4)<<2));
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
oldWrites[0x08+i]=-1;
|
||||
|
|
@ -291,7 +294,7 @@ void DivPlatformAY8910::tick() {
|
|||
int DivPlatformAY8910::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AY);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -454,7 +457,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AY));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class DivPlatformAY8910: public DivDispatch {
|
|||
void flushWrites();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setFlags(unsigned int flags);
|
||||
bool isStereo();
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ const unsigned char regMode[3]={
|
|||
0x0d, 0x14, 0x15
|
||||
};
|
||||
|
||||
void DivPlatformAY8930::tick() {
|
||||
void DivPlatformAY8930::tick(bool sysTick) {
|
||||
// PSG
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i].std.next();
|
||||
|
|
@ -226,6 +226,9 @@ void DivPlatformAY8930::tick() {
|
|||
rWrite(0x08+i,(chan[i].outVol&31)|((chan[i].psgMode&4)<<3));
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
oldWrites[0x08+i]=-1;
|
||||
|
|
@ -315,7 +318,7 @@ void DivPlatformAY8930::tick() {
|
|||
int DivPlatformAY8930::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AY8930);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -479,7 +482,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AY8930));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setFlags(unsigned int flags);
|
||||
bool isStereo();
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ void DivPlatformBubSysWSG::updateWave(int ch) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformBubSysWSG::tick() {
|
||||
void DivPlatformBubSysWSG::tick(bool sysTick) {
|
||||
for (int i=0; i<2; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -110,13 +110,16 @@ void DivPlatformBubSysWSG::tick() {
|
|||
if (!chan[i].keyOff) chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].active) {
|
||||
if (chan[i].ws.tick()) {
|
||||
updateWave(i);
|
||||
}
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SCC);
|
||||
chan[i].freq=0x1000-parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
|
|
@ -139,7 +142,7 @@ void DivPlatformBubSysWSG::tick() {
|
|||
int DivPlatformBubSysWSG::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_SCC);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -225,7 +228,7 @@ int DivPlatformBubSysWSG::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SCC));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class DivPlatformBubSysWSG: public DivDispatch {
|
|||
int getRegisterPoolDepth();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -122,11 +122,11 @@ void DivPlatformC64::updateFilter() {
|
|||
rWrite(0x18,(filtControl<<4)|vol);
|
||||
}
|
||||
|
||||
void DivPlatformC64::tick() {
|
||||
void DivPlatformC64::tick(bool sysTick) {
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
|
||||
if (ins->c64.volIsCutoff) {
|
||||
if (ins->c64.filterIsAbs) {
|
||||
filtCut=MIN(2047,chan[i].std.vol.val);
|
||||
|
|
@ -157,7 +157,7 @@ void DivPlatformC64::tick() {
|
|||
}
|
||||
}
|
||||
if (chan[i].std.duty.had) {
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_C64);
|
||||
if (ins->c64.dutyIsAbs) {
|
||||
chan[i].duty=chan[i].std.duty.val;
|
||||
} else {
|
||||
|
|
@ -166,12 +166,14 @@ void DivPlatformC64::tick() {
|
|||
rWrite(i*7+2,chan[i].duty&0xff);
|
||||
rWrite(i*7+3,chan[i].duty>>8);
|
||||
}
|
||||
if (chan[i].testWhen>0) {
|
||||
if (--chan[i].testWhen<1) {
|
||||
if (!chan[i].resetMask) {
|
||||
rWrite(i*7+5,0);
|
||||
rWrite(i*7+6,0);
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|8|(chan[i].ring<<2)|(chan[i].sync<<1));
|
||||
if (sysTick) {
|
||||
if (chan[i].testWhen>0) {
|
||||
if (--chan[i].testWhen<1) {
|
||||
if (!chan[i].resetMask && !chan[i].inPorta) {
|
||||
rWrite(i*7+5,0);
|
||||
rWrite(i*7+6,0);
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|8|(chan[i].ring<<2)|(chan[i].sync<<1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -179,6 +181,9 @@ void DivPlatformC64::tick() {
|
|||
chan[i].wave=chan[i].std.wave.val;
|
||||
rWrite(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
filtControl=chan[i].std.ex1.val&15;
|
||||
updateFilter();
|
||||
|
|
@ -218,7 +223,7 @@ void DivPlatformC64::tick() {
|
|||
int DivPlatformC64::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -339,8 +344,8 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) {
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta || !chan[c.chan].inPorta) {
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_C64));
|
||||
chan[c.chan].keyOn=true;
|
||||
}
|
||||
}
|
||||
|
|
@ -378,7 +383,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_C64_FILTER_RESET:
|
||||
if (c.value&15) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
||||
if (ins->c64.initFilter) {
|
||||
filtCut=ins->c64.cut;
|
||||
updateFilter();
|
||||
|
|
@ -388,7 +393,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_C64_DUTY_RESET:
|
||||
if (c.value&15) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
||||
chan[c.chan].duty=ins->c64.duty;
|
||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setFlags(unsigned int flags);
|
||||
void notifyInsChange(int ins);
|
||||
|
|
|
|||
|
|
@ -38,10 +38,12 @@ void DivPlatformDummy::muteChannel(int ch, bool mute) {
|
|||
isMuted[ch]=mute;
|
||||
}
|
||||
|
||||
void DivPlatformDummy::tick() {
|
||||
void DivPlatformDummy::tick(bool sysTick) {
|
||||
for (unsigned char i=0; i<chans; i++) {
|
||||
chan[i].amp-=3;
|
||||
if (chan[i].amp<16) chan[i].amp=16;
|
||||
if (sysTick) {
|
||||
chan[i].amp-=3;
|
||||
if (chan[i].amp<16) chan[i].amp=16;
|
||||
}
|
||||
|
||||
if (chan[i].freqChanged) {
|
||||
chan[i].freqChanged=false;
|
||||
|
|
@ -115,4 +117,4 @@ void DivPlatformDummy::quit() {
|
|||
}
|
||||
|
||||
DivPlatformDummy::~DivPlatformDummy() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class DivPlatformDummy: public DivDispatch {
|
|||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
void reset();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformDummy();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include <math.h>
|
||||
#include <map>
|
||||
|
||||
#define CHIP_FREQBASE (16*2048)
|
||||
#define CHIP_FREQBASE (16*2048*(chanMax+1))
|
||||
#define NOTE_ES5506(c,note) (chan[c].pcm.freqOffs*NOTE_FREQUENCY(note))
|
||||
|
||||
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.emplace(4,(a),__VA_ARGS__); }}
|
||||
|
|
@ -106,14 +106,40 @@ const char** DivPlatformES5506::getRegisterSheet() {
|
|||
const char* DivPlatformES5506::getEffectName(unsigned char effect) {
|
||||
switch (effect) {
|
||||
case 0x10:
|
||||
return "10xx: Set echo feedback level (00 to FF)";
|
||||
return "10xx: Change waveform";
|
||||
break;
|
||||
case 0x11:
|
||||
return "11xx: Set channel echo level (00 to FF)";
|
||||
return "11xx: Set filter mode (00 to 03)";
|
||||
break;
|
||||
case 0x20:
|
||||
return "20xx: Set envelope count (000 to 0FF)";
|
||||
break;
|
||||
case 0x21:
|
||||
return "21xx: Set envelope count (100 to 1FF)";
|
||||
break;
|
||||
case 0x22:
|
||||
return "22xx: Set envelope left volume ramp (signed)";
|
||||
break;
|
||||
case 0x23:
|
||||
return "23xx: Set envelope right volume ramp (signed)";
|
||||
break;
|
||||
case 0x24:
|
||||
return "24xx: Set envelope k1 ramp (signed)";
|
||||
break;
|
||||
case 0x25:
|
||||
return "25xx: Set envelope k1 ramp (signed, slower)";
|
||||
break;
|
||||
case 0x26:
|
||||
return "26xx: Set envelope k2 ramp (signed)";
|
||||
break;
|
||||
case 0x27:
|
||||
return "27xx: Set envelope k2 ramp (signed, slower)";
|
||||
break;
|
||||
default:
|
||||
if ((effect & 0xf0) == 0x30) {
|
||||
return "3xxx: Set echo delay buffer length (000 to AA5)";
|
||||
if ((effect&0xf0)==0x30) {
|
||||
return "3xxx: Set filter K1";
|
||||
} else if ((effect&0xf0)==0x40) {
|
||||
return "4xxx: Set filter K2";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -190,9 +216,9 @@ void DivPlatformES5506::e(bool state)
|
|||
irqTrigger=false;
|
||||
if ((irqv&0x80)==0) {
|
||||
unsigned char ch=irqv&0x1f;
|
||||
if (chan[ch].isReversed) { // Reversed loop
|
||||
pageWriteMask(0x00|ch,0x5f,0x00,0x48,0x78);
|
||||
chan[ch].isReversed=false;
|
||||
if (chan[ch].isReverseLoop) { // Reversed loop
|
||||
pageWriteMask(0x00|ch,0x5f,0x00,(chan[ch].pcm.reversed?0x0040:0x0000)|0x08,0x78);
|
||||
chan[ch].isReverseLoop=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -204,7 +230,7 @@ void DivPlatformES5506::irqb(bool state) {
|
|||
irqTrigger=true;
|
||||
}
|
||||
|
||||
void DivPlatformES5506::tick() {
|
||||
void DivPlatformES5506::tick(bool sysTick) {
|
||||
for (int i=0; i<=chanMax; i++) {
|
||||
chan[i].std.next();
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
|
|
@ -252,6 +278,104 @@ void DivPlatformES5506::tick() {
|
|||
chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
// filter macros
|
||||
if (chan[i].std.duty.had) {
|
||||
if (chan[i].filter.mode!=DivInstrumentES5506::Filter::FilterMode(chan[i].std.duty.val&3)) {
|
||||
chan[i].filter.mode=DivInstrumentES5506::Filter::FilterMode(chan[i].std.duty.val&3);
|
||||
chan[i].filterChanged.mode=1;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
switch (chan[i].std.ex1.mode) {
|
||||
case 0: // relative
|
||||
if (chan[i].k1Offs!=chan[i].std.ex1.val) {
|
||||
chan[i].k1Offs=chan[i].std.ex1.val;
|
||||
chan[i].filterChanged.k1=1;
|
||||
}
|
||||
case 1: // absolute
|
||||
if (chan[i].filter.k1!=(chan[i].std.ex1.val&0xffff)) {
|
||||
chan[i].filter.k1=chan[i].std.ex1.val&0xffff;
|
||||
chan[i].filterChanged.k1=1;
|
||||
}
|
||||
break;
|
||||
case 2: { // delta
|
||||
signed int next_k1=MAX(0,MIN(65535,chan[i].filter.k1+chan[i].std.ex1.val));
|
||||
if (chan[i].filter.k1!=next_k1) {
|
||||
chan[i].filter.k1=next_k1;
|
||||
chan[i].filterChanged.k1=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex2.had) {
|
||||
switch (chan[i].std.ex2.mode) {
|
||||
case 0: // relative
|
||||
if (chan[i].k2Offs!=chan[i].std.ex1.val) {
|
||||
chan[i].k2Offs=chan[i].std.ex1.val;
|
||||
chan[i].filterChanged.k2=1;
|
||||
}
|
||||
case 1: // absolute
|
||||
if (chan[i].filter.k2!=(chan[i].std.ex2.val&0xffff)) {
|
||||
chan[i].filter.k2=chan[i].std.ex2.val&0xffff;
|
||||
chan[i].filterChanged.k2=1;
|
||||
}
|
||||
break;
|
||||
case 2: { // delta
|
||||
signed int next_k2=MAX(0,MIN(65535,chan[i].filter.k2+chan[i].std.ex2.val));
|
||||
if (chan[i].filter.k2!=next_k2) {
|
||||
chan[i].filter.k2=next_k2;
|
||||
chan[i].filterChanged.k2=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// envelope macros
|
||||
if (chan[i].std.ex3.had) {
|
||||
if (chan[i].envelope.ecount!=(chan[i].std.ex3.val&0x1ff)) {
|
||||
chan[i].envelope.ecount=chan[i].std.ex3.val&0x1ff;
|
||||
chan[i].envChanged.ecount=1;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex4.had) {
|
||||
if (chan[i].envelope.lVRamp!=chan[i].std.ex4.val) {
|
||||
chan[i].envelope.lVRamp=chan[i].std.ex4.val;
|
||||
chan[i].envChanged.lVRamp=1;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex5.had) {
|
||||
if (chan[i].envelope.rVRamp!=chan[i].std.ex5.val) {
|
||||
chan[i].envelope.rVRamp=chan[i].std.ex5.val;
|
||||
chan[i].envChanged.rVRamp=1;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex6.had) {
|
||||
if (chan[i].envelope.k1Ramp!=chan[i].std.ex6.val) {
|
||||
chan[i].envelope.k1Ramp=chan[i].std.ex6.val;
|
||||
chan[i].envChanged.k1Ramp=1;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex7.had) {
|
||||
if (chan[i].envelope.k2Ramp!=chan[i].std.ex7.val) {
|
||||
chan[i].envelope.k2Ramp=chan[i].std.ex7.val;
|
||||
chan[i].envChanged.k2Ramp=1;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.ex8.had) {
|
||||
if (chan[i].envelope.k1Slow!=(chan[i].std.ex8.val&1)) {
|
||||
chan[i].envelope.k1Slow=chan[i].std.ex8.val&1;
|
||||
chan[i].envChanged.k1Ramp=1;
|
||||
}
|
||||
if (chan[i].envelope.k2Slow!=(chan[i].std.ex8.val&2)) {
|
||||
chan[i].envelope.k2Slow=chan[i].std.ex8.val&2;
|
||||
chan[i].envChanged.k2Ramp=1;
|
||||
}
|
||||
}
|
||||
// update registers
|
||||
if (chan[i].volChanged) {
|
||||
if (!isMuted[i]) { // calculate volume (16 bit)
|
||||
|
|
@ -267,72 +391,96 @@ void DivPlatformES5506::tick() {
|
|||
}
|
||||
chan[i].volChanged=false;
|
||||
}
|
||||
if (chan[i].filterChanged) {
|
||||
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].filter.mode<<8),0x0300);
|
||||
if (chan[i].filterChanged.changed) {
|
||||
if (!chan[i].keyOn) {
|
||||
pageWrite(0x00|i,0x07,chan[i].filter.k2);
|
||||
pageWrite(0x00|i,0x09,chan[i].filter.k1);
|
||||
if (chan[i].filterChanged.mode) {
|
||||
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].filter.mode<<8),0x0300);
|
||||
}
|
||||
if (chan[i].filterChanged.k2) {
|
||||
if (chan[i].std.ex2.mode==0) { // Relative
|
||||
pageWrite(0x00|i,0x07,MAX(0,MIN(65535,chan[i].filter.k2+chan[i].k2Offs)));
|
||||
} else {
|
||||
pageWrite(0x00|i,0x07,chan[i].filter.k2);
|
||||
}
|
||||
}
|
||||
if (chan[i].filterChanged.k1) {
|
||||
if (chan[i].std.ex1.mode==0) { // Relative
|
||||
pageWrite(0x00|i,0x09,MAX(0,MIN(65535,chan[i].filter.k1+chan[i].k1Offs)));
|
||||
} else {
|
||||
pageWrite(0x00|i,0x09,chan[i].filter.k1);
|
||||
}
|
||||
}
|
||||
}
|
||||
chan[i].filterChanged=false;
|
||||
chan[i].filterChanged.changed=0;
|
||||
}
|
||||
if (chan[i].envChanged) {
|
||||
if (chan[i].envChanged.changed) {
|
||||
if (!chan[i].keyOn) {
|
||||
pageWrite(0x00|i,0x06,chan[i].envelope.ecount);
|
||||
if (chan[i].envChanged.lVRamp) {
|
||||
pageWrite(0x00|i,0x03,((unsigned char)chan[i].envelope.lVRamp)<<8);
|
||||
}
|
||||
if (chan[i].envChanged.rVRamp) {
|
||||
pageWrite(0x00|i,0x05,((unsigned char)chan[i].envelope.rVRamp)<<8);
|
||||
}
|
||||
if (chan[i].envChanged.ecount) {
|
||||
pageWrite(0x00|i,0x06,chan[i].envelope.ecount);
|
||||
}
|
||||
if (chan[i].envChanged.k2Ramp) {
|
||||
pageWrite(0x00|i,0x08,(((unsigned char)chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0));
|
||||
}
|
||||
if (chan[i].envChanged.k1Ramp) {
|
||||
pageWrite(0x00|i,0x0a,(((unsigned char)chan[i].envelope.k1Ramp)<<8)|(chan[i].envelope.k1Slow?1:0));
|
||||
}
|
||||
}
|
||||
chan[i].envChanged=false;
|
||||
}
|
||||
if (chan[i].rampChanged) {
|
||||
if (!chan[i].keyOn) {
|
||||
pageWrite(0x00|i,0x03,((unsigned char)chan[i].envelope.lVRamp)<<8);
|
||||
pageWrite(0x00|i,0x05,((unsigned char)chan[i].envelope.rVRamp)<<8);
|
||||
pageWrite(0x00|i,0x0a,(((unsigned char)chan[i].envelope.k1Ramp)<<8)|(chan[i].envelope.k1Slow?1:0));
|
||||
pageWrite(0x00|i,0x08,(((unsigned char)chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0));
|
||||
}
|
||||
chan[i].rampChanged=false;
|
||||
chan[i].envChanged.changed=0;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq*(chanMax+1),chan[i].pitch,false)+chan[i].std.pitch.val;
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
||||
if (chan[i].keyOn) {
|
||||
if (chan[i].pcm.index>=0) {
|
||||
pageWriteMask(0x00|i,0x5f,0x00,0x0303); // Wipeout CR
|
||||
pageWrite(0x00|i,0x06,0); // Clear ECOUNT
|
||||
pageWrite(0x20|i,0x03,chan[i].pcm.base); // Set ACCUM to start address
|
||||
pageWrite(0x00|i,0x09,0xffff); // Set K1 and K2 to 0xffff
|
||||
pageWrite(0x00|i,0x07,0xffff,~0,(chanMax+1)*4*2); // needs to 4 sample period delay
|
||||
pageWrite(0x20|i,0x03,chan[i].pcm.reversed?chan[i].pcm.end:chan[i].pcm.start); // Set ACCUM to start address
|
||||
pageWrite(0x00|i,0x07,0xffff); // Set K1 and K2 to 0xffff
|
||||
pageWrite(0x00|i,0x09,0xffff);
|
||||
pageWrite(0x00|i,0x01,chan[i].freq);
|
||||
if (chan[i].pcm.loopMode!=DIV_SAMPLE_LOOPMODE_ONESHOT) {
|
||||
pageWrite(0x20|i,0x01,chan[i].pcm.loopStart);
|
||||
}
|
||||
pageWrite(0x20|i,0x02,chan[i].pcm.loopEnd);
|
||||
pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT)?chan[i].pcm.start:chan[i].pcm.loopStart);
|
||||
pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOPMODE_ONESHOT)?chan[i].pcm.end:chan[i].pcm.loopEnd);
|
||||
// initialize envelope
|
||||
pageWrite(0x00|i,0x03,((unsigned char)chan[i].envelope.lVRamp)<<8);
|
||||
pageWrite(0x00|i,0x05,((unsigned char)chan[i].envelope.rVRamp)<<8);
|
||||
pageWrite(0x00|i,0x0a,(((unsigned char)chan[i].envelope.k1Ramp)<<8)|(chan[i].envelope.k1Slow?1:0));
|
||||
pageWrite(0x00|i,0x08,(((unsigned char)chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0));
|
||||
pageWrite(0x00|i,0x08,(((unsigned char)chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0),~0,(chanMax+1)*4*2); // needs to 4 sample period delay
|
||||
// initialize filter
|
||||
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].pcm.bank<<14)|(chan[i].filter.mode<<8),0xc300);
|
||||
pageWrite(0x00|i,0x09,chan[i].filter.k1);
|
||||
pageWrite(0x00|i,0x07,chan[i].filter.k2);
|
||||
if ((chan[i].std.ex2.mode==0) && (chan[i].std.ex2.had)) {
|
||||
pageWrite(0x00|i,0x07,MAX(0,MIN(65535,chan[i].filter.k2+chan[i].k2Offs)));
|
||||
} else {
|
||||
pageWrite(0x00|i,0x07,chan[i].filter.k2);
|
||||
}
|
||||
if ((chan[i].std.ex1.mode==0) && (chan[i].std.ex1.had)) {
|
||||
pageWrite(0x00|i,0x09,MAX(0,MIN(65535,chan[i].filter.k1+chan[i].k1Offs)));
|
||||
} else {
|
||||
pageWrite(0x00|i,0x09,chan[i].filter.k1);
|
||||
}
|
||||
pageWrite(0x00|i,0x02,chan[i].resLVol);
|
||||
pageWrite(0x00|i,0x04,chan[i].resRVol);
|
||||
unsigned int loopFlag=0x0000;
|
||||
chan[i].isReversed=false;
|
||||
unsigned int loopFlag=chan[i].pcm.reversed?0x0040:0x0000;
|
||||
chan[i].isReverseLoop=false;
|
||||
switch (chan[i].pcm.loopMode) {
|
||||
case DIV_SAMPLE_LOOPMODE_ONESHOT: // One shot (no loop)
|
||||
default:
|
||||
loopFlag=0x0000;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_FOWARD: // Foward loop
|
||||
loopFlag=0x0008;
|
||||
loopFlag|=0x0008;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_BACKWARD: // Backward loop: IRQ enable
|
||||
loopFlag=0x0038;
|
||||
chan[i].isReversed=true;
|
||||
loopFlag|=0x0038;
|
||||
chan[i].isReverseLoop=true;
|
||||
break;
|
||||
case DIV_SAMPLE_LOOPMODE_PINGPONG: // Pingpong loop: Hardware support
|
||||
loopFlag=0x0018;
|
||||
loopFlag|=0x0018;
|
||||
break;
|
||||
}
|
||||
// Run sample
|
||||
|
|
@ -341,7 +489,7 @@ void DivPlatformES5506::tick() {
|
|||
}
|
||||
}
|
||||
if (chan[i].keyOff) {
|
||||
pageWriteMask(0x00|i,0x5f,0x00,0x0003); // Wipeout CR
|
||||
pageWriteMask(0x00|i,0x5f,0x00,0x0303); // Wipeout CR
|
||||
} else if (chan[i].active) {
|
||||
pageWrite(0x00|i,0x01,chan[i].freq);
|
||||
}
|
||||
|
|
@ -356,30 +504,38 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
chan[c.chan].sample=ins->amiga.useNoteMap?ins->amiga.noteMap[c.value].ind:ins->amiga.initSample;
|
||||
double off=1.0;
|
||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
chan[c.chan].pcm.index=chan[c.chan].sample;
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].sample=ins->amiga.useNoteMap?ins->amiga.noteMap[c.value].ind:ins->amiga.initSample;
|
||||
double off=1.0;
|
||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
chan[c.chan].pcm.index=chan[c.chan].sample;
|
||||
DivSample* s=parent->getSample(chan[c.chan].sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=ins->amiga.useNoteMap?((double)ins->amiga.noteMap[c.value].freq/((double)s->centerRate*pow(2.0,((double)c.value-48.0)/12.0))):((double)s->centerRate/8363.0);
|
||||
}
|
||||
const unsigned int start=s->offES5506<<10;
|
||||
const unsigned int length=s->samples-1;
|
||||
const unsigned int end=start+(length<<11);
|
||||
chan[c.chan].pcm.loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOPMODE_ONESHOT;
|
||||
chan[c.chan].pcm.freqOffs=off;
|
||||
chan[c.chan].pcm.reversed=ins->amiga.reversed;
|
||||
chan[c.chan].pcm.bank=(s->offES5506>>22)&3;
|
||||
chan[c.chan].pcm.start=start;
|
||||
chan[c.chan].pcm.end=end;
|
||||
chan[c.chan].pcm.length=length;
|
||||
chan[c.chan].pcm.loopStart=(start+(s->loopStart<<11))&0xfffff800;
|
||||
chan[c.chan].pcm.loopEnd=(start+((s->loopEnd-1)<<11))&0xffffff80;
|
||||
chan[c.chan].filter=ins->es5506.filter;
|
||||
chan[c.chan].envelope=ins->es5506.envelope;
|
||||
} else {
|
||||
off=ins->amiga.useNoteMap?((double)ins->amiga.noteMap[c.value].freq/((double)s->centerRate*pow(2.0,((double)c.value-48.0)/12.0))):((double)s->centerRate/8363.0);
|
||||
chan[c.chan].sample=-1;
|
||||
chan[c.chan].pcm.index=-1;
|
||||
chan[c.chan].filter=DivInstrumentES5506::Filter();
|
||||
chan[c.chan].envelope=DivInstrumentES5506::Envelope();
|
||||
}
|
||||
unsigned int base=s->offES5506<<10;
|
||||
chan[c.chan].pcm.loopMode=s->isLoopable()?s->loopMode:DIV_SAMPLE_LOOPMODE_ONESHOT;
|
||||
chan[c.chan].pcm.freqOffs=off;
|
||||
chan[c.chan].pcm.bank=(s->offES5506>>22)&3;
|
||||
chan[c.chan].pcm.base=base;
|
||||
chan[c.chan].pcm.loopStart=(base+(s->loopStart<<11))&0xfffff800;
|
||||
chan[c.chan].pcm.loopEnd=((base+(s->loopEnd<<11))-0x800)&0xffffff80;
|
||||
chan[c.chan].filter=ins->es5506.filter;
|
||||
chan[c.chan].envelope=ins->es5506.envelope;
|
||||
} else {
|
||||
chan[c.chan].sample=-1;
|
||||
chan[c.chan].pcm.index=-1;
|
||||
chan[c.chan].filter=DivInstrumentES5506::Filter();
|
||||
chan[c.chan].envelope=DivInstrumentES5506::Envelope();
|
||||
chan[c.chan].insChanged=false;
|
||||
}
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_ES5506(c.chan,c.value);
|
||||
|
|
@ -466,6 +622,45 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
chan[c.chan].pitch=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_WAVE:
|
||||
// reserved for useWave
|
||||
break;
|
||||
// Filter commands
|
||||
case DIV_CMD_ES5506_FILTER_MODE:
|
||||
chan[c.chan].filter.mode=DivInstrumentES5506::Filter::FilterMode(c.value&3);
|
||||
chan[c.chan].filterChanged.mode=1;
|
||||
break;
|
||||
case DIV_CMD_ES5506_FILTER_K1:
|
||||
chan[c.chan].filter.k1=(chan[c.chan].filter.k1&0xf)|((c.value&0xfff)<<4);
|
||||
chan[c.chan].filterChanged.k1=1;
|
||||
break;
|
||||
case DIV_CMD_ES5506_FILTER_K2:
|
||||
chan[c.chan].filter.k2=(chan[c.chan].filter.k2&0xf)|((c.value&0xfff)<<4);
|
||||
chan[c.chan].filterChanged.k2=1;
|
||||
break;
|
||||
// Envelope commands
|
||||
case DIV_CMD_ES5506_ENVELOPE_COUNT:
|
||||
chan[c.chan].envelope.ecount=c.value&0x1ff;
|
||||
chan[c.chan].envChanged.ecount=1;
|
||||
break;
|
||||
case DIV_CMD_ES5506_ENVELOPE_LVRAMP:
|
||||
chan[c.chan].envelope.lVRamp=(signed char)(c.value&0xff);
|
||||
chan[c.chan].envChanged.lVRamp=1;
|
||||
break;
|
||||
case DIV_CMD_ES5506_ENVELOPE_RVRAMP:
|
||||
chan[c.chan].envelope.rVRamp=(signed char)(c.value&0xff);
|
||||
chan[c.chan].envChanged.rVRamp=1;
|
||||
break;
|
||||
case DIV_CMD_ES5506_ENVELOPE_K1RAMP:
|
||||
chan[c.chan].envelope.k1Ramp=(signed char)(c.value&0xff);
|
||||
chan[c.chan].envelope.k1Slow=c.value2&1;
|
||||
chan[c.chan].envChanged.k1Ramp=1;
|
||||
break;
|
||||
case DIV_CMD_ES5506_ENVELOPE_K2RAMP:
|
||||
chan[c.chan].envelope.k2Ramp=(signed char)(c.value&0xff);
|
||||
chan[c.chan].envelope.k2Slow=c.value2&1;
|
||||
chan[c.chan].envChanged.k2Ramp=1;
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_ES5506(c.chan,c.value2);
|
||||
bool return2=false;
|
||||
|
|
@ -501,6 +696,16 @@ int DivPlatformES5506::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
case DIV_CMD_SAMPLE_POS: {
|
||||
if (chan[c.chan].useWave) break;
|
||||
if (chan[c.chan].active) {
|
||||
unsigned int pos=chan[c.chan].pcm.reversed?(chan[c.chan].pcm.length-c.value):c.value;
|
||||
if ((chan[c.chan].pcm.reversed && pos>0) || ((!chan[c.chan].pcm.reversed) && pos<chan[c.chan].pcm.length)) {
|
||||
pageWrite(0x20|c.chan,0x03,chan[c.chan].pcm.start+(pos<<11));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
return 255;
|
||||
break;
|
||||
|
|
@ -523,6 +728,8 @@ void DivPlatformES5506::forceIns() {
|
|||
chan[i].insChanged=true;
|
||||
chan[i].freqChanged=true;
|
||||
chan[i].volChanged=true;
|
||||
chan[i].filterChanged.changed=(unsigned char)(~0);
|
||||
chan[i].envChanged.changed=(unsigned char)(~0);
|
||||
chan[i].sample=-1;
|
||||
}
|
||||
}
|
||||
|
|
@ -629,7 +836,7 @@ int DivPlatformES5506::init(DivEngine* p, int channels, int sugRate, unsigned in
|
|||
setFlags(flags);
|
||||
|
||||
chipClock=16000000;
|
||||
rate=chipClock/16;
|
||||
rate=chipClock/16; // 2 E clock tick (16 CLKIN tick) per voice
|
||||
reset();
|
||||
return 32;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,33 +32,69 @@
|
|||
class DivPlatformES5506: public DivDispatch, public es550x_intf {
|
||||
struct Channel {
|
||||
struct PCM {
|
||||
double freqOffs;
|
||||
int index;
|
||||
double freqOffs;
|
||||
bool reversed;
|
||||
unsigned int bank;
|
||||
unsigned int base;
|
||||
unsigned int start;
|
||||
unsigned int end;
|
||||
unsigned int length;
|
||||
unsigned int loopStart;
|
||||
unsigned int loopEnd;
|
||||
DivSampleLoopMode loopMode;
|
||||
PCM():
|
||||
freqOffs(1.0),
|
||||
index(-1),
|
||||
freqOffs(1.0),
|
||||
reversed(false),
|
||||
bank(0),
|
||||
base(0),
|
||||
start(0),
|
||||
end(0),
|
||||
length(0),
|
||||
loopStart(0),
|
||||
loopEnd(0),
|
||||
loopMode(DIV_SAMPLE_LOOPMODE_ONESHOT) {}
|
||||
} pcm;
|
||||
int freq, baseFreq, pitch;
|
||||
unsigned short audLen;
|
||||
unsigned int audPos;
|
||||
int sample, wave;
|
||||
unsigned char ins;
|
||||
int note;
|
||||
int panning;
|
||||
bool active, insChanged, freqChanged, volChanged, filterChanged, envChanged, rampChanged, keyOn, keyOff, inPorta, useWave, isReversed;
|
||||
int vol, outVol;
|
||||
int lVol, outLVol;
|
||||
int rVol, outRVol;
|
||||
bool active, insChanged, freqChanged, volChanged, keyOn, keyOff, inPorta, useWave, isReverseLoop;
|
||||
|
||||
struct FilterChanged { // Filter changed flags
|
||||
union { // pack flag bits in single byte
|
||||
struct { // flag bits
|
||||
unsigned char mode: 1; // Filter mode
|
||||
unsigned char k1: 1; // K1
|
||||
unsigned char k2: 1; // K2
|
||||
unsigned char dummy: 5; // dummy for bit padding
|
||||
};
|
||||
unsigned char changed; // Packed flags are stored here
|
||||
};
|
||||
|
||||
FilterChanged():
|
||||
changed(0) {}
|
||||
} filterChanged;
|
||||
|
||||
struct EnvChanged { // Envelope changed flags
|
||||
union { // pack flag bits in single byte
|
||||
struct { // flag bits
|
||||
unsigned char ecount: 1; // Envelope count
|
||||
unsigned char lVRamp: 1; // Left volume Ramp
|
||||
unsigned char rVRamp: 1; // Right volume Ramp
|
||||
unsigned char k1Ramp: 1; // K1 Ramp w/Slow flag
|
||||
unsigned char k2Ramp: 1; // K2 Ramp w/Slow flag
|
||||
unsigned char dummy: 3; // dummy for bit padding
|
||||
};
|
||||
unsigned char changed; // Packed flags are stored here
|
||||
};
|
||||
|
||||
EnvChanged():
|
||||
changed(0) {}
|
||||
} envChanged;
|
||||
|
||||
signed int k1Offs, k2Offs;
|
||||
int vol, lVol, rVol;
|
||||
int outVol, outLVol, outRVol;
|
||||
int resLVol, resRVol;
|
||||
DivInstrumentES5506::Filter filter;
|
||||
DivInstrumentES5506::Envelope envelope;
|
||||
|
|
@ -67,27 +103,23 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
|
|||
freq(0),
|
||||
baseFreq(0),
|
||||
pitch(0),
|
||||
audLen(0),
|
||||
audPos(0),
|
||||
sample(-1),
|
||||
ins(-1),
|
||||
note(0),
|
||||
panning(0x10),
|
||||
active(false),
|
||||
insChanged(true),
|
||||
freqChanged(false),
|
||||
volChanged(false),
|
||||
filterChanged(false),
|
||||
envChanged(false),
|
||||
rampChanged(false),
|
||||
keyOn(false),
|
||||
keyOff(false),
|
||||
inPorta(false),
|
||||
vol(0xffff),
|
||||
k1Offs(0),
|
||||
k2Offs(0),
|
||||
vol(0xff),
|
||||
lVol(0xf),
|
||||
rVol(0xf),
|
||||
outVol(0xffff),
|
||||
lVol(0xffff),
|
||||
outLVol(0xffff),
|
||||
rVol(0xffff),
|
||||
outRVol(0xffff),
|
||||
resLVol(0xffff),
|
||||
resRVol(0xffff) {}
|
||||
|
|
@ -150,7 +182,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
|
|||
virtual int getRegisterPoolSize() override;
|
||||
virtual void reset() override;
|
||||
virtual void forceIns() override;
|
||||
virtual void tick() override;
|
||||
virtual void tick(bool sysTick=true) override;
|
||||
virtual void muteChannel(int ch, bool mute) override;
|
||||
virtual bool isStereo() override;
|
||||
virtual bool keyOffAffectsArp(int ch) override;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ void DivPlatformFDS::updateWave() {
|
|||
rWrite(0x4089,0);
|
||||
}
|
||||
|
||||
void DivPlatformFDS::tick() {
|
||||
void DivPlatformFDS::tick(bool sysTick) {
|
||||
for (int i=0; i<1; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -107,21 +107,11 @@ void DivPlatformFDS::tick() {
|
|||
rWrite(0x4080,0x80|chan[i].outVol);
|
||||
}
|
||||
if (chan[i].std.arp.had) {
|
||||
if (i==3) { // noise
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arp.mode) {
|
||||
chan[i].baseFreq=chan[i].std.arp.val;
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||
} else {
|
||||
chan[i].baseFreq=chan[i].note+chan[i].std.arp.val;
|
||||
}
|
||||
if (chan[i].baseFreq>255) chan[i].baseFreq=255;
|
||||
if (chan[i].baseFreq<0) chan[i].baseFreq=0;
|
||||
} else {
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arp.mode) {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].std.arp.val);
|
||||
} else {
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note+chan[i].std.arp.val);
|
||||
}
|
||||
chan[i].baseFreq=NOTE_FREQUENCY(chan[i].note+chan[i].std.arp.val);
|
||||
}
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
|
|
@ -155,6 +145,9 @@ void DivPlatformFDS::tick() {
|
|||
//if (!chan[i].keyOff) chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].active) {
|
||||
if (ws.tick()) {
|
||||
updateWave();
|
||||
|
|
@ -205,7 +198,7 @@ void DivPlatformFDS::tick() {
|
|||
int DivPlatformFDS::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FDS);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -365,7 +358,7 @@ int DivPlatformFDS::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_FDS));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class DivPlatformFDS: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ static unsigned char noiseTable[256]={
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
void DivPlatformGB::tick() {
|
||||
void DivPlatformGB::tick(bool sysTick) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.arp.had) {
|
||||
|
|
@ -176,7 +176,7 @@ void DivPlatformGB::tick() {
|
|||
}
|
||||
if (chan[i].std.duty.had) {
|
||||
chan[i].duty=chan[i].std.duty.val;
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_GB);
|
||||
if (i!=2) {
|
||||
rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63)));
|
||||
} else {
|
||||
|
|
@ -192,6 +192,14 @@ void DivPlatformGB::tick() {
|
|||
if (!chan[i].keyOff) chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.panL.had) {
|
||||
lastPan&=~(0x11<<i);
|
||||
lastPan|=((chan[i].std.panL.val&1)<<i)|((chan[i].std.panL.val&2)<<(i+3));
|
||||
rWrite(0x25,procMute());
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -212,7 +220,7 @@ void DivPlatformGB::tick() {
|
|||
}
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_GB);
|
||||
if (i==3) { // noise
|
||||
int ntPos=chan[i].baseFreq;
|
||||
if (ntPos<0) ntPos=0;
|
||||
|
|
@ -261,7 +269,7 @@ void DivPlatformGB::muteChannel(int ch, bool mute) {
|
|||
int DivPlatformGB::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_GB);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
if (c.chan==3) { // noise
|
||||
chan[c.chan].baseFreq=c.value;
|
||||
|
|
@ -298,7 +306,7 @@ int DivPlatformGB::dispatch(DivCommand c) {
|
|||
chan[c.chan].ins=c.value;
|
||||
chan[c.chan].insChanged=true;
|
||||
if (c.chan!=2) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_GB);
|
||||
chan[c.chan].vol=ins->gb.envVol;
|
||||
if (parent->song.gbInsAffectsEnvelope) {
|
||||
rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(ins->gb.envLen&7)|((ins->gb.envDir&1)<<3));
|
||||
|
|
@ -352,7 +360,7 @@ int DivPlatformGB::dispatch(DivCommand c) {
|
|||
chan[c.chan].duty=c.value;
|
||||
if (c.chan!=2) {
|
||||
chan[c.chan].freqChanged=true;
|
||||
rWrite(16+c.chan*5+1,((chan[c.chan].duty&3)<<6)|(63-(parent->getIns(chan[c.chan].ins)->gb.soundLen&63)));
|
||||
rWrite(16+c.chan*5+1,((chan[c.chan].duty&3)<<6)|(63-(parent->getIns(chan[c.chan].ins,DIV_INS_GB)->gb.soundLen&63)));
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_PANNING: {
|
||||
|
|
@ -371,7 +379,7 @@ int DivPlatformGB::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_GB));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class DivPlatformGB: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
void notifyInsChange(int ins);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::tick() {
|
||||
void DivPlatformGenesis::tick(bool sysTick) {
|
||||
for (int i=0; i<6; i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
chan[i].std.next();
|
||||
|
|
@ -260,6 +260,15 @@ void DivPlatformGenesis::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan=chan[i].std.panL.val&3;
|
||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -477,7 +486,7 @@ void DivPlatformGenesis::muteChannel(int ch, bool mute) {
|
|||
int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (c.chan==5) {
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
dacMode=1;
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
void setYMFM(bool use);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
|||
int ordch=orderedOps[ch];
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
||||
if (opChan[ch].insChanged) {
|
||||
chan[2].state.alg=ins->fm.alg;
|
||||
|
|
@ -266,7 +266,7 @@ static int opChanOffsH[4]={
|
|||
0xad, 0xae, 0xac, 0xa6
|
||||
};
|
||||
|
||||
void DivPlatformGenesisExt::tick() {
|
||||
void DivPlatformGenesisExt::tick(bool sysTick) {
|
||||
if (extMode) {
|
||||
bool writeSomething=false;
|
||||
unsigned char writeMask=2;
|
||||
|
|
@ -283,7 +283,7 @@ void DivPlatformGenesisExt::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
DivPlatformGenesis::tick();
|
||||
DivPlatformGenesis::tick(sysTick);
|
||||
|
||||
bool writeNoteOn=false;
|
||||
unsigned char writeMask=2;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
|
|||
void* getChanState(int chan);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
bool keyOffAffectsPorta(int ch);
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len
|
|||
mikey->sampleAudio( bufL + start, bufR + start, len );
|
||||
}
|
||||
|
||||
void DivPlatformLynx::tick() {
|
||||
void DivPlatformLynx::tick(bool sysTick) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -171,6 +171,24 @@ void DivPlatformLynx::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan&=0x0f;
|
||||
chan[i].pan|=(chan[i].std.panL.val&15)<<4;
|
||||
}
|
||||
|
||||
if (chan[i].std.panR.had) {
|
||||
chan[i].pan&=0xf0;
|
||||
chan[i].pan|=chan[i].std.panR.val&15;
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had || chan[i].std.panR.had) {
|
||||
WRITE_ATTEN(i,chan[i].pan);
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].freqChanged) {
|
||||
if (chan[i].lfsr >= 0) {
|
||||
WRITE_LFSR(i, (chan[i].lfsr&0xff));
|
||||
|
|
@ -184,8 +202,8 @@ void DivPlatformLynx::tick() {
|
|||
}
|
||||
WRITE_CONTROL(i, (chan[i].fd.clockDivider|0x18|chan[i].duty.int_feedback7));
|
||||
WRITE_BACKUP( i, chan[i].fd.backup );
|
||||
}
|
||||
else if (chan[i].std.duty.had) {
|
||||
chan[i].freqChanged=false;
|
||||
} else if (chan[i].std.duty.had) {
|
||||
chan[i].duty = chan[i].std.duty.val;
|
||||
WRITE_FEEDBACK(i, chan[i].duty.feedback);
|
||||
WRITE_CONTROL(i, (chan[i].fd.clockDivider|0x18|chan[i].duty.int_feedback7));
|
||||
|
|
@ -206,7 +224,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127)));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
chan[c.chan].active=false;
|
||||
|
|
@ -223,7 +241,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_INSTRUMENT:
|
||||
chan[c.chan].ins=c.value;
|
||||
//chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
//chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
|
||||
break;
|
||||
case DIV_CMD_VOLUME:
|
||||
if (chan[c.chan].vol!=c.value) {
|
||||
|
|
@ -279,7 +297,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ class DivPlatformLynx: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformMMC5::tick() {
|
||||
void DivPlatformMMC5::tick(bool sysTick) {
|
||||
for (int i=0; i<2; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -124,6 +124,9 @@ void DivPlatformMMC5::tick() {
|
|||
chan[i].duty=chan[i].std.duty.val;
|
||||
rWrite(0x5000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].freqChanged=true;
|
||||
|
|
@ -175,7 +178,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
if (c.chan==2) { // PCM
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
dacSample=ins->amiga.initSample;
|
||||
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
||||
|
|
@ -225,7 +228,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
rWrite(0x5000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
|
|
@ -303,7 +306,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class DivPlatformMMC5: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
float getPostAmp();
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ void DivPlatformN163::updateWaveCh(int ch) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformN163::tick() {
|
||||
void DivPlatformN163::tick(bool sysTick) {
|
||||
for (int i=0; i<=chanMax; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -261,6 +261,9 @@ void DivPlatformN163::tick() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
if (chan[i].waveLen!=(chan[i].std.ex1.val&0xfc)) {
|
||||
chan[i].waveLen=chan[i].std.ex1.val&0xfc;
|
||||
|
|
@ -371,7 +374,7 @@ void DivPlatformN163::tick() {
|
|||
int DivPlatformN163::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_N163);
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].wave=ins->n163.wave;
|
||||
chan[c.chan].ws.changeWave1(chan[c.chan].wave);
|
||||
|
|
@ -543,7 +546,7 @@ int DivPlatformN163::dispatch(DivCommand c) {
|
|||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) {
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_N163));
|
||||
chan[c.chan].keyOn=true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class DivPlatformN163: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setFlags(unsigned int flags);
|
||||
void notifyWaveChange(int wave);
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ static unsigned char noiseTable[253]={
|
|||
15
|
||||
};
|
||||
|
||||
void DivPlatformNES::tick() {
|
||||
void DivPlatformNES::tick(bool sysTick) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -196,6 +196,9 @@ void DivPlatformNES::tick() {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].sweepChanged) {
|
||||
chan[i].sweepChanged=false;
|
||||
if (i==0) {
|
||||
|
|
@ -269,7 +272,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
if (c.chan==4) { // PCM
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
dacSample=ins->amiga.initSample;
|
||||
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
|
||||
|
|
@ -323,7 +326,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
if (c.chan==2) {
|
||||
rWrite(0x4000+c.chan*4,0xff);
|
||||
} else {
|
||||
|
|
@ -426,7 +429,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class DivPlatformNES: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
float getPostAmp();
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ void DivPlatformOPL::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
|||
//}
|
||||
}
|
||||
|
||||
void DivPlatformOPL::tick() {
|
||||
void DivPlatformOPL::tick(bool sysTick) {
|
||||
for (int i=0; i<totalChans; i++) {
|
||||
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
|
||||
chan[i].std.next();
|
||||
|
|
@ -269,6 +269,14 @@ void DivPlatformOPL::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (oplType==3 && chan[i].std.panL.had) {
|
||||
chan[i].pan=((chan[i].std.panL.val&1)<<1)|((chan[i].std.panL.val&2)>>1);
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -282,7 +290,7 @@ void DivPlatformOPL::tick() {
|
|||
chan[i].state.fb=chan[i].std.fb.val;
|
||||
}
|
||||
|
||||
if (chan[i].std.alg.had || chan[i].std.fb.had) {
|
||||
if (chan[i].std.alg.had || chan[i].std.fb.had || (oplType==3 && chan[i].std.panL.had)) {
|
||||
if (isMuted[i]) {
|
||||
rWrite(chanMap[i]+ADDR_LR_FB_ALG,(chan[i].state.alg&1)|(chan[i].state.fb<<1));
|
||||
if (ops==4) {
|
||||
|
|
@ -527,7 +535,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
|||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPL);
|
||||
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].state=ins->fm;
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class DivPlatformOPL: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
void setYMFM(bool use);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ void DivPlatformOPLL::acquire(short* bufL, short* bufR, size_t start, size_t len
|
|||
acquire_nuked(bufL,bufR,start,len);
|
||||
}
|
||||
|
||||
void DivPlatformOPLL::tick() {
|
||||
void DivPlatformOPLL::tick(bool sysTick) {
|
||||
for (int i=0; i<11; i++) {
|
||||
chan[i].std.next();
|
||||
|
||||
|
|
@ -145,6 +145,10 @@ void DivPlatformOPLL::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -361,7 +365,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan>=9 && !properDrums) return 0;
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPLL);
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].state=ins->fm;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class DivPlatformOPLL: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setYMFM(bool use);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ static unsigned char noiseFreq[12]={
|
|||
4,13,15,18,21,23,25,27,29,31,0,2
|
||||
};
|
||||
|
||||
void DivPlatformPCE::tick() {
|
||||
void DivPlatformPCE::tick(bool sysTick) {
|
||||
for (int i=0; i<6; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -196,13 +196,27 @@ void DivPlatformPCE::tick() {
|
|||
if (!chan[i].keyOff) chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan&=0x0f;
|
||||
chan[i].pan|=(chan[i].std.panL.val&15)<<4;
|
||||
}
|
||||
if (chan[i].std.panR.had) {
|
||||
chan[i].pan&=0xf0;
|
||||
chan[i].pan|=chan[i].std.panR.val&15;
|
||||
}
|
||||
if (chan[i].std.panL.had || chan[i].std.panR.had) {
|
||||
chWrite(i,0x05,isMuted[i]?0:chan[i].pan);
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].active) {
|
||||
if (chan[i].ws.tick() || (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1)) {
|
||||
updateWave(i);
|
||||
}
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
||||
if (chan[i].furnaceDac) {
|
||||
double off=1.0;
|
||||
|
|
@ -237,7 +251,7 @@ void DivPlatformPCE::tick() {
|
|||
int DivPlatformPCE::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE);
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
chan[c.chan].pcm=true;
|
||||
} else if (chan[c.chan].furnaceDac) {
|
||||
|
|
@ -415,7 +429,7 @@ int DivPlatformPCE::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_PCE));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class DivPlatformPCE: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ void DivPlatformPCSpeaker::acquire(short* bufL, short* bufR, size_t start, size_
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformPCSpeaker::tick() {
|
||||
void DivPlatformPCSpeaker::tick(bool sysTick) {
|
||||
for (int i=0; i<1; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -186,6 +186,9 @@ void DivPlatformPCSpeaker::tick() {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
|
|
@ -214,7 +217,7 @@ int DivPlatformPCSpeaker::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER));
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
chan[c.chan].active=false;
|
||||
|
|
@ -279,7 +282,7 @@ int DivPlatformPCSpeaker::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_BEEPER));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class DivPlatformPCSpeaker: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ void DivPlatformPET::writeOutVol() {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformPET::tick() {
|
||||
void DivPlatformPET::tick(bool sysTick) {
|
||||
chan.std.next();
|
||||
if (chan.std.vol.had) {
|
||||
chan.outVol=chan.std.vol.val&chan.vol;
|
||||
|
|
@ -112,6 +112,9 @@ void DivPlatformPET::tick() {
|
|||
rWrite(10,chan.wave);
|
||||
}
|
||||
}
|
||||
if (chan.std.pitch.had) {
|
||||
chan.freqChanged=true;
|
||||
}
|
||||
if (chan.freqChanged || chan.keyOn || chan.keyOff) {
|
||||
chan.freq=parent->calcFreq(chan.baseFreq,chan.pitch,true)+chan.std.pitch.val;
|
||||
if (chan.freq>257) chan.freq=257;
|
||||
|
|
@ -135,7 +138,7 @@ void DivPlatformPET::tick() {
|
|||
int DivPlatformPET::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan.ins);
|
||||
DivInstrument* ins=parent->getIns(chan.ins,DIV_INS_PET);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan.baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan.freqChanged=true;
|
||||
|
|
@ -210,7 +213,7 @@ int DivPlatformPET::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan.active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan.std.init(parent->getIns(chan.ins));
|
||||
if (parent->song.resetMacroOnPorta) chan.std.init(parent->getIns(chan.ins,DIV_INS_PET));
|
||||
}
|
||||
chan.inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class DivPlatformPET: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void notifyInsDeletion(void* ins);
|
||||
bool isStereo();
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ void DivPlatformQSound::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformQSound::tick() {
|
||||
void DivPlatformQSound::tick(bool sysTick) {
|
||||
for (int i=0; i<16; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -326,8 +326,11 @@ void DivPlatformQSound::tick() {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_AMIGA);
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false)+chan[i].std.pitch.val;
|
||||
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
||||
if (chan[i].keyOn) {
|
||||
|
|
@ -360,7 +363,7 @@ void DivPlatformQSound::tick() {
|
|||
int DivPlatformQSound::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||
chan[c.chan].sample=ins->amiga.initSample;
|
||||
double off=1.0;
|
||||
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
|
||||
|
|
@ -484,7 +487,7 @@ int DivPlatformQSound::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class DivPlatformQSound: public DivDispatch {
|
|||
int getRegisterPoolDepth();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ inline unsigned char applyPan(unsigned char vol, unsigned char pan) {
|
|||
return ((vol*(pan>>4))/15)|(((vol*(pan&15))/15)<<4);
|
||||
}
|
||||
|
||||
void DivPlatformSAA1099::tick() {
|
||||
void DivPlatformSAA1099::tick(bool sysTick) {
|
||||
for (int i=0; i<6; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -166,6 +166,29 @@ void DivPlatformSAA1099::tick() {
|
|||
if (chan[i].std.wave.had) {
|
||||
chan[i].psgMode=chan[i].std.wave.val&3;
|
||||
}
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan&=0x0f;
|
||||
chan[i].pan|=(chan[i].std.panL.val&15)<<4;
|
||||
}
|
||||
|
||||
if (chan[i].std.panR.had) {
|
||||
chan[i].pan&=0xf0;
|
||||
chan[i].pan|=chan[i].std.panR.val&15;
|
||||
}
|
||||
if (chan[i].std.panL.had || chan[i].std.panR.had) {
|
||||
if (isMuted[i]) {
|
||||
rWrite(i,0);
|
||||
} else {
|
||||
if (chan[i].std.vol.had) {
|
||||
if (chan[i].active) rWrite(i,applyPan(chan[i].outVol&15,chan[i].pan));
|
||||
} else {
|
||||
if (chan[i].active) rWrite(i,applyPan(chan[i].vol&15,chan[i].pan));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
saaEnv[i/3]=chan[i].std.ex1.val;
|
||||
rWrite(0x18+(i/3),saaEnv[i/3]);
|
||||
|
|
@ -226,7 +249,7 @@ void DivPlatformSAA1099::tick() {
|
|||
int DivPlatformSAA1099::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_SAA1099);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -333,7 +356,7 @@ int DivPlatformSAA1099::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SAA1099));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class DivPlatformSAA1099: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setCore(DivSAACores core);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -76,13 +76,14 @@ void DivPlatformSegaPCM::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformSegaPCM::tick() {
|
||||
void DivPlatformSegaPCM::tick(bool sysTick) {
|
||||
for (int i=0; i<16; i++) {
|
||||
chan[i].std.next();
|
||||
|
||||
if (chan[i].std.vol.had) {
|
||||
// TODO: fix
|
||||
/*if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=(chan[i].vol*MIN(127,chan[i].std.vol.val))/127;
|
||||
}
|
||||
}*/
|
||||
|
||||
if (chan[i].std.arp.had) {
|
||||
if (!chan[i].inPorta) {
|
||||
|
|
@ -99,6 +100,24 @@ void DivPlatformSegaPCM::tick() {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].chVolL=chan[i].std.panL.val&127;
|
||||
if (dumpWrites) {
|
||||
addWrite(0x10002+(i<<3),chan[i].chVolL);
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.panR.had) {
|
||||
chan[i].chVolR=chan[i].std.panR.val&127;
|
||||
if (dumpWrites) {
|
||||
addWrite(0x10003+(i<<3),chan[i].chVolR);
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
/*if (chan[i].keyOn || chan[i].keyOff) {
|
||||
chan[i].keyOff=false;
|
||||
}*/
|
||||
|
|
@ -130,7 +149,7 @@ void DivPlatformSegaPCM::muteChannel(int ch, bool mute) {
|
|||
int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||
if (skipRegisterWrites) break;
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
chan[c.chan].pcm.sample=ins->amiga.initSample;
|
||||
|
|
@ -139,14 +158,17 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
|||
if (dumpWrites) {
|
||||
addWrite(0x10086+(c.chan<<3),3);
|
||||
}
|
||||
chan[c.chan].std.init(NULL);
|
||||
break;
|
||||
}
|
||||
chan[c.chan].pcm.pos=0;
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].baseFreq=(c.value<<6);
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].furnacePCM=true;
|
||||
chan[c.chan].std.init(ins);
|
||||
if (dumpWrites) { // Sega PCM writes
|
||||
DivSample* s=parent->getSample(chan[c.chan].pcm.sample);
|
||||
addWrite(0x10086+(c.chan<<3),3+((s->offSegaPCM>>16)<<3));
|
||||
|
|
@ -163,6 +185,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].std.init(NULL);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].note=c.value;
|
||||
}
|
||||
|
|
@ -204,6 +227,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) {
|
|||
chan[c.chan].keyOff=true;
|
||||
chan[c.chan].keyOn=false;
|
||||
chan[c.chan].active=false;
|
||||
chan[c.chan].std.init(NULL);
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF_ENV:
|
||||
chan[c.chan].keyOff=true;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class DivPlatformSegaPCM: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void notifyInsChange(int ins);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#define rWrite(v) {if (!skipRegisterWrites) {sn->write(v); if (dumpWrites) {addWrite(0x200,v);}}}
|
||||
|
||||
#define CHIP_DIVIDER 64
|
||||
|
||||
const char* regCheatSheetSN[]={
|
||||
"DATA", "0",
|
||||
NULL
|
||||
|
|
@ -53,8 +51,10 @@ int DivPlatformSMS::acquireOne() {
|
|||
return v;
|
||||
}
|
||||
|
||||
void DivPlatformSMS::tick() {
|
||||
void DivPlatformSMS::tick(bool sysTick) {
|
||||
for (int i=0; i<4; i++) {
|
||||
int CHIP_DIVIDER=64;
|
||||
if (i==3 && isRealSN) CHIP_DIVIDER=60;
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=MIN(15,chan[i].std.vol.val)-(15-(chan[i].vol&15));
|
||||
|
|
@ -98,6 +98,9 @@ void DivPlatformSMS::tick() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<3; i++) {
|
||||
if (chan[i].freqChanged) {
|
||||
|
|
@ -116,8 +119,7 @@ void DivPlatformSMS::tick() {
|
|||
}
|
||||
}
|
||||
if (chan[3].freqChanged || updateSNMode) {
|
||||
// seems arbitrary huh?
|
||||
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch-1-(isRealSN?127:0),true)+chan[3].std.pitch.val;
|
||||
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true)+chan[3].std.pitch.val;
|
||||
if (chan[3].freq>1023) chan[3].freq=1023;
|
||||
if (chan[3].actualNote>0x5d) chan[3].freq=0x01;
|
||||
if (snNoiseMode&2) { // take period from channel 3
|
||||
|
|
@ -161,6 +163,8 @@ void DivPlatformSMS::tick() {
|
|||
}
|
||||
|
||||
int DivPlatformSMS::dispatch(DivCommand c) {
|
||||
int CHIP_DIVIDER=64;
|
||||
if (c.chan==3 && isRealSN) CHIP_DIVIDER=60;
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
|
|
@ -171,7 +175,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
rWrite(0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15))));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
chan[c.chan].active=false;
|
||||
|
|
@ -184,7 +188,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_INSTRUMENT:
|
||||
chan[c.chan].ins=c.value;
|
||||
//chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
//chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
break;
|
||||
case DIV_CMD_VOLUME:
|
||||
if (chan[c.chan].vol!=c.value) {
|
||||
|
|
@ -240,7 +244,7 @@ int DivPlatformSMS::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_STD));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class DivPlatformSMS: public DivDispatch {
|
|||
void* getChanState(int chan);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
bool keyOffAffectsPorta(int ch);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ namespace es550x
|
|||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
|
|
@ -250,12 +251,14 @@ protected:
|
|||
: m_integer(integer)
|
||||
, m_fraction(fraction)
|
||||
, m_total_bits(integer + fraction)
|
||||
, m_accum_mask(u32(std::min<u64>(~0, u64(u64(1) << u64(integer + fraction)) - 1)))
|
||||
, m_transwave(transwave)
|
||||
{}
|
||||
|
||||
const u8 m_integer;
|
||||
const u8 m_fraction;
|
||||
const u8 m_total_bits;
|
||||
const u32 m_accum_mask;
|
||||
const bool m_transwave;
|
||||
|
||||
void reset();
|
||||
|
|
|
|||
|
|
@ -29,15 +29,14 @@ bool es550x_shared_core::es550x_alu_t::busy()
|
|||
bool es550x_shared_core::es550x_alu_t::tick()
|
||||
{
|
||||
if (m_cr.dir)
|
||||
{
|
||||
m_accum = bitfield(m_accum - m_fc, 0, m_total_bits);
|
||||
return ((!m_cr.lei) && (m_accum < m_start)) ? true : false;
|
||||
}
|
||||
m_accum -= m_fc;
|
||||
else
|
||||
{
|
||||
m_accum = bitfield(m_accum + m_fc, 0, m_total_bits);
|
||||
return ((!m_cr.lei) && (m_accum > m_end)) ? true : false;
|
||||
}
|
||||
m_accum += m_fc;
|
||||
|
||||
m_accum &= m_accum_mask;
|
||||
return ((!m_cr.lei)
|
||||
&& ((( m_cr.dir) && (m_accum < m_start))
|
||||
|| ((!m_cr.dir) && (m_accum > m_end)))) ? true : false;
|
||||
}
|
||||
|
||||
void es550x_shared_core::es550x_alu_t::loop_exec()
|
||||
|
|
|
|||
|
|
@ -141,13 +141,13 @@ void DivPlatformSwan::writeOutVol(int ch) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformSwan::tick() {
|
||||
void DivPlatformSwan::tick(bool sysTick) {
|
||||
unsigned char sndCtrl=(pcm?0x20:0)|(sweep?0x40:0)|((noise>0)?0x80:0);
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
int env=chan[i].std.vol.val;
|
||||
if(parent->getIns(chan[i].ins)->type==DIV_INS_AMIGA) {
|
||||
if(parent->getIns(chan[i].ins,DIV_INS_SWAN)->type==DIV_INS_AMIGA) {
|
||||
env=MIN(env/4,15);
|
||||
}
|
||||
calcAndWriteOutVol(i,env);
|
||||
|
|
@ -173,6 +173,20 @@ void DivPlatformSwan::tick() {
|
|||
chan[i].ws.changeWave1(chan[i].wave);
|
||||
}
|
||||
}
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan&=0x0f;
|
||||
chan[i].pan|=(chan[i].std.panL.val&15)<<4;
|
||||
}
|
||||
if (chan[i].std.panR.had) {
|
||||
chan[i].pan&=0xf0;
|
||||
chan[i].pan|=chan[i].std.panR.val&15;
|
||||
}
|
||||
if (chan[i].std.panL.had || chan[i].std.panR.had) {
|
||||
calcAndWriteOutVol(i,chan[i].std.vol.will?chan[i].std.vol.val:15);
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].active) {
|
||||
sndCtrl|=(1<<i);
|
||||
if (chan[i].ws.tick()) {
|
||||
|
|
@ -226,7 +240,7 @@ void DivPlatformSwan::tick() {
|
|||
int DivPlatformSwan::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_SWAN);
|
||||
if (c.chan==1) {
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
pcm=true;
|
||||
|
|
@ -401,7 +415,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_SWAN));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class DivPlatformSwan: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void notifyWaveChange(int wave);
|
||||
void notifyInsDeletion(void* ins);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ unsigned char DivPlatformTIA::dealWithFreq(unsigned char shape, int base, int pi
|
|||
return 0;
|
||||
}
|
||||
|
||||
void DivPlatformTIA::tick() {
|
||||
void DivPlatformTIA::tick(bool sysTick) {
|
||||
for (int i=0; i<2; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -116,6 +116,9 @@ void DivPlatformTIA::tick() {
|
|||
rWrite(0x15+i,chan[i].shape);
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
if (chan[i].insChanged) {
|
||||
if (!chan[i].std.wave.will) {
|
||||
|
|
@ -151,7 +154,7 @@ void DivPlatformTIA::tick() {
|
|||
int DivPlatformTIA::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_TIA);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=c.value<<8;
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -245,7 +248,7 @@ int DivPlatformTIA::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_TIA));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class DivPlatformTIA: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setFlags(unsigned int flags);
|
||||
bool isStereo();
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ inline int hScale(int note) {
|
|||
return ((note/12)<<4)+(noteMap[note%12]);
|
||||
}
|
||||
|
||||
void DivPlatformTX81Z::tick() {
|
||||
void DivPlatformTX81Z::tick(bool sysTick) {
|
||||
for (int i=0; i<8; i++) {
|
||||
chan[i].std.next();
|
||||
|
||||
|
|
@ -228,6 +228,10 @@ void DivPlatformTX81Z::tick() {
|
|||
rWrite(0x1b,chan[i].std.wave.val&3);
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -420,7 +424,7 @@ void DivPlatformTX81Z::muteChannel(int ch, bool mute) {
|
|||
int DivPlatformTX81Z::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPZ);
|
||||
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].state=ins->fm;
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class DivPlatformTX81Z: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void notifyInsChange(int ins);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len
|
|||
psg_render(psg,buf[0],buf[1],curLen);
|
||||
pcm_render(pcm,buf[2],buf[3],curLen);
|
||||
for (int i=0; i<curLen; i++) {
|
||||
bufL[pos]=(short)(((int)buf[0][i]+(buf[2][i]>>1))/2);
|
||||
bufR[pos]=(short)(((int)buf[1][i]+(buf[3][i]>>1))/2);
|
||||
bufL[pos]=(short)(((int)buf[0][i]+buf[2][i])/2);
|
||||
bufR[pos]=(short)(((int)buf[1][i]+buf[3][i])/2);
|
||||
pos++;
|
||||
}
|
||||
len-=curLen;
|
||||
|
|
@ -156,7 +156,7 @@ int DivPlatformVERA::calcNoteFreq(int ch, int note) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformVERA::tick() {
|
||||
void DivPlatformVERA::tick(bool sysTick) {
|
||||
for (int i=0; i<16; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -184,6 +184,15 @@ void DivPlatformVERA::tick() {
|
|||
if (chan[i].std.wave.had) {
|
||||
rWriteHi(i,3,chan[i].std.wave.val);
|
||||
}
|
||||
if (i<16) {
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan=chan[i].std.panL.val&3;
|
||||
rWriteHi(i,2,isMuted[i]?0:chan[i].pan);
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].freqChanged) {
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,8)+chan[i].std.pitch.val;
|
||||
if (chan[i].freq>65535) chan[i].freq=65535;
|
||||
|
|
@ -228,7 +237,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
|
|||
if(c.chan<16) {
|
||||
rWriteLo(c.chan,2,chan[c.chan].vol)
|
||||
} else {
|
||||
chan[16].pcm.sample=parent->getIns(chan[16].ins)->amiga.initSample;
|
||||
chan[16].pcm.sample=parent->getIns(chan[16].ins,DIV_INS_VERA)->amiga.initSample;
|
||||
if (chan[16].pcm.sample<0 || chan[16].pcm.sample>=parent->song.sampleLen) {
|
||||
chan[16].pcm.sample=-1;
|
||||
}
|
||||
|
|
@ -250,7 +259,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
|
|||
chan[c.chan].note=c.value;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VERA));
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
chan[c.chan].active=false;
|
||||
|
|
@ -318,7 +327,7 @@ int DivPlatformVERA::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VERA));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
@ -374,7 +383,7 @@ void DivPlatformVERA::muteChannel(int ch, bool mute) {
|
|||
}
|
||||
|
||||
float DivPlatformVERA::getPostAmp() {
|
||||
return 4.0f;
|
||||
return 8.0f;
|
||||
}
|
||||
|
||||
bool DivPlatformVERA::isStereo() {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class DivPlatformVERA: public DivDispatch {
|
|||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void notifyInsDeletion(void* ins);
|
||||
float getPostAmp();
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void DivPlatformVIC20::writeOutVol(int ch) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformVIC20::tick() {
|
||||
void DivPlatformVIC20::tick(bool sysTick) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -119,6 +119,9 @@ void DivPlatformVIC20::tick() {
|
|||
chan[i].keyOn=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)+chan[i].std.pitch.val;
|
||||
if (i<3) {
|
||||
|
|
@ -155,7 +158,7 @@ void DivPlatformVIC20::tick() {
|
|||
int DivPlatformVIC20::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_VIC);
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
@ -229,7 +232,7 @@ int DivPlatformVIC20::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VIC));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class DivPlatformVIC20: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setFlags(unsigned int flags);
|
||||
void notifyInsDeletion(void* ins);
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformVRC6::tick() {
|
||||
void DivPlatformVRC6::tick(bool sysTick) {
|
||||
for (int i=0; i<3; i++) {
|
||||
// 16 for pulse; 14 for saw
|
||||
int CHIP_DIVIDER=(i==2)?14:16;
|
||||
|
|
@ -178,6 +178,9 @@ void DivPlatformVRC6::tick() {
|
|||
chWrite(i,0,(chan[i].outVol&0xf)|((chan[i].duty&7)<<4));
|
||||
}
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
if (i==2) { // sawtooth
|
||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true)-1+chan[i].std.pitch.val;
|
||||
|
|
@ -217,7 +220,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
if (c.chan!=2) { // pulse wave
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_VRC6);
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
chan[c.chan].pcm=true;
|
||||
} else if (chan[c.chan].furnaceDac) {
|
||||
|
|
@ -281,7 +284,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6));
|
||||
if (!isMuted[c.chan]) {
|
||||
if (c.chan==2) { // sawtooth
|
||||
chWrite(c.chan,0,chan[c.chan].vol);
|
||||
|
|
@ -377,7 +380,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_VRC6));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
@ -431,9 +434,9 @@ void DivPlatformVRC6::reset() {
|
|||
chan[i]=DivPlatformVRC6::Channel();
|
||||
chan[i].std.setEngine(parent);
|
||||
}
|
||||
// a poll may be necessary to decide the default
|
||||
chan[2].vol=30;
|
||||
chan[2].outVol=30;
|
||||
// HELP
|
||||
chan[2].vol=63;
|
||||
chan[2].outVol=63;
|
||||
if (dumpWrites) {
|
||||
addWrite(0xffffffff,0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class DivPlatformVRC6: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setFlags(unsigned int flags);
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ void DivPlatformX1_010::updateEnvelope(int ch) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformX1_010::tick() {
|
||||
void DivPlatformX1_010::tick(bool sysTick) {
|
||||
for (int i=0; i<16; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
|
@ -372,6 +372,19 @@ void DivPlatformX1_010::tick() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan&=0x0f;
|
||||
chan[i].pan|=(chan[i].std.panL.val&15)<<4;
|
||||
chan[i].envChanged=true;
|
||||
}
|
||||
if (chan[i].std.panR.had) {
|
||||
chan[i].pan&=0xf0;
|
||||
chan[i].pan|=chan[i].std.panR.val&15;
|
||||
chan[i].envChanged=true;
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
bool nextEnable=(chan[i].std.ex1.val&1);
|
||||
if (nextEnable!=(chan[i].env.flag.envEnable)) {
|
||||
|
|
@ -512,7 +525,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
chWrite(c.chan,0,0); // reset previous note
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_X1_010);
|
||||
if ((ins->type==DIV_INS_AMIGA) || chan[c.chan].pcm) {
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
chan[c.chan].furnacePCM=true;
|
||||
|
|
@ -690,7 +703,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_X1_010));
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ class DivPlatformX1_010: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -365,9 +365,9 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::tick() {
|
||||
void DivPlatformYM2610::tick(bool sysTick) {
|
||||
// PSG
|
||||
ay->tick();
|
||||
ay->tick(sysTick);
|
||||
ay->flushWrites();
|
||||
for (DivRegWrite& i: ay->getRegisterWrites()) {
|
||||
immWrite(i.addr&15,i.val);
|
||||
|
|
@ -408,6 +408,15 @@ void DivPlatformYM2610::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan=chan[i].std.panL.val&3;
|
||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -626,7 +635,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan>12) { // ADPCM-B
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
chan[c.chan].furnacePCM=true;
|
||||
} else {
|
||||
|
|
@ -709,7 +718,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
immWrite(0x100,0x00|(1<<(c.chan-7)));
|
||||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
chan[c.chan].std.init(ins);
|
||||
if (c.chan<4) {
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
|
|
@ -972,7 +981,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
case DIV_CMD_PRE_PORTA:
|
||||
if (c.chan>3) {
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_FM));
|
||||
}
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -429,9 +429,9 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610B::tick() {
|
||||
void DivPlatformYM2610B::tick(bool sysTick) {
|
||||
// PSG
|
||||
ay->tick();
|
||||
ay->tick(sysTick);
|
||||
ay->flushWrites();
|
||||
for (DivRegWrite& i: ay->getRegisterWrites()) {
|
||||
immWrite(i.addr&15,i.val);
|
||||
|
|
@ -472,6 +472,15 @@ void DivPlatformYM2610B::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.panL.had) {
|
||||
chan[i].pan=chan[i].std.panL.val&3;
|
||||
rWrite(chanOffs[i]+ADDR_LRAF,(isMuted[i]?0:(chan[i].pan<<6))|(chan[i].state.fms&7)|((chan[i].state.ams&3)<<4));
|
||||
}
|
||||
|
||||
if (chan[i].std.pitch.had) {
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].keyOn=true;
|
||||
|
|
@ -689,7 +698,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan>14) { // ADPCM-B
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (ins->type==DIV_INS_AMIGA) {
|
||||
chan[c.chan].furnacePCM=true;
|
||||
} else {
|
||||
|
|
@ -772,7 +781,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
immWrite(0x100,0x00|(1<<(c.chan-9)));
|
||||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
chan[c.chan].std.init(ins);
|
||||
if (c.chan<6) {
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
|
|
@ -1035,7 +1044,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
case DIV_CMD_PRE_PORTA:
|
||||
if (c.chan>5) {
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].std.init(parent->getIns(chan[c.chan].ins,DIV_INS_FM));
|
||||
}
|
||||
}
|
||||
chan[c.chan].inPorta=c.value;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class DivPlatformYM2610B: public DivDispatch {
|
|||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
int ordch=orderedOps[ch];
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
|
||||
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||
|
|
@ -78,7 +78,7 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_VOLUME: {
|
||||
opChan[ch].vol=c.value;
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
|
||||
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||
if (isOpMuted[ch]) {
|
||||
|
|
@ -104,7 +104,7 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
} else {
|
||||
opChan[ch].pan=((c.value&15)>0)|(((c.value>>4)>0)<<1);
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (parent->song.sharedExtStat) {
|
||||
for (int i=0; i<4; i++) {
|
||||
if (ch==i) continue;
|
||||
|
|
@ -159,14 +159,14 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_FM_MULT: { // TODO
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
DivInstrumentFM::Operator op=ins->fm.op[orderedOps[c.value]];
|
||||
rWrite(baseAddr+0x30,(c.value2&15)|(dtTable[op.dt&7]<<4));
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_TL: { // TODO
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (isOutput[ins->fm.alg][c.value]) {
|
||||
rWrite(baseAddr+0x40,127-(((127-c.value2)*(opChan[ch].vol&0x7f))/127));
|
||||
} else {
|
||||
|
|
@ -175,7 +175,7 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AR: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator op=ins->fm.op[i];
|
||||
|
|
@ -212,7 +212,7 @@ static int opChanOffsH[4]={
|
|||
0xad, 0xae, 0xac, 0xa6
|
||||
};
|
||||
|
||||
void DivPlatformYM2610BExt::tick() {
|
||||
void DivPlatformYM2610BExt::tick(bool sysTick) {
|
||||
if (extMode) {
|
||||
bool writeSomething=false;
|
||||
unsigned char writeMask=2;
|
||||
|
|
@ -229,7 +229,7 @@ void DivPlatformYM2610BExt::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
DivPlatformYM2610B::tick();
|
||||
DivPlatformYM2610B::tick(sysTick);
|
||||
|
||||
bool writeNoteOn=false;
|
||||
unsigned char writeMask=2;
|
||||
|
|
@ -268,7 +268,7 @@ void DivPlatformYM2610BExt::muteChannel(int ch, bool mute) {
|
|||
isOpMuted[ch-2]=mute;
|
||||
|
||||
int ordch=orderedOps[ch-2];
|
||||
DivInstrument* ins=parent->getIns(opChan[ch-2].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch-2].ins,DIV_INS_FM);
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
|
||||
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||
if (isOpMuted[ch-2]) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B {
|
|||
void* getChanState(int chan);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsChange(int ins);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
int ordch=orderedOps[ch];
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[ordch];
|
||||
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||
|
|
@ -78,7 +78,7 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_VOLUME: {
|
||||
opChan[ch].vol=c.value;
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[ordch];
|
||||
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||
if (isOpMuted[ch]) {
|
||||
|
|
@ -104,7 +104,7 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
} else {
|
||||
opChan[ch].pan=((c.value&15)>0)|(((c.value>>4)>0)<<1);
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (parent->song.sharedExtStat) {
|
||||
for (int i=0; i<4; i++) {
|
||||
if (ch==i) continue;
|
||||
|
|
@ -159,14 +159,14 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_FM_MULT: { // TODO
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
DivInstrumentFM::Operator op=ins->fm.op[orderedOps[c.value]];
|
||||
rWrite(baseAddr+0x30,(c.value2&15)|(dtTable[op.dt&7]<<4));
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_TL: { // TODO
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (isOutput[ins->fm.alg][c.value]) {
|
||||
rWrite(baseAddr+0x40,127-(((127-c.value2)*(opChan[ch].vol&0x7f))/127));
|
||||
} else {
|
||||
|
|
@ -175,7 +175,7 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AR: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator op=ins->fm.op[i];
|
||||
|
|
@ -212,7 +212,7 @@ static int opChanOffsH[4]={
|
|||
0xad, 0xae, 0xac, 0xa6
|
||||
};
|
||||
|
||||
void DivPlatformYM2610Ext::tick() {
|
||||
void DivPlatformYM2610Ext::tick(bool sysTick) {
|
||||
if (extMode) {
|
||||
bool writeSomething=false;
|
||||
unsigned char writeMask=2;
|
||||
|
|
@ -229,7 +229,7 @@ void DivPlatformYM2610Ext::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
DivPlatformYM2610::tick();
|
||||
DivPlatformYM2610::tick(sysTick);
|
||||
|
||||
bool writeNoteOn=false;
|
||||
unsigned char writeMask=2;
|
||||
|
|
@ -268,7 +268,7 @@ void DivPlatformYM2610Ext::muteChannel(int ch, bool mute) {
|
|||
isOpMuted[ch-1]=mute;
|
||||
|
||||
int ordch=orderedOps[ch-1];
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins);
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[ordch];
|
||||
DivInstrumentFM::Operator op=ins->fm.op[ordch];
|
||||
if (isOpMuted[ch]) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
|
|||
void* getChanState(int chan);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsChange(int ins);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue