From ccfe3bdd976b643b0041ae3b2e3252c3b208c23e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 2 Feb 2022 23:08:45 -0500 Subject: [PATCH] Genesis: add ability to use ymfm instead of Nuked --- src/engine/dispatchContainer.cpp | 2 + src/engine/engine.cpp | 2 + src/engine/platform/genesis.cpp | 104 ++++++++++++++++++++++++++++++- src/engine/platform/genesis.h | 15 ++++- src/gui/gui.cpp | 11 ++++ src/gui/gui.h | 2 + 6 files changed, 133 insertions(+), 3 deletions(-) diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index 90f286385..f7f22973e 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -113,9 +113,11 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do case DIV_SYSTEM_GENESIS: case DIV_SYSTEM_YM2612: dispatch=new DivPlatformGenesis; + ((DivPlatformGenesis*)dispatch)->setYMFM(eng->getConfInt("ym2612Core",0)); break; case DIV_SYSTEM_GENESIS_EXT: dispatch=new DivPlatformGenesisExt; + ((DivPlatformGenesisExt*)dispatch)->setYMFM(eng->getConfInt("ym2612Core",0)); break; case DIV_SYSTEM_SMS: dispatch=new DivPlatformSMS; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index bbb113b19..7781aa237 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -5835,6 +5835,8 @@ void DivEngine::setConsoleMode(bool enable) { void DivEngine::switchMaster() { deinitAudioBackend(); + quitDispatch(); + initDispatch(); if (initAudioBackend()) { for (int i=0; isong.sample[dacSample]; + if (s->rendLength>0) { + if (!isMuted[5]) { + if (s->depth==8) { + immWrite(0x2a,(unsigned char)s->rendData[dacPos]+0x80); + } else { + immWrite(0x2a,((unsigned short)s->rendData[dacPos]+0x8000)>>8); + } + } + if (++dacPos>=s->rendLength) { + if (s->loopStart>=0 && s->loopStart<=(int)s->rendLength) { + dacPos=s->loopStart; + } else { + dacSample=-1; + } + } + dacPeriod+=MAX(40,dacRate); + } else { + dacSample=-1; + } + } + } + + os[0]=0; os[1]=0; + if (!writes.empty() && !fm_ymfm->read_status()) { + QueuedWrite& w=writes.front(); + if (w.addrOrVal) { + fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val); + //printf("write: %x = %.2x\n",w.addr,w.val); + lastBusy=0; + writes.pop(); + } else { + //printf("busycounter: %d\n",lastBusy); + fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr); + w.addrOrVal=true; + } + } + + if (ladder) { + fm_ymfm->generate(&out_ymfm); + } else { + ((ymfm::ym3438*)fm_ymfm)->generate(&out_ymfm); + } + os[0]=out_ymfm.data[0]; + os[1]=out_ymfm.data[1]; + //OPN2_Write(&fm,0,0); + + psgClocks+=psg.rate; + while (psgClocks>=rate) { + psgOut=(psg.acquireOne()*3)>>3; + psgClocks-=rate; + } + + os[0]=os[0]+psgOut; + if (os[0]<-32768) os[0]=-32768; + if (os[0]>32767) os[0]=32767; + + os[1]=os[1]+psgOut; + if (os[1]<-32768) os[1]=-32768; + if (os[1]>32767) os[1]=32767; + + bufL[h]=os[0]; + bufR[h]=os[1]; + } +} + +void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t len) { + if (useYMFM) { + acquire_ymfm(bufL,bufR,start,len); + } else { + acquire_nuked(bufL,bufR,start,len); + } +} + void DivPlatformGenesis::tick() { for (int i=0; i<6; i++) { if (i==2 && extMode) continue; @@ -616,6 +697,9 @@ void* DivPlatformGenesis::getChanState(int ch) { void DivPlatformGenesis::reset() { while (!writes.empty()) writes.pop(); + if (useYMFM) { + fm_ymfm->reset(); + } OPN2_Reset(&fm); OPN2_SetChipType(ladder?ym3438_mode_ym2612:0); if (dumpWrites) { @@ -693,6 +777,10 @@ int DivPlatformGenesis::getPortaFloor(int ch) { return (ch>5)?12:0; } +void DivPlatformGenesis::setYMFM(bool use) { + useYMFM=use; +} + void DivPlatformGenesis::setFlags(unsigned int flags) { if (flags==2) { chipClock=8000000.0; @@ -702,9 +790,19 @@ void DivPlatformGenesis::setFlags(unsigned int flags) { chipClock=COLOR_NTSC*15.0/7.0; } psg.setFlags(flags==1); - rate=chipClock/36; ladder=flags&0x80000000; OPN2_SetChipType(ladder?ym3438_mode_ym2612:0); + if (useYMFM) { + if (fm_ymfm!=NULL) delete fm_ymfm; + if (ladder) { + fm_ymfm=new ymfm::ym2612(iface); + } else { + fm_ymfm=new ymfm::ym3438(iface); + } + rate=chipClock/144; + } else { + rate=chipClock/36; + } } int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { @@ -715,6 +813,7 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned i for (int i=0; i<10; i++) { isMuted[i]=false; } + fm_ymfm=NULL; psg.init(p,4,sugRate,flags==1); setFlags(flags); @@ -723,6 +822,7 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned i } void DivPlatformGenesis::quit() { + if (fm_ymfm!=NULL) delete fm_ymfm; psg.quit(); } diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 7a3f6124c..f187d4a91 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -3,9 +3,14 @@ #include "../dispatch.h" #include #include "../../../extern/Nuked-OPN2/ym3438.h" +#include "sound/ymfm/ymfm_opn.h" #include "sms.h" +class DivYM2612Interface: public ymfm::ymfm_interface { + +}; + class DivPlatformGenesis: public DivDispatch { protected: struct Channel { @@ -51,6 +56,10 @@ class DivPlatformGenesis: public DivDispatch { int psgOut; int delay; unsigned char lastBusy; + + ymfm::ym2612* fm_ymfm; + ymfm::ym2612::output_data out_ymfm; + DivYM2612Interface iface; bool dacMode; int dacPeriod; @@ -60,7 +69,7 @@ class DivPlatformGenesis: public DivDispatch { unsigned char sampleBank; unsigned char lfoValue; - bool extMode; + bool extMode, useYMFM; bool ladder; short oldWrites[512]; @@ -70,6 +79,9 @@ class DivPlatformGenesis: public DivDispatch { int toFreq(int freq); friend void putDispatchChan(void*,int,int); + + void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); + void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); @@ -80,6 +92,7 @@ class DivPlatformGenesis: public DivDispatch { void tick(); void muteChannel(int ch, bool mute); bool isStereo(); + void setYMFM(bool use); bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); void toggleRegisterDump(bool enable); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a1cf64649..70045201d 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2753,6 +2753,11 @@ const char* arcadeCores[]={ "Nuked-OPM" }; +const char* ym2612Cores[]={ + "Nuked-OPN2", + "ymfm" +}; + #define SAMPLE_RATE_SELECTABLE(x) \ if (ImGui::Selectable(#x,settings.audioRate==x)) { \ settings.audioRate=x; \ @@ -2860,6 +2865,10 @@ void FurnaceGUI::drawSettings() { ImGui::SameLine(); ImGui::Combo("##ArcadeCore",&settings.arcadeCore,arcadeCores,2); + ImGui::Text("Genesis core"); + ImGui::SameLine(); + ImGui::Combo("##YM2612Core",&settings.ym2612Core,ym2612Cores,2); + ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Appearance")) { @@ -3041,6 +3050,7 @@ void FurnaceGUI::syncSettings() { settings.audioBufSize=e->getConfInt("audioBufSize",1024); settings.audioRate=e->getConfInt("audioRate",44100); settings.arcadeCore=e->getConfInt("arcadeCore",0); + settings.ym2612Core=e->getConfInt("ym2612Core",0); settings.mainFont=e->getConfInt("mainFont",0); settings.patFont=e->getConfInt("patFont",0); settings.mainFontPath=e->getConfString("mainFontPath",""); @@ -3071,6 +3081,7 @@ void FurnaceGUI::commitSettings() { e->setConf("audioBufSize",settings.audioBufSize); e->setConf("audioRate",settings.audioRate); e->setConf("arcadeCore",settings.arcadeCore); + e->setConf("ym2612Core",settings.ym2612Core); e->setConf("mainFont",settings.mainFont); e->setConf("patFont",settings.patFont); e->setConf("mainFontPath",settings.mainFontPath); diff --git a/src/gui/gui.h b/src/gui/gui.h index cac707abe..d4783bf61 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -196,6 +196,7 @@ class FurnaceGUI { int audioEngine; int audioQuality; int arcadeCore; + int ym2612Core; int mainFont; int patFont; int audioRate; @@ -223,6 +224,7 @@ class FurnaceGUI { audioEngine(DIV_AUDIO_SDL), audioQuality(0), arcadeCore(0), + ym2612Core(0), mainFont(0), patFont(0), audioRate(44100),