diff --git a/demos/ay8930/AY8930Shuffle.fur b/demos/ay8930/AY8930Shuffle.fur new file mode 100644 index 000000000..68931cf09 Binary files /dev/null and b/demos/ay8930/AY8930Shuffle.fur differ diff --git a/demos/sms/FlowOfSN7.fur b/demos/sms/FlowOfSN7.fur new file mode 100644 index 000000000..643686cc0 Binary files /dev/null and b/demos/sms/FlowOfSN7.fur differ diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index b41a52d5e..5c1521aba 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -64,6 +64,41 @@ const char** DivPlatformC64::getRegisterSheet() { return regCheatSheetSID; } +short DivPlatformC64::runFakeFilter(unsigned char ch, int in) { + if (!(regPool[0x17]&(1<0x5F)?8.0/(float)(regPool[0x17]>>4):1.41): + (pow(2,((float)(4-(float)(regPool[0x17]>>4))/8))) + ); + float tmp=fin+fakeBand[ch]*reso+fakeLow[ch]; + if (regPool[0x18]&0x40) { + fout-=tmp; + } + tmp=fakeBand[ch]-tmp*ctf; + fakeBand[ch]=tmp; + if (regPool[0x18]&0x20) { + fout-=tmp; + } + tmp=fakeLow[ch]+tmp*ctf; + fakeLow[ch]=tmp; + if (regPool[0x18]&0x10) { + fout+=tmp; + } + + fout*=(float)(regPool[0x18]&15)/20.0f; + return CLAMP(fout,-32768,32767); +} + void DivPlatformC64::acquire(short** buf, size_t len) { int dcOff=(sidCore)?0:sid->get_dc(0); for (size_t i=0; iclock(4,&buf[0][i]); if (++writeOscBuf>=4) { writeOscBuf=0; - oscBuf[0]->data[oscBuf[0]->needle++]=(sid_fp->lastChanOut[0]-dcOff)>>5; - oscBuf[1]->data[oscBuf[1]->needle++]=(sid_fp->lastChanOut[1]-dcOff)>>5; - oscBuf[2]->data[oscBuf[2]->needle++]=(sid_fp->lastChanOut[2]-dcOff)>>5; + oscBuf[0]->data[oscBuf[0]->needle++]=runFakeFilter(0,(sid_fp->lastChanOut[0]-dcOff)>>5); + oscBuf[1]->data[oscBuf[1]->needle++]=runFakeFilter(1,(sid_fp->lastChanOut[1]-dcOff)>>5); + oscBuf[2]->data[oscBuf[2]->needle++]=runFakeFilter(2,(sid_fp->lastChanOut[2]-dcOff)>>5); } } else { sid->clock(); buf[0][i]=sid->output(); if (++writeOscBuf>=16) { writeOscBuf=0; - oscBuf[0]->data[oscBuf[0]->needle++]=(sid->last_chan_out[0]-dcOff)>>5; - oscBuf[1]->data[oscBuf[1]->needle++]=(sid->last_chan_out[1]-dcOff)>>5; - oscBuf[2]->data[oscBuf[2]->needle++]=(sid->last_chan_out[2]-dcOff)>>5; + oscBuf[0]->data[oscBuf[0]->needle++]=runFakeFilter(0,(sid->last_chan_out[0]-dcOff)>>5); + oscBuf[1]->data[oscBuf[1]->needle++]=runFakeFilter(1,(sid->last_chan_out[1]-dcOff)>>5); + oscBuf[2]->data[oscBuf[2]->needle++]=runFakeFilter(2,(sid->last_chan_out[2]-dcOff)>>5); } } } @@ -540,6 +575,8 @@ void DivPlatformC64::reset() { for (int i=0; i<3; i++) { chan[i]=DivPlatformC64::Channel(); chan[i].std.setEngine(parent); + fakeLow[i]=0; + fakeBand[i]=0; } if (sidCore==2) { @@ -613,6 +650,24 @@ void DivPlatformC64::setFlags(const DivConfig& flags) { keyPriority=flags.getBool("keyPriority",true); testAD=((flags.getInt("testAttack",0)&15)<<4)|(flags.getInt("testDecay",0)&15); testSR=((flags.getInt("testSustain",0)&15)<<4)|(flags.getInt("testRelease",0)&15); + + // init fake filter table + // taken from dSID + double cutRatio=-2.0*3.14*(sidIs6581?(((double)oscBuf[0]->rate/44100.0)*(20000.0/256.0)):(12500.0/256.0))/(double)oscBuf[0]->rate; + + for (int i=0; i<2048; i++) { + double c=(double)i/8.0+0.2; + if (sidIs6581) { + if (c<24) { + c=2.0*sin(771.78/(double)oscBuf[0]->rate); + } else { + c=(44100.0/(double)oscBuf[0]->rate)-1.263*(44100.0/(double)oscBuf[0]->rate)*exp(c*cutRatio); + } + } else { + c=1-exp(c*cutRatio); + } + fakeCutTable[i]=c; + } } int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { diff --git a/src/engine/platform/c64.h b/src/engine/platform/c64.h index 26b39c804..5f67b956a 100644 --- a/src/engine/platform/c64.h +++ b/src/engine/platform/c64.h @@ -56,6 +56,9 @@ class DivPlatformC64: public DivDispatch { Channel chan[3]; DivDispatchOscBuffer* oscBuf[3]; bool isMuted[3]; + float fakeLow[3]; + float fakeBand[3]; + float fakeCutTable[2048]; struct QueuedWrite { unsigned char addr; unsigned char val; @@ -80,6 +83,8 @@ class DivPlatformC64: public DivDispatch { friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); + inline short runFakeFilter(unsigned char ch, int in); + void acquire_classic(short* bufL, short* bufR, size_t start, size_t len); void acquire_fp(short* bufL, short* bufR, size_t start, size_t len); diff --git a/src/engine/platform/sound/c64_d/dsid.c b/src/engine/platform/sound/c64_d/dsid.c index d01dc7ad7..2ff2dacf8 100644 --- a/src/engine/platform/sound/c64_d/dsid.c +++ b/src/engine/platform/sound/c64_d/dsid.c @@ -115,11 +115,17 @@ void dSID_init(struct SID_chip* sid, double clockRate, double samplingRate, int double prd0 = sid->g.ckr > 9 ? sid->g.ckr : 9; sid->g.Aprd[0] = prd0; sid->g.Astp[0] = ceil(prd0 / 9); + + for (int i=0; i<3; i++) { + sid->fakeplp[i]=0; + sid->fakepbp[i]=0; + } } double dSID_render(struct SID_chip* sid) { double flin = 0, output = 0; double wfout = 0; + double step = 0; for (int chn = 0; chn < 3; chn++) { struct SIDVOICE *voic = &((struct SIDMEM *) (sid->M))->v[chn]; double pgt = (sid->SIDct->ch[chn].Ast & GAT); @@ -142,7 +148,6 @@ double dSID_render(struct SID_chip* sid) { if (sid->SIDct->ch[chn].rcnt >= 0x8000) sid->SIDct->ch[chn].rcnt -= 0x8000; - static double step; double prd; if (sid->SIDct->ch[chn].Ast & ATK) { @@ -291,8 +296,6 @@ double dSID_render(struct SID_chip* sid) { // mostly copypasted from below double fakeflin = chnout; double fakeflout = 0; - static double fakeplp[3] = {0}; - static double fakepbp[3] = {0}; double ctf = sid->g.ctf_table[((sid->M[0x15]&7)|(sid->M[0x16]<<3))&0x7ff]; double reso; if (sid->g.model == 8580) { @@ -300,15 +303,15 @@ double dSID_render(struct SID_chip* sid) { } else { reso = (sid->M[0x17] > 0x5F) ? 8.0 / (double) (sid->M[0x17] >> 4) : 1.41; } - double tmp = fakeflin + fakepbp[chn] * reso + fakeplp[chn]; + double tmp = fakeflin + sid->fakepbp[chn] * reso + sid->fakeplp[chn]; if (sid->M[0x18] & HP) fakeflout -= tmp; - tmp = fakepbp[chn] - tmp * ctf; - fakepbp[chn] = tmp; + tmp = sid->fakepbp[chn] - tmp * ctf; + sid->fakepbp[chn] = tmp; if (sid->M[0x18] & BP) fakeflout -= tmp; - tmp = fakeplp[chn] + tmp * ctf; - fakeplp[chn] = tmp; + tmp = sid->fakeplp[chn] + tmp * ctf; + sid->fakeplp[chn] = tmp; if (sid->M[0x18] & LP) fakeflout += tmp; diff --git a/src/engine/platform/sound/c64_d/dsid.h b/src/engine/platform/sound/c64_d/dsid.h index b02d1870e..b17a51f55 100644 --- a/src/engine/platform/sound/c64_d/dsid.h +++ b/src/engine/platform/sound/c64_d/dsid.h @@ -81,6 +81,8 @@ struct SID_chip { uint8_t M[MemLen]; int16_t lastOut[3]; int mute_mask; + double fakeplp[3]; + double fakepbp[3]; }; double dSID_render(struct SID_chip* sid); diff --git a/src/engine/platform/sound/c64_fp/SID.cpp b/src/engine/platform/sound/c64_fp/SID.cpp index a996d2230..03c778c90 100644 --- a/src/engine/platform/sound/c64_fp/SID.cpp +++ b/src/engine/platform/sound/c64_fp/SID.cpp @@ -351,7 +351,7 @@ void SID::write(int offset, unsigned char value) break; case 0x04: // Voice #1 control register - voice[0]->writeCONTROL_REG(muted[0] ? 0 : value); + voice[0]->writeCONTROL_REG(value); break; case 0x05: // Voice #1 Attack and Decay length @@ -379,7 +379,7 @@ void SID::write(int offset, unsigned char value) break; case 0x0b: // Voice #2 control register - voice[1]->writeCONTROL_REG(muted[1] ? 0 : value); + voice[1]->writeCONTROL_REG(value); break; case 0x0c: // Voice #2 Attack and Decay length @@ -407,7 +407,7 @@ void SID::write(int offset, unsigned char value) break; case 0x12: // Voice #3 control register - voice[2]->writeCONTROL_REG(muted[2] ? 0 : value); + voice[2]->writeCONTROL_REG(value); break; case 0x13: // Voice #3 Attack and Decay length diff --git a/src/engine/platform/sound/c64_fp/SID.h b/src/engine/platform/sound/c64_fp/SID.h index 85b6a4e4d..77d7706d4 100644 --- a/src/engine/platform/sound/c64_fp/SID.h +++ b/src/engine/platform/sound/c64_fp/SID.h @@ -320,11 +320,11 @@ int SID::output() const int v2 = voice[1]->output(voice[0]->wave()); const int v3 = voice[2]->output(voice[1]->wave()); - lastChanOut[0]=v1; - lastChanOut[1]=v2; - lastChanOut[2]=v3; + lastChanOut[0]=muted[0]?0:v1; + lastChanOut[1]=muted[1]?0:v2; + lastChanOut[2]=muted[2]?0:v3; - return externalFilter->clock(filter->clock(v1, v2, v3)); + return externalFilter->clock(filter->clock(muted[0]?0:v1, muted[1]?0:v2, muted[2]?0:v3)); } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 6eefb6913..6437ecab7 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -5252,7 +5252,7 @@ bool FurnaceGUI::loop() { quit=true; } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } break; @@ -5276,7 +5276,7 @@ bool FurnaceGUI::loop() { displayNew=true; } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } break; @@ -5300,7 +5300,7 @@ bool FurnaceGUI::loop() { openFileDialog(GUI_FILE_OPEN); } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } break; @@ -5324,7 +5324,7 @@ bool FurnaceGUI::loop() { openFileDialog(GUI_FILE_OPEN_BACKUP); } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } break; @@ -5355,7 +5355,7 @@ bool FurnaceGUI::loop() { nextFile=""; } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); nextFile=""; } @@ -5409,7 +5409,7 @@ bool FurnaceGUI::loop() { syncSettings(); } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } break; @@ -5496,7 +5496,7 @@ bool FurnaceGUI::loop() { ImGui::CloseCurrentPopup(); } - if (ImGui::Button("Wait! What am I doing? Cancel!")) { + if (ImGui::Button("Wait! What am I doing? Cancel!") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } break; @@ -5647,7 +5647,7 @@ bool FurnaceGUI::loop() { ImGui::EndDisabled(); ImGui::SameLine(); } - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { for (std::pair& i: pendingIns) { i.second=false; } @@ -5719,7 +5719,7 @@ bool FurnaceGUI::loop() { ImGui::CloseCurrentPopup(); } ImGui::SameLine(); - if (ImGui::Button("Cancel")) { + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); @@ -5849,13 +5849,12 @@ bool FurnaceGUI::loop() { if (outFile!=NULL) { if (fwrite(w->getFinalBuf(),1,w->size(),outFile)!=w->size()) { logW("did not write backup entirely: %s!",strerror(errno)); - w->finish(); } fclose(outFile); } else { logW("could not save backup: %s!",strerror(errno)); - w->finish(); } + w->finish(); // delete previous backup if there are too many delFirstBackup(backupBaseName);