diff --git a/src/engine/platform/zxbeeperquadtone.cpp b/src/engine/platform/zxbeeperquadtone.cpp index e9c9e5d68..66e1ee007 100644 --- a/src/engine/platform/zxbeeperquadtone.cpp +++ b/src/engine/platform/zxbeeperquadtone.cpp @@ -30,13 +30,14 @@ const char** DivPlatformZXBeeperQuadTone::getRegisterSheet() { } void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) { - bool o=false; for (size_t h=0; h=0 && curSamplesong.sampleLen && !isMuted[4]) { + bool sampleActive=false; + if (curSample>=0 && curSamplesong.sampleLen) { + sampleActive=!isMuted[4]; while (curSamplePeriod>=chan[4].freq) { DivSample* s=parent->getSample(curSample); if (s->samples>0) { - if (!isMuted[4]) o=(s->data8[curSamplePos++]>0); + chan[4].out=(s->data8[curSamplePos++]>0); if (curSamplePos>=s->samples) curSample=-1; // (theoretical) 32KiB limit if (curSamplePos>=32768*8) curSample=-1; @@ -46,46 +47,47 @@ void DivPlatformZXBeeperQuadTone::acquire(short** buf, size_t len) { curSamplePeriod-=chan[4].freq; } curSamplePeriod+=40; - if ((outputClock&3)==0) { + } + if (sampleActive) { + buf[0][h]=chan[4].out?32767:0; + if (outputClock==0) { oscBuf[0]->data[oscBuf[0]->needle++]=0; oscBuf[1]->data[oscBuf[1]->needle++]=0; oscBuf[2]->data[oscBuf[2]->needle++]=0; oscBuf[3]->data[oscBuf[3]->needle++]=0; - oscBuf[4]->data[oscBuf[4]->needle++]=o?32767:0; } + oscBuf[4]->data[oscBuf[4]->needle++]=buf[0][h]; } else { int ch=outputClock/2; int b=ch*4; + bool o=false; if ((outputClock&1)==0) { + short oscOut; chan[ch].sPosition+=(regPool[1+b]<<8)|regPool[0+b]; chan[ch].out=regPool[3+b]+((((chan[ch].sPosition>>8)&0xff)data[oscBuf[4]->needle++]=0; - } - o=chan[ch].out&0x10; - oscBuf[ch]->data[oscBuf[ch]->needle++]=o?32767:0; - chan[ch].out<<=1; - - // if muted, ztill run sample - if (curSample>=0 && curSamplesong.sampleLen && isMuted[4]) { - while (curSamplePeriod>=chan[4].freq) { - DivSample* s=parent->getSample(curSample); - if (s->samples>0) { - if (curSamplePos>=s->samples) curSample=-1; - // (theoretical) 32KiB limit - if (curSamplePos>=32768*8) curSample=-1; - } else { - curSample=-1; - } - curSamplePeriod-=chan[4].freq; + if (isMuted[ch] || ((chan[ch].out&0x18)==0)) { + oscOut=0; + } else if ((chan[ch].out&0x18)==0x18) { + oscOut=32767; + } else { + oscOut=16383; } - curSamplePeriod+=40; + oscBuf[ch]->data[oscBuf[ch]->needle++]=oscOut; } + if (!isMuted[ch]) o=chan[ch].out&0x10; + if (noHiss) { + deHisser[outputClock]=o; + buf[0][h]=-1; + for (int i=0; i<8; i++) { + buf[0][h]+=deHisser[i]?4096:0; + } + } else { + buf[0][h]=o?32767:0; + } + chan[ch].out<<=1; + oscBuf[4]->data[oscBuf[4]->needle++]=0; } outputClock=(outputClock+1)&7; - buf[0][h]=o?32767:0; } } @@ -157,6 +159,7 @@ void DivPlatformZXBeeperQuadTone::tick(bool sysTick) { chan[4].freq=parent->calcFreq(chan[4].baseFreq,chan[4].pitch,chan[4].fixedArp?chan[4].baseNoteOverride:chan[4].arpOff,chan[4].fixedArp,true,2,chan[4].pitch2,chipClock,off); if (chan[4].freq>258) chan[4].freq=258; if (chan[4].freq<3) chan[4].freq=3; + rWrite(16,(chan[4].freq-2)&255); chan[4].freq*=13; } if (chan[4].keyOn) chan[4].keyOn=false; @@ -340,11 +343,12 @@ unsigned char* DivPlatformZXBeeperQuadTone::getRegisterPool() { } int DivPlatformZXBeeperQuadTone::getRegisterPoolSize() { - return 16; + return 17; } void DivPlatformZXBeeperQuadTone::reset() { - memset(regPool,0,16); + memset(regPool,0,17); + memset(deHisser,0,8); for (int i=0; i<5; i++) { chan[i]=DivPlatformZXBeeperQuadTone::Channel(); chan[i].std.setEngine(parent); @@ -353,7 +357,6 @@ void DivPlatformZXBeeperQuadTone::reset() { cycles=0; curChan=0; sOffTimer=0; - ulaOut=0; curSample=-1; curSamplePos=0; curSamplePeriod=0; @@ -381,9 +384,11 @@ void DivPlatformZXBeeperQuadTone::setFlags(const DivConfig& flags) { } CHECK_CUSTOM_CLOCK; rate=chipClock/40; + noHiss=flags.getBool("noHiss",false); for (int i=0; i<4; i++) { - oscBuf[i]->rate=rate/4; + oscBuf[i]->rate=rate/8; } + oscBuf[4]->rate=rate; } void DivPlatformZXBeeperQuadTone::poke(unsigned int addr, unsigned short val) { diff --git a/src/engine/platform/zxbeeperquadtone.h b/src/engine/platform/zxbeeperquadtone.h index 4efd66c07..f4fdda058 100644 --- a/src/engine/platform/zxbeeperquadtone.h +++ b/src/engine/platform/zxbeeperquadtone.h @@ -36,12 +36,13 @@ class DivPlatformZXBeeperQuadTone: public DivDispatch { Channel chan[5]; DivDispatchOscBuffer* oscBuf[5]; bool isMuted[5]; - unsigned char ulaOut; + bool noHiss; + bool deHisser[8]; int cycles, curChan, sOffTimer, delay, curSample, curSamplePeriod; unsigned int curSamplePos; unsigned int outputClock; - unsigned char regPool[16]; + unsigned char regPool[17]; friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index efa453c3c..86b478ca8 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -2270,6 +2270,23 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl } break; } + case DIV_SYSTEM_SFX_BEEPER_QUADTONE: { + bool sysPal=flags.getInt("clockSel",0); + bool noHiss=flags.getBool("noHiss",false); + if (ImGui::Checkbox("PAL",&sysPal)) { + altered=true; + } + if (ImGui::Checkbox("Disable hissing",&noHiss)) { + altered=true; + } + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",(int)sysPal); + flags.set("noHiss",noHiss); + }); + } + break; + } case DIV_SYSTEM_SWAN: case DIV_SYSTEM_BUBSYS_WSG: case DIV_SYSTEM_PET: