From 7080434ed453c40c3d8b2e5d5897c28202f7d9ad Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 8 Jan 2022 16:03:32 -0500 Subject: [PATCH] this does not compile --- CMakeLists.txt | 1 + src/engine/dispatch.h | 5 +- src/engine/dispatchContainer.cpp | 108 ++++++++++++ src/engine/engine.cpp | 272 +++++++++++++------------------ src/engine/engine.h | 51 ++++-- src/engine/playback.cpp | 64 +++++--- src/gui/gui.cpp | 22 +-- src/gui/gui.h | 1 - 8 files changed, 302 insertions(+), 222 deletions(-) create mode 100644 src/engine/dispatchContainer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5edee5da..286b0756 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ src/engine/platform/ym2610Interface.cpp src/engine/blip_buf.c src/engine/safeReader.cpp src/engine/safeWriter.cpp +src/engine/dispatchContainer.cpp src/engine/engine.cpp src/engine/macroInt.cpp src/engine/pattern.cpp diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index b2438aa4..09070e71 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -66,21 +66,24 @@ enum DivDispatchCmds { struct DivCommand { DivDispatchCmds cmd; - unsigned char chan; + unsigned char chan, dis; int value, value2; DivCommand(DivDispatchCmds c, unsigned char ch, int val, int val2): cmd(c), chan(ch), + dis(ch), value(val), value2(val2) {} DivCommand(DivDispatchCmds c, unsigned char ch, int val): cmd(c), chan(ch), + dis(ch), value(val), value2(0) {} DivCommand(DivDispatchCmds c, unsigned char ch): cmd(c), chan(ch), + dis(ch), value(0), value2(0) {} }; diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp new file mode 100644 index 00000000..81db5d72 --- /dev/null +++ b/src/engine/dispatchContainer.cpp @@ -0,0 +1,108 @@ +#include "engine.h" +#include "platform/genesis.h" +#include "platform/genesisext.h" +#include "platform/sms.h" +#include "platform/gb.h" +#include "platform/pce.h" +#include "platform/nes.h" +#include "platform/c64.h" +#include "platform/arcade.h" +#include "platform/ym2610.h" +#include "platform/ym2610ext.h" +#include "platform/dummy.h" +#include "../ta-log.h" + +void DivDispatchContainer::setRates(double gotRate) { + blip_set_rates(bb[0],dispatch->rate,gotRate); + blip_set_rates(bb[1],dispatch->rate,gotRate); +} + +void DivDispatchContainer::clear() { + blip_clear(bb[0]); + blip_clear(bb[1]); + temp[0]=0; + temp[1]=0; + prevSample[0]=0; + prevSample[1]=0; +} + +void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, bool pal) { + if (dispatch!=NULL) return; + + bb[0]=blip_new(32768); + if (bb[0]==NULL) { + logE("not enough memory!\n"); + return; + } + + bb[1]=blip_new(32768); + if (bb[1]==NULL) { + logE("not enough memory!\n"); + return; + } + + bbOut[0]=new short[32768]; + bbOut[1]=new short[32768]; + bbIn[0]=new short[32768]; + bbIn[1]=new short[32768]; + bbInLen=32768; + + switch (sys) { + case DIV_SYSTEM_GENESIS: + dispatch=new DivPlatformGenesis; + break; + case DIV_SYSTEM_GENESIS_EXT: + dispatch=new DivPlatformGenesisExt; + break; + case DIV_SYSTEM_SMS: + dispatch=new DivPlatformSMS; + break; + case DIV_SYSTEM_GB: + dispatch=new DivPlatformGB; + break; + case DIV_SYSTEM_PCE: + dispatch=new DivPlatformPCE; + break; + case DIV_SYSTEM_NES: + dispatch=new DivPlatformNES; + break; + case DIV_SYSTEM_C64_6581: + dispatch=new DivPlatformC64; + ((DivPlatformC64*)dispatch)->setChipModel(true); + break; + case DIV_SYSTEM_C64_8580: + dispatch=new DivPlatformC64; + ((DivPlatformC64*)dispatch)->setChipModel(false); + break; + case DIV_SYSTEM_ARCADE: + dispatch=new DivPlatformArcade; + ((DivPlatformArcade*)dispatch)->setYMFM(true); + break; + case DIV_SYSTEM_YM2610: + dispatch=new DivPlatformYM2610; + break; + case DIV_SYSTEM_YM2610_EXT: + dispatch=new DivPlatformYM2610Ext; + break; + default: + logW("this system is not supported yet! using dummy platform.\n"); + dispatch=new DivPlatformDummy; + break; + } + dispatch->init(eng,chanCount,gotRate,pal); +} + +void DivDispatchContainer::quit() { + if (dispatch==NULL) return; + dispatch->quit(); + delete dispatch; + dispatch=NULL; + + delete[] bbOut[0]; + delete[] bbOut[1]; + delete[] bbIn[0]; + delete[] bbIn[1]; + bbInLen=0; + blip_delete(bb[0]); + blip_delete(bb[1]); +} diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 672033c4..f52549a3 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -13,17 +13,6 @@ #ifdef HAVE_JACK #include "../audio/jack.h" #endif -#include "platform/genesis.h" -#include "platform/genesisext.h" -#include "platform/sms.h" -#include "platform/gb.h" -#include "platform/pce.h" -#include "platform/nes.h" -#include "platform/c64.h" -#include "platform/arcade.h" -#include "platform/ym2610.h" -#include "platform/ym2610ext.h" -#include "platform/dummy.h" #include #include #include @@ -246,117 +235,119 @@ const int chanTypes[11][17]={ }; const char* DivEngine::getChannelName(int chan) { - switch (song.system[0]) { + if (chan<0 || chan>chans) return "??"; + switch (sysOfChan[chan]) { case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanNames[0][chan]; + return chanNames[0][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GENESIS: - return chanNames[1][chan]; + return chanNames[1][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GENESIS_EXT: - return chanNames[2][chan]; + return chanNames[2][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_SMS: - return chanNames[3][chan]; + return chanNames[3][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GB: - return chanNames[4][chan]; + return chanNames[4][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_PCE: - return chanNames[5][chan]; + return chanNames[5][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_NES: - return chanNames[6][chan]; + return chanNames[6][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanNames[7][chan]; + return chanNames[7][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_ARCADE: - return chanNames[8][chan]; + return chanNames[8][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_YM2610: - return chanNames[9][chan]; + return chanNames[9][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_YM2610_EXT: - return chanNames[10][chan]; + return chanNames[10][dispatchChanOfChan[chan]]; break; } return "??"; } const char* DivEngine::getChannelShortName(int chan) { - switch (song.system[0]) { + if (chan<0 || chan>chans) return "??"; + switch (sysOfChan[chan]) { case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanShortNames[0][chan]; + return chanShortNames[0][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GENESIS: - return chanShortNames[1][chan]; + return chanShortNames[1][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GENESIS_EXT: - return chanShortNames[2][chan]; + return chanShortNames[2][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_SMS: - return chanShortNames[3][chan]; + return chanShortNames[3][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GB: - return chanShortNames[4][chan]; + return chanShortNames[4][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_PCE: - return chanShortNames[5][chan]; + return chanShortNames[5][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_NES: - return chanShortNames[6][chan]; + return chanShortNames[6][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanShortNames[7][chan]; + return chanShortNames[7][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_ARCADE: - return chanShortNames[8][chan]; + return chanShortNames[8][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_YM2610: - return chanShortNames[9][chan]; + return chanShortNames[9][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_YM2610_EXT: - return chanShortNames[10][chan]; + return chanShortNames[10][dispatchChanOfChan[chan]]; break; } return "??"; } int DivEngine::getChannelType(int chan) { - switch (song.system[0]) { + switch (sysOfChan[chan]) { case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanTypes[0][chan]; + return chanTypes[0][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GENESIS: - return chanTypes[1][chan]; + return chanTypes[1][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GENESIS_EXT: - return chanTypes[2][chan]; + return chanTypes[2][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_SMS: - return chanTypes[3][chan]; + return chanTypes[3][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_GB: - return chanTypes[4][chan]; + return chanTypes[4][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_PCE: - return chanTypes[5][chan]; + return chanTypes[5][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_NES: - return chanTypes[6][chan]; + return chanTypes[6][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanTypes[7][chan]; + return chanTypes[7][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_ARCADE: - return chanTypes[8][chan]; + return chanTypes[8][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_YM2610: - return chanTypes[9][chan]; + return chanTypes[9][dispatchChanOfChan[chan]]; break; case DIV_SYSTEM_YM2610_EXT: - return chanTypes[10][chan]; + return chanTypes[10][dispatchChanOfChan[chan]]; break; } return 1; @@ -882,7 +873,7 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { isBusy.lock(); song.unload(); song=ds; - chans=getChannelCount(song.system[0]); + recalcChans(); renderSamples(); isBusy.unlock(); if (active) { @@ -1494,7 +1485,7 @@ void DivEngine::createNew() { song.unload(); song=DivSong(); song.system[0]=sys; - chans=getChannelCount(song.system[0]); + recalcChans(); renderSamples(); isBusy.unlock(); initDispatch(); @@ -1503,17 +1494,17 @@ void DivEngine::createNew() { isBusy.unlock(); } -void DivEngine::changeSystem(DivSystem which) { +void DivEngine::changeSystem(int index, DivSystem which) { quitDispatch(); isBusy.lock(); - song.system[0]=which; - chans=getChannelCount(song.system[0]); - // instrument safety check + song.system[index]=which; + recalcChans(); + // instrument safety check (TODO: rewrite for multi-system) for (DivInstrument* i: song.ins) { - if (!isFMSystem(song.system[0]) && i->mode) { + if (!isFMSystem(song.system[index]) && i->mode) { i->mode=false; } - if (!isSTDSystem(song.system[0]) && !i->mode) { + if (!isSTDSystem(song.system[index]) && !i->mode) { i->mode=true; } } @@ -1557,9 +1548,12 @@ void DivEngine::playSub(bool preserveDrift) { int goal=curOrder; curOrder=0; curRow=0; - int prevDrift=clockDrift; - clockDrift=0; - cycles=0; + int prevDrift[32]; + for (int i=0; isetSkipRegisterWrites(true); + for (int i=0; isetSkipRegisterWrites(true); while (curOrdersetSkipRegisterWrites(false); + for (int i=0; isetSkipRegisterWrites(false); if (goal>0) { - dispatch->forceIns(); + for (int i=0; iforceIns(); } repeatPattern=oldRepeatPattern; - if (preserveDrift) { - clockDrift=prevDrift; - } else { - clockDrift=0; + for (int i=0; idispatch(DivCommand(DIV_CMD_GET_VOLMAX,i))<<8)|0xff; + if (idispatch(DivCommand(DIV_CMD_GET_VOLMAX,dispatchChanOfChan[i]))<<8)|0xff; chan[i].volume=chan[i].volMax; } extValue=0; @@ -1621,13 +1632,10 @@ void DivEngine::reset() { speed2=song.speed2; nextSpeed=speed1; globalPitch=0; - blip_clear(bb[0]); - blip_clear(bb[1]); - temp[0]=0; - temp[1]=0; - prevSample[0]=0; - prevSample[1]=0; - dispatch->reset(); + for (int i=0; ireset(); + } } void DivEngine::syncReset() { @@ -1690,9 +1698,9 @@ void DivEngine::previewSample(int sample) { isBusy.unlock(); return; } - blip_clear(bb[2]); - blip_set_rates(bb[2],song.sample[sample]->rate,got.rate); - prevSample[2]=0; + blip_clear(samp_bb); + blip_set_rates(samp_bb,song.sample[sample]->rate,got.rate); + samp_prevSample=0; sPreview.pos=0; sPreview.sample=sample; isBusy.unlock(); @@ -1784,15 +1792,15 @@ void DivEngine::toggleSolo(int chan) { if (!solo) { for (int i=0; imuteChannel(i,isMuted[i]); + if (disCont[dispatchOfChan[i]].dispatch!=NULL) { + disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]); } } } else { for (int i=0; imuteChannel(i,isMuted[i]); + if (disCont[dispatchOfChan[i]].dispatch!=NULL) { + disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]); } } } @@ -1802,8 +1810,8 @@ void DivEngine::toggleSolo(int chan) { void DivEngine::muteChannel(int chan, bool mute) { isBusy.lock(); isMuted[chan]=mute; - if (dispatch!=NULL) { - dispatch->muteChannel(chan,isMuted[chan]); + if (disCont[dispatchOfChan[chan]].dispatch!=NULL) { + disCont[dispatchOfChan[chan]].dispatch->muteChannel(dispatchChanOfChan[chan],isMuted[chan]); } isBusy.unlock(); } @@ -2061,9 +2069,10 @@ void DivEngine::setSongRate(int hz, bool pal) { song.pal=!pal; song.hz=hz; song.customTempo=(song.hz!=50 && song.hz!=60); - dispatch->setPAL((!song.pal) || (song.customTempo!=0 && song.hz<53)); - blip_set_rates(bb[0],dispatch->rate,got.rate); - blip_set_rates(bb[1],dispatch->rate,got.rate); + for (int i=0; isetPAL((!song.pal) || (song.customTempo!=0 && song.hz<53)); + disCont[i].setRates(got.rate); + } isBusy.unlock(); } @@ -2089,74 +2098,30 @@ void DivEngine::setConsoleMode(bool enable) { } void DivEngine::initDispatch() { - if (dispatch!=NULL) return; isBusy.lock(); - switch (song.system[0]) { - case DIV_SYSTEM_GENESIS: - dispatch=new DivPlatformGenesis; - break; - case DIV_SYSTEM_GENESIS_EXT: - dispatch=new DivPlatformGenesisExt; - break; - case DIV_SYSTEM_SMS: - dispatch=new DivPlatformSMS; - break; - case DIV_SYSTEM_GB: - dispatch=new DivPlatformGB; - break; - case DIV_SYSTEM_PCE: - dispatch=new DivPlatformPCE; - break; - case DIV_SYSTEM_NES: - dispatch=new DivPlatformNES; - break; - case DIV_SYSTEM_C64_6581: - dispatch=new DivPlatformC64; - ((DivPlatformC64*)dispatch)->setChipModel(true); - break; - case DIV_SYSTEM_C64_8580: - dispatch=new DivPlatformC64; - ((DivPlatformC64*)dispatch)->setChipModel(false); - break; - case DIV_SYSTEM_ARCADE: - dispatch=new DivPlatformArcade; - ((DivPlatformArcade*)dispatch)->setYMFM(true); - break; - case DIV_SYSTEM_YM2610: - dispatch=new DivPlatformYM2610; - break; - case DIV_SYSTEM_YM2610_EXT: - dispatch=new DivPlatformYM2610Ext; - break; - default: - logW("this system is not supported yet! using dummy platform.\n"); - dispatch=new DivPlatformDummy; - break; + for (int i=0; iinit(this,getChannelCount(song.system[0]),got.rate,(!song.pal) || (song.customTempo!=0 && song.hz<53)); - chans=getChannelCount(song.system[0]); - - blip_set_rates(bb[0],dispatch->rate,got.rate); - blip_set_rates(bb[1],dispatch->rate,got.rate); + recalcChans(); isBusy.unlock(); } void DivEngine::quitDispatch() { - if (dispatch==NULL) return; isBusy.lock(); - dispatch->quit(); - delete dispatch; - dispatch=NULL; + for (int i=0; i conf; std::queue pendingNotes; bool isMuted[DIV_MAX_CHANS]; + DivSystem sysOfChan[DIV_MAX_CHANS]; + int dispatchOfChan[DIV_MAX_CHANS]; + int dispatchChanOfChan[DIV_MAX_CHANS]; std::mutex isBusy; String configPath; String configFile; @@ -131,11 +151,11 @@ class DivEngine { short vibTable[64]; - blip_buffer_t* bb[3]; - size_t bbInLen; - int temp[3], prevSample[3]; - short* bbIn[3]; - short* bbOut[3]; + blip_buffer_t* samp_bb; + size_t samp_bbInLen; + int samp_temp, samp_prevSample; + short* samp_bbIn; + short* samp_bbOut; unsigned char* metroTick; size_t metroTickLen; float metroFreq, metroPos; @@ -153,6 +173,7 @@ class DivEngine { bool nextTick(bool noAccum=false); bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal); bool perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal); + void recalcChans(); void renderSamples(); void reset(); void playSub(bool preserveDrift); @@ -376,7 +397,13 @@ class DivEngine { void renderSamplesP(); // change system - void changeSystem(DivSystem which); + void changeSystem(int index, DivSystem which); + + // add system + void addSystem(DivSystem which); + + // remove system + void removeSystem(int index); // get last error String getLastError(); @@ -407,12 +434,10 @@ class DivEngine { repeatPattern(false), metronome(false), ticks(0), - cycles(0), curRow(0), curOrder(0), remainingLoops(-1), nextSpeed(3), - clockDrift(0), changeOrd(-1), changePos(0), totalTicks(0), @@ -424,9 +449,9 @@ class DivEngine { speed2(3), view(DIV_STATUS_NOTHING), audioEngine(DIV_AUDIO_SDL), - bbInLen(0), - temp{0,0}, - prevSample{0,0}, + samp_bbInLen(0), + samp_temp(0), + samp_prevSample(0), metroTick(NULL), metroTickLen(0), metroFreq(0), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index ffa185eb..9374e373 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -90,11 +90,12 @@ int DivEngine::dispatchCmd(DivCommand c) { printf("%8d | %d: %s(%d, %d)\n",totalTicks,c.chan,cmdName[c.cmd],c.value,c.value2); } totalCmds++; - return dispatch->dispatch(c); + c.chan=dispatchChanOfChan[c.dis]; + return disCont[dispatchOfChan[c.dis]].dispatch->dispatch(c); } bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effectVal) { - switch (song.system[0]) { + switch (sysOfChan[ch]) { case DIV_SYSTEM_GENESIS: case DIV_SYSTEM_GENESIS_EXT: switch (effect) { @@ -172,7 +173,7 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe } bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal) { - switch (song.system[0]) { + switch (sysOfChan[ch]) { case DIV_SYSTEM_GENESIS: case DIV_SYSTEM_GENESIS_EXT: case DIV_SYSTEM_ARCADE: @@ -180,7 +181,7 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char case DIV_SYSTEM_YM2610_EXT: switch (effect) { case 0x10: // LFO or noise mode - if (song.system[0]==DIV_SYSTEM_ARCADE) { + if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) { dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal)); } else { dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal)); @@ -207,12 +208,12 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char } break; case 0x17: // arcade LFO - if (song.system[0]==DIV_SYSTEM_ARCADE) { + if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) { dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal)); } break; case 0x18: // EXT or LFO waveform - if (song.system[0]==DIV_SYSTEM_ARCADE) { + if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) { dispatchCmd(DivCommand(DIV_CMD_FM_LFO_WAVE,ch,effectVal)); } else { dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal)); @@ -234,29 +235,29 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&31)); break; case 0x20: // PCM frequency or Neo Geo PSG mode - if (song.system[0]==DIV_SYSTEM_ARCADE) { + if (sysOfChan[ch]==DIV_SYSTEM_ARCADE) { dispatchCmd(DivCommand(DIV_CMD_SAMPLE_FREQ,ch,effectVal)); - } else if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) { + } else if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal)); } break; case 0x21: // Neo Geo PSG noise freq - if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) { + if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal)); } break; case 0x22: // UNOFFICIAL: Neo Geo PSG envelope enable - if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) { + if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SET,ch,effectVal)); } break; case 0x23: // UNOFFICIAL: Neo Geo PSG envelope period low - if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) { + if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_LOW,ch,effectVal)); } break; case 0x24: // UNOFFICIAL: Neo Geo PSG envelope period high - if (song.system[0]==DIV_SYSTEM_YM2610 || song.system[0]==DIV_SYSTEM_YM2610_EXT) { + if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_HIGH,ch,effectVal)); } break; @@ -322,7 +323,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].delayOrder=whatOrder; chan[i].delayRow=whatRow; if (effectVal==nextSpeed) { - if (song.system[0]!=DIV_SYSTEM_YM2610 && song.system[0]!=DIV_SYSTEM_YM2610_EXT) chan[i].delayLocked=true; + if (sysOfChan[i]!=DIV_SYSTEM_YM2610 && sysOfChan[i]!=DIV_SYSTEM_YM2610_EXT) chan[i].delayLocked=true; } else { chan[i].delayLocked=false; } @@ -348,10 +349,10 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].portaSpeed=-1; chan[i].stopOnOff=false; } - if (dispatch->keyOffAffectsPorta(i)) { + if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsPorta(dispatchChanOfChan[i])) { chan[i].portaNote=-1; chan[i].portaSpeed=-1; - if (i==2 && song.system[0]==DIV_SYSTEM_SMS) { + if (i==2 && sysOfChan[i]==DIV_SYSTEM_SMS) { chan[i+1].portaNote=-1; chan[i+1].portaSpeed=-1; } @@ -361,7 +362,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].oldNote=chan[i].note; chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12; if (!chan[i].keyOn) { - if (dispatch->keyOffAffectsArp(i)) { + if (disCont[dispatchOfChan[i]].dispatch->keyOffAffectsArp(dispatchChanOfChan[i])) { chan[i].arp=0; } } @@ -428,7 +429,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].portaSpeed=-1; chan[i].inPorta=false; } else { - chan[i].portaNote=dispatch->getPortaFloor(i); + chan[i].portaNote=disCont[dispatchOfChan[i]].dispatch->getPortaFloor(dispatchChanOfChan[i]); chan[i].portaSpeed=effectVal; chan[i].portaStop=true; chan[i].nowYouCanStop=false; @@ -507,7 +508,7 @@ void DivEngine::processRow(int i, bool afterDelay) { break; case 0xe5: // pitch chan[i].pitch=effectVal-0x80; - if (song.system[0]==DIV_SYSTEM_ARCADE) { // arcade pitch oddity + if (sysOfChan[i]==DIV_SYSTEM_ARCADE) { // arcade pitch oddity chan[i].pitch*=2; if (chan[i].pitch<-128) chan[i].pitch=-128; if (chan[i].pitch>127) chan[i].pitch=127; @@ -708,11 +709,15 @@ bool DivEngine::nextTick(bool noAccum) { divider=50; } } - cycles=dispatch->rate/divider; - clockDrift+=dispatch->rate%divider; - if (clockDrift>=divider) { - clockDrift-=divider; - cycles++; + + for (int i=0; irate/divider; + dc.clockDrift+=dc.dispatch->rate%divider; + if (dc.clockDrift>=divider) { + dc.clockDrift-=divider; + dc.cycles++; + } } while (!pendingNotes.empty()) { @@ -813,7 +818,7 @@ bool DivEngine::nextTick(bool noAccum) { } // system tick - dispatch->tick(); + for (int i=0; itick(); if (!freelance) { if (!noAccum) totalTicks++; @@ -837,6 +842,13 @@ bool DivEngine::nextTick(bool noAccum) { return ret; } +// TODO: all of this! +// PLAYBACK LOGIC: +// 1. end of buffer for all chips? if so quit +// 2. are all chips clocked yet? +// if not clock them until possible and try again +// 3. engine tick + void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) { if (out!=NULL) { memset(out[0],0,size*sizeof(float)); @@ -869,10 +881,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi } } - if (!playing || dispatch==NULL) { + if (!playing) { isBusy.unlock(); return; } + + // logic starts here size_t runtotal=blip_clocks_needed(bb[0],size); if (runtotal>bbInLen) { diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index f66a337d..8cfa20b7 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1713,9 +1713,6 @@ void FurnaceGUI::editAdvance() { void FurnaceGUI::prepareUndo(ActionType action) { int order=e->getOrder(); switch (action) { - case GUI_ACTION_CHANGE_SYSTEM: - oldSystem=e->song.system[0]; - break; case GUI_ACTION_CHANGE_ORDER: oldOrders=e->song.orders; oldOrdersLen=e->song.ordersLen; @@ -1744,13 +1741,6 @@ void FurnaceGUI::makeUndo(ActionType action) { s.order=order; s.nibble=curNibble; switch (action) { - case GUI_ACTION_CHANGE_SYSTEM: - if (oldSystem!=e->song.system[0]) { - s.oldSystem=oldSystem; - s.newSystem=e->song.system[0]; - doPush=true; - } - break; case GUI_ACTION_CHANGE_ORDER: for (int i=0; i<32; i++) { for (int j=0; j<128; j++) { @@ -2085,10 +2075,6 @@ void FurnaceGUI::doUndo() { modified=true; switch (us.type) { - case GUI_ACTION_CHANGE_SYSTEM: - e->changeSystem(us.oldSystem); - updateWindowTitle(); - break; case GUI_ACTION_CHANGE_ORDER: e->song.ordersLen=us.oldOrdersLen; for (UndoOrderData& i: us.ord) { @@ -2126,10 +2112,6 @@ void FurnaceGUI::doRedo() { modified=true; switch (us.type) { - case GUI_ACTION_CHANGE_SYSTEM: - e->changeSystem(us.newSystem); - updateWindowTitle(); - break; case GUI_ACTION_CHANGE_ORDER: e->song.ordersLen=us.newOrdersLen; for (UndoOrderData& i: us.ord) { @@ -2575,10 +2557,8 @@ void FurnaceGUI::processDrags(int dragX, int dragY) { #define sysChangeOption(x) \ if (ImGui::MenuItem(e->getSystemName(x),NULL,e->song.system[0]==x)) { \ - prepareUndo(GUI_ACTION_CHANGE_SYSTEM); \ - e->changeSystem(x); \ + e->changeSystem(0,x); \ updateWindowTitle(); \ - makeUndo(GUI_ACTION_CHANGE_SYSTEM); \ } bool FurnaceGUI::loop() { diff --git a/src/gui/gui.h b/src/gui/gui.h index c1cfb5af..90b45687 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -87,7 +87,6 @@ struct SelectionPoint { }; enum ActionType { - GUI_ACTION_CHANGE_SYSTEM, GUI_ACTION_CHANGE_ORDER, GUI_ACTION_PATTERN_EDIT, GUI_ACTION_PATTERN_DELETE,