Genesis: add ability to use ymfm instead of Nuked

This commit is contained in:
tildearrow 2022-02-02 23:08:45 -05:00
parent 2fdca5a98f
commit ccfe3bdd97
6 changed files with 133 additions and 3 deletions

View file

@ -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;

View file

@ -5835,6 +5835,8 @@ void DivEngine::setConsoleMode(bool enable) {
void DivEngine::switchMaster() {
deinitAudioBackend();
quitDispatch();
initDispatch();
if (initAudioBackend()) {
for (int i=0; i<song.systemLen; i++) {
disCont[i].setRates(got.rate);

View file

@ -11,7 +11,7 @@ static unsigned char konOffs[6]={
#define CHIP_FREQBASE 9440540
void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t len) {
void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
static short o[2];
static int os[2];
@ -85,6 +85,87 @@ void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t
}
}
void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
for (size_t h=start; h<start+len; h++) {
if (dacMode && dacSample!=-1) {
dacPeriod-=24;
if (dacPeriod<1) {
DivSample* s=parent->song.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();
}

View file

@ -3,9 +3,14 @@
#include "../dispatch.h"
#include <queue>
#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);

View file

@ -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);

View file

@ -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),