diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 83de1fa1..52ac6e57 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -593,6 +593,13 @@ void DivPlatformAY8910::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) immWrite(i.addr,i.val); } +void DivPlatformAY8910::setExtClockDiv(unsigned int eclk, unsigned char ediv) { + if (extMode) { + extClock=eclk; + extDiv=ediv; + } +} + void DivPlatformAY8910::setFlags(unsigned int flags) { if (extMode) { chipClock=extClock; diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index a1f35d1b..f67a2ad9 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -91,6 +91,7 @@ class DivPlatformAY8910: public DivDispatch { friend void putDispatchChan(void*,int,int); public: + void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8); void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index 97844656..9b838c19 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -26,16 +26,16 @@ class DivPlatformOPM: public DivPlatformFMBase { protected: - const unsigned char ADDR_MULT_DT=0x40; - const unsigned char ADDR_TL=0x60; - const unsigned char ADDR_RS_AR=0x80; - const unsigned char ADDR_AM_DR=0xa0; - const unsigned char ADDR_DT2_D2R=0xc0; - const unsigned char ADDR_SL_RR=0xe0; - const unsigned char ADDR_NOTE=0x28; - const unsigned char ADDR_KF=0x30; - const unsigned char ADDR_FMS_AMS=0x38; - const unsigned char ADDR_LR_FB_ALG=0x20; + const unsigned short ADDR_MULT_DT=0x40; + const unsigned short ADDR_TL=0x60; + const unsigned short ADDR_RS_AR=0x80; + const unsigned short ADDR_AM_DR=0xa0; + const unsigned short ADDR_DT2_D2R=0xc0; + const unsigned short ADDR_SL_RR=0xe0; + const unsigned short ADDR_NOTE=0x28; + const unsigned short ADDR_KF=0x30; + const unsigned short ADDR_FMS_AMS=0x38; + const unsigned short ADDR_LR_FB_ALG=0x20; const unsigned short opOffs[4]={ 0x00, 0x08, 0x10, 0x18 diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index 74e13219..0aaad16d 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -85,27 +85,27 @@ class DivPlatformOPN: public DivPlatformFMBase { protected: - const unsigned char ADDR_MULT_DT=0x30; - const unsigned char ADDR_TL=0x40; - const unsigned char ADDR_RS_AR=0x50; - const unsigned char ADDR_AM_DR=0x60; - const unsigned char ADDR_DT2_D2R=0x70; - const unsigned char ADDR_SL_RR=0x80; - const unsigned char ADDR_SSG=0x90; - const unsigned char ADDR_FREQ=0xa0; - const unsigned char ADDR_FREQH=0xa4; - const unsigned char ADDR_FB_ALG=0xb0; - const unsigned char ADDR_LRAF=0xb4; + const unsigned short ADDR_MULT_DT=0x30; + const unsigned short ADDR_TL=0x40; + const unsigned short ADDR_RS_AR=0x50; + const unsigned short ADDR_AM_DR=0x60; + const unsigned short ADDR_DT2_D2R=0x70; + const unsigned short ADDR_SL_RR=0x80; + const unsigned short ADDR_SSG=0x90; + const unsigned short ADDR_FREQ=0xa0; + const unsigned short ADDR_FREQH=0xa4; + const unsigned short ADDR_FB_ALG=0xb0; + const unsigned short ADDR_LRAF=0xb4; const unsigned short opOffs[4]={ 0x00, 0x04, 0x08, 0x0c }; double fmFreqBase; - double fmDivBase; - unsigned char ayDiv; + unsigned int fmDivBase; + unsigned int ayDiv; - DivPlatformOPN(double f=9440540.0, double d=72, unsigned char a=32): + DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32): DivPlatformFMBase(), fmFreqBase(f), fmDivBase(d), diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 7d2004f3..c46a992d 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -99,13 +99,6 @@ class DivPlatformGenesis: public DivPlatformOPN { Channel chan[10]; DivDispatchOscBuffer* oscBuf[10]; bool isMuted[10]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::deque writes; ym3438_t fm; ymfm::ym2612* fm_ymfm; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 35bb9c40..71e9b0bc 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -35,7 +35,7 @@ const char* regCheatSheetGG[]={ }; const char** DivPlatformSMS::getRegisterSheet() { - return isStereo()?regCheatSheetGG:regCheatSheetSN; + return stereo?regCheatSheetGG:regCheatSheetSN; } const char* DivPlatformSMS::getEffectName(unsigned char effect) { @@ -74,7 +74,7 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ o=YMPSG_GetOutput(&sn_nuked); if (o<-32768) o=-32768; if (o>32767) o=32767; - bufL[h]=o; + bufL[h]=bufR[h]=o; for (int i=0; i<4; i++) { if (isMuted[i]) { oscBuf[i]->data[oscBuf[i]->needle++]=0; @@ -86,13 +86,6 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ } void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t len) { - if (snBufLenwrite(w.val); writes.pop(); } - for (size_t h=0; hsound_stream_update(outs,1); for (int i=0; i<4; i++) { @@ -115,17 +108,6 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t } } } - if (stereo) { - for (size_t i=0; i>1)&1)<>1)&1)<<(i+4)); rWrite(1,lastPan); } } @@ -204,7 +186,7 @@ void DivPlatformSMS::tick(bool sysTick) { } for (int i=0; i<3; i++) { if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,64); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,toneDivider); if (chan[i].freq>1023) chan[i].freq=1023; if (chan[i].freq<8) chan[i].freq=1; //if (chan[i].actualNote>0x5d) chan[i].freq=0x01; @@ -263,7 +245,7 @@ void DivPlatformSMS::tick(bool sysTick) { } int DivPlatformSMS::dispatch(DivCommand c) { - int CHIP_DIVIDER=64; + int CHIP_DIVIDER=toneDivider; if (c.chan==3) CHIP_DIVIDER=noiseDivider; switch (c.cmd) { case DIV_CMD_NOTE_ON: @@ -340,11 +322,12 @@ int DivPlatformSMS::dispatch(DivCommand c) { updateSNMode=true; break; case DIV_CMD_PANNING: { - if (isStereo()) { + if (stereo) { + if (c.chan>3) c.chan=3; lastPan&=~(0x11<0) pan|=0x01; - if (c.value2>0) pan|=0x10; + if (c.value>0) pan|=0x10; + if (c.value2>0) pan|=0x01; if (pan==0) pan=0x11; lastPan|=pan<reset(); ay->getRegisterWrites().clear(); ay->flushWrites(); @@ -1013,7 +1017,8 @@ void DivPlatformYM2203::setSkipRegisterWrites(bool value) { } void DivPlatformYM2203::setFlags(unsigned int flags) { - switch (flags&0x3f) { + // Clock flags + switch (flags&0x1f) { default: case 0x00: chipClock=COLOR_NTSC; @@ -1034,10 +1039,36 @@ void DivPlatformYM2203::setFlags(unsigned int flags) { chipClock=3000000.0/2.0; break; } + // Prescaler flags + switch ((flags>>5)&0x3) { + default: + case 0x00: // /6 + prescale=0x2d; + fmFreqBase=4720270.0, + fmDivBase=36, + ayDiv=16; + break; + case 0x01: // /3 + prescale=0x2e; + fmFreqBase=4720270.0/2.0, + fmDivBase=18, + ayDiv=8; + break; + case 0x02: // /2 + prescale=0x2f; + fmFreqBase=4720270.0/3.0, + fmDivBase=12, + ayDiv=4; + break; + } rate=fm->sample_rate(chipClock); for (int i=0; i<6; i++) { oscBuf[i]->rate=rate; } + immWrite(0x2d,0xff); + immWrite(prescale,0xff); + ay->setExtClockDiv(chipClock,ayDiv); + ay->setFlags(16); } int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { @@ -1050,11 +1081,11 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned in } fm=new ymfm::ym2203(iface); fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); - setFlags(flags); // YM2149, 2MHz ay=new DivPlatformAY8910(true,chipClock,ayDiv); ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); + setFlags(flags); reset(); return 6; diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index 6d7bc420..d406e2f2 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -90,6 +90,7 @@ class DivPlatformYM2203: public DivPlatformOPN { unsigned char sampleBank; bool extMode; + unsigned char prescale; friend void putDispatchChan(void*,int,int); @@ -118,7 +119,8 @@ class DivPlatformYM2203: public DivPlatformOPN { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2203(): - DivPlatformOPN(4720270.0, 36, 16) {} + DivPlatformOPN(4720270.0, 36, 16), + prescale(0x2d) {} ~DivPlatformYM2203(); }; #endif diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index 46b8b0ad..733f0481 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -1325,6 +1325,10 @@ void DivPlatformYM2608::reset() { // enable 6 channel mode immWrite(0x29,0x80); + // set prescaler + immWrite(0x2d,0xff); + immWrite(prescale,0xff); + ay->reset(); ay->getRegisterWrites().clear(); ay->flushWrites(); @@ -1395,7 +1399,8 @@ void DivPlatformYM2608::renderSamples() { } void DivPlatformYM2608::setFlags(unsigned int flags) { - switch (flags&0x3f) { + // Clock flags + switch (flags&0x1f) { default: case 0x00: chipClock=8000000.0; @@ -1404,10 +1409,36 @@ void DivPlatformYM2608::setFlags(unsigned int flags) { chipClock=38400*13*16; // 31948800/4 break; } + // Prescaler flags + switch ((flags>>5)&0x3) { + default: + case 0x00: // /6 + prescale=0x2d; + fmFreqBase=9440540.0, + fmDivBase=72, + ayDiv=32; + break; + case 0x01: // /3 + prescale=0x2e; + fmFreqBase=9440540.0/2.0, + fmDivBase=36, + ayDiv=16; + break; + case 0x02: // /2 + prescale=0x2f; + fmFreqBase=9440540.0/3.0, + fmDivBase=24, + ayDiv=8; + break; + } rate=fm->sample_rate(chipClock); for (int i=0; i<16; i++) { oscBuf[i]->rate=rate; } + immWrite(0x2d,0xff); + immWrite(prescale,0xff); + ay->setExtClockDiv(chipClock,ayDiv); + ay->setFlags(16); } int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { @@ -1423,11 +1454,12 @@ int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned in oscBuf[i]=new DivDispatchOscBuffer; } fm=new ymfm::ym2608(iface); - setFlags(flags); + fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); // YM2149, 2MHz - ay=new DivPlatformAY8910(true,chipClock,32); + ay=new DivPlatformAY8910(true,chipClock,ayDiv); ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); + setFlags(flags); reset(); return 16; } diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index c1f43f4d..ac38a8c0 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -101,8 +101,7 @@ class DivPlatformYM2608: public DivPlatformOPN { unsigned char writeRSSOff, writeRSSOn; bool extMode; - double fmFreqBase; - unsigned char ayDiv; + unsigned char prescale; double NOTE_OPNB(int ch, int note); double NOTE_ADPCMB(int note); @@ -137,7 +136,8 @@ class DivPlatformYM2608: public DivPlatformOPN { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2608(): - DivPlatformOPN(9440540.0, 72, 32) {} + DivPlatformOPN(9440540.0, 72, 32), + prescale(0x2d) {} ~DivPlatformYM2608(); }; #endif diff --git a/src/engine/song.h b/src/engine/song.h index 6bbb00cf..df622d86 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -357,7 +357,7 @@ struct DivSong { // - 3: 3MHz // - 4: 3.9936MHz (PC-88, PC-98) // - 5: 1.5MHz - // - bit 5-6: output rate (TODO) + // - bit 5-6: output rate // - 0: FM: clock / 72, SSG: clock / 16 // - 1: FM: clock / 36, SSG: clock / 8 // - 2: FM: clock / 24, SSG: clock / 4 @@ -365,7 +365,7 @@ struct DivSong { // - bit 0-4: clock rate // - 0: 8MHz // - 1: 7.987MHz (PC-88, PC-98) - // - bit 5-6: output rate (TODO) + // - bit 5-6: output rate // - 0: FM: clock / 144, SSG: clock / 32 // - 1: FM: clock / 72, SSG: clock / 16 // - 2: FM: clock / 48, SSG: clock / 8 diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index d0e63c11..5056de74 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -56,13 +56,13 @@ void FurnaceGUI::initSystemPresets() { )); cat.systems.push_back(FurnaceGUISysDef( "Yamaha YM2608 (OPNA)", { - DIV_SYSTEM_PC98, 64, 0, 3, + DIV_SYSTEM_PC98, 64, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Yamaha YM2608 (extended channel 3)", { - DIV_SYSTEM_PC98_EXT, 64, 0, 3, + DIV_SYSTEM_PC98_EXT, 64, 0, 0, 0 } )); @@ -258,6 +258,18 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "TI SN94624", { + DIV_SYSTEM_SMS, 64, 0, 0x80, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "TI SN76494", { + DIV_SYSTEM_SMS, 64, 0, 0x84, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "AY-3-8910", { DIV_SYSTEM_AY8910, 64, 0, 0, diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 02d06db3..21fef35d 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -397,8 +397,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("1.5MHz",(flags&31)==5)) { copyOfFlags=(flags&(~31))|5; } - /* - ImGui::Text("Output rate: (DOES NOT WORK YET!)"); + ImGui::Text("Output rate:"); if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",(flags&96)==0)) { copyOfFlags=(flags&(~96))|0; } @@ -408,7 +407,6 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("FM: clock / 24, SSG: clock / 4",(flags&96)==64)) { copyOfFlags=(flags&(~96))|64; } - */ break; } case DIV_SYSTEM_PC98: @@ -420,8 +418,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("7.987MHz (PC-88/PC-98)",(flags&31)==1)) { copyOfFlags=(flags&(~31))|1; } - /* - ImGui::Text("Output rate: (DOES NOT WORK YET!)"); + ImGui::Text("Output rate:"); if (ImGui::RadioButton("FM: clock / 144, SSG: clock / 32",(flags&96)==0)) { copyOfFlags=(flags&(~96))|0; } @@ -431,7 +428,6 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("FM: clock / 48, SSG: clock / 8",(flags&96)==64)) { copyOfFlags=(flags&(~96))|64; } - */ break; } case DIV_SYSTEM_RF5C68: {