diff --git a/TODO.md b/TODO.md index 3b354a90..7de18ef0 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ # to-do for 0.6pre1 -- MSM6258 pitch and clock select - rewrite the system name detection function anyway - add another FM editor layout - if macros have release, note off should release them diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index 9bcb7966..a144959e 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -31,51 +31,68 @@ const char** DivPlatformMSM6258::getRegisterSheet() { } const char* DivPlatformMSM6258::getEffectName(unsigned char effect) { + switch (effect) { + case 0x20: + return "20xx: Set frequency divider (0-2)"; + break; + case 0x21: + return "21xx: Select clock rate (0: full; 1: half)"; + break; + } return NULL; } void DivPlatformMSM6258::acquire(short* bufL, short* bufR, size_t start, size_t len) { + short* outs[2]={ + &msmOut, + NULL + }; for (size_t h=start; hctrl_w(w.val); - break; - case 2: - msmPan=w.val; - break; - case 8: - msmClock=w.val; - break; - case 12: - msmDivider=4-(w.val&3); - if (msmDivider<2) msmDivider=2; - break; - } - writes.pop(); - } - - if (sample>=0 && samplesong.sampleLen) { - DivSample* s=parent->getSample(sample); - unsigned char nextData=(s->dataVOX[samplePos]>>4)|(s->dataVOX[samplePos]<<4); - if (msm->data_w(nextData)) { - samplePos++; - if (samplePos>=(int)s->lengthVOX) { - sample=-1; - samplePos=0; - msm->ctrl_w(1); + if (--msmClockCount<0) { + if (--msmDividerCount<=0) { + if (!writes.empty()) { + QueuedWrite& w=writes.front(); + switch (w.addr) { + case 0: + msm->ctrl_w(w.val); + break; + case 2: + msmPan=w.val; + break; + case 8: + msmClock=w.val; + break; + case 12: + msmDivider=4-(w.val&3); + if (msmDivider<2) msmDivider=2; + break; + } + writes.pop(); } + + if (sample>=0 && samplesong.sampleLen) { + DivSample* s=parent->getSample(sample); + unsigned char nextData=(s->dataVOX[samplePos]>>4)|(s->dataVOX[samplePos]<<4); + if (msm->data_w(nextData)) { + samplePos++; + if (samplePos>=(int)s->lengthVOX) { + sample=-1; + samplePos=0; + msm->ctrl_w(1); + } + } + } + + msm->sound_stream_update(outs,1); + msmDividerCount=msmDivider; } + msmClockCount=msmClock; } - msm->sound_stream_update(outs,1); if (isMuted[0]) { bufL[h]=0; + } else { + bufL[h]=msmOut; } /*if (++updateOsc>=22) { @@ -186,6 +203,14 @@ int DivPlatformMSM6258::dispatch(DivCommand c) { sampleBank=parent->song.sample.size()/12; } break; + case DIV_CMD_SAMPLE_FREQ: + rateSel=c.value&3; + rWrite(12,rateSel); + break; + case DIV_CMD_SAMPLE_MODE: + clockSel=c.value&1; + rWrite(8,clockSel); + break; case DIV_CMD_LEGATO: { break; } @@ -215,6 +240,8 @@ void DivPlatformMSM6258::forceIns() { for (int i=0; i<1; i++) { chan[i].insChanged=true; } + rWrite(12,rateSel); + rWrite(8,clockSel); } void* DivPlatformMSM6258::getChanState(int ch) { @@ -244,6 +271,14 @@ void DivPlatformMSM6258::poke(std::vector& wlist) { void DivPlatformMSM6258::reset() { while (!writes.empty()) writes.pop(); msm->device_reset(); + msmClock=chipClock; + msmDivider=2; + msmDividerCount=0; + msmClock=0; + msmClockCount=0; + msmPan=3; + rateSel=0; + clockSel=0; if (dumpWrites) { addWrite(0xffffffff,0); } @@ -317,15 +352,24 @@ void DivPlatformMSM6258::renderSamples() { } void DivPlatformMSM6258::setFlags(unsigned int flags) { - if (flags&1) { - chipClock=4096000; - } else { - chipClock=4000000; + switch (flags) { + case 3: + chipClock=8192000; + break; + case 2: + chipClock=8000000; + break; + case 1: + chipClock=4096000; + break; + default: + chipClock=4000000; + break; } - rate=chipClock/256; + rate=chipClock/128; for (int i=0; i<1; i++) { isMuted[i]=false; - oscBuf[i]->rate=rate/256; + oscBuf[i]->rate=rate; } } diff --git a/src/engine/platform/msm6258.h b/src/engine/platform/msm6258.h index 7ef22681..b870eb1c 100644 --- a/src/engine/platform/msm6258.h +++ b/src/engine/platform/msm6258.h @@ -87,9 +87,11 @@ class DivPlatformMSM6258: public DivDispatch { unsigned char* adpcmMem; size_t adpcmMemLen; - unsigned char sampleBank, msmPan, msmDivider; + unsigned char sampleBank, msmPan, msmDivider, rateSel, msmClock, clockSel; + signed char msmDividerCount, msmClockCount; + short msmOut; - int delay, updateOsc, sample, samplePos, msmClock; + int delay, updateOsc, sample, samplePos; bool extMode; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index be2c7236..e5a4888b 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1975,7 +1975,21 @@ void DivEngine::registerSystems() { {"Sample"}, {"PCM"}, {DIV_CH_PCM}, - {DIV_INS_AMIGA} + {DIV_INS_AMIGA}, + {}, + [this](int ch, unsigned char effect, unsigned char effectVal) -> bool { + switch (effect) { + case 0x20: // select rate + dispatchCmd(DivCommand(DIV_CMD_SAMPLE_FREQ,ch,effectVal)); + break; + case 0x21: // select clock + dispatchCmd(DivCommand(DIV_CMD_SAMPLE_MODE,ch,effectVal)); + break; + default: + return false; + } + return true; + } ); sysDefs[DIV_SYSTEM_YMZ280B]=new DivSysDef( diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 91d542bd..89d35b0b 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -415,6 +415,22 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool } break; } + case DIV_SYSTEM_MSM6258: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("4MHz",flags==0)) { + copyOfFlags=0; + } + if (ImGui::RadioButton("4.096MHz",flags==1)) { + copyOfFlags=1; + } + if (ImGui::RadioButton("8MHz (X68000)",flags==2)) { + copyOfFlags=2; + } + if (ImGui::RadioButton("8.192MHz",flags==3)) { + copyOfFlags=3; + } + break; + } case DIV_SYSTEM_MSM6295: { ImGui::Text("Clock rate:"); if (ImGui::RadioButton("1MHz",flags==0)) {